EF Code First「無効な列名 'Discriminator'」ですが継承はありません


154

SEntriesというデータベースにテーブルがあります(CREATE TABLEステートメントの下を参照)。主キー、いくつかの外部キーがあり、特別なことは何もありません。私のデータベースには、そのテーブルに似たテーブルがたくさんありますが、何らかの理由で、このテーブルはEFプロキシクラスの「Discriminator」列で終わっていました。

これは、クラスがC#で宣言される方法です。

public class SEntry
{
    public long SEntryId { get; set; }

    public long OriginatorId { get; set; }
    public DateTime DatePosted { get; set; }
    public string Message { get; set; }
    public byte DataEntrySource { get; set; }
    public string SourceLink { get; set; }
    public int SourceAppId { get; set; }
    public int? LocationId { get; set; }
    public long? ActivityId { get; set; }
    public short OriginatorObjectTypeId { get; set; }
}

public class EMData : DbContext
{
    public DbSet<SEntry> SEntries { get; set; }
            ...
    }

そのテーブルに新しい行を追加しようとすると、エラーが発生します。

System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'.

この問題は、C#クラスを別のクラスから継承しているが、SEntryが何からも継承していない場合にのみ発生します(上記を参照)。

さらに、SEntriesプロパティのEMDataインスタンスの上にマウスを置くと、デバッガーのツールチップが表示され、次のように表示されます。

base {System.Data.Entity.Infrastructure.DbQuery<EM.SEntry>} = {SELECT 
[Extent1].[Discriminator] AS [Discriminator], 
[Extent1].[SEntryId] AS [SEntryId], 
[Extent1].[OriginatorId] AS [OriginatorId], 
[Extent1].[DatePosted] AS [DatePosted], 
[Extent1].[Message] AS [Message], 
[Extent1].[DataEntrySource] AS [DataE...

この問題の根底に到達するための提案やアイデアはありますか?テーブル、主キー、その他いくつかの名前を変更しようとしましたが、何も機能しません。

SQLテーブル:

CREATE TABLE [dbo].[SEntries](
[SEntryId] [bigint] IDENTITY(1125899906842624,1) NOT NULL,
[OriginatorId] [bigint] NOT NULL,
[DatePosted] [datetime] NOT NULL,
[Message] [nvarchar](500) NOT NULL,
[DataEntrySource] [tinyint] NOT NULL,
[SourceLink] [nvarchar](100) NULL,
[SourceAppId] [int] NOT NULL,
[LocationId] [int] NULL,
[ActivityId] [bigint] NULL,
[OriginatorObjectTypeId] [smallint] NOT NULL,
CONSTRAINT [PK_SEntries] PRIMARY KEY CLUSTERED 
(
[SEntryId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,       ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[SEntries]  WITH CHECK ADD  CONSTRAINT [FK_SEntries_ObjectTypes] FOREIGN KEY([OriginatorObjectTypeId])
REFERENCES [dbo].[ObjectTypes] ([ObjectTypeId])
GO

ALTER TABLE [dbo].[SEntries] CHECK CONSTRAINT [FK_SEntries_ObjectTypes]
GO

ALTER TABLE [dbo].[SEntries]  WITH CHECK ADD  CONSTRAINT [FK_SEntries_SourceApps] FOREIGN KEY([SourceAppId])
REFERENCES [dbo].[SourceApps] ([SourceAppId])
GO

ALTER TABLE [dbo].[SEntries] CHECK CONSTRAINT [FK_SEntries_SourceApps]
GO

16
これを理解するためにしばらく時間を費やす次の人のために、何が起こったかというと、コードの別の場所で、SEntryから継承したクラスがありましたが、これはDBに保存されるクラスではありません。そのため、クラスの属性として[NotMapped]を追加するだけで済みました。
Marcelo Calbucci、2011

IdentityModel.csのApplicationUserクラスに[NotMapped]を配置しないと、このエラーが発生します
Heemanshu Bhalla '21

回答:


319

Entity Frameworkは、派生クラスがDBに保存されない場合でも、データベースのテーブルにマップされたPOCOクラスから継承するクラスにはDiscriminator列が必要であると想定していることがわかります。

解決策は非常に簡単[NotMapped]で、派生クラスの属性として追加するだけです。

例:

class Person
{
    public string Name { get; set; }
}

[NotMapped]
class PersonViewModel : Person
{
    public bool UpdateProfile { get; set; }
}

これで、PersonクラスをデータベースのPersonテーブルにマップしても、派生クラスにはがあるため、「Discriminator」列は作成されません[NotMapped]

追加のヒントとして、[NotMapped]DBのフィールドにマップしたくないプロパティを使用できます。


7
わかりましたので、私の人生の3時間になります;(しかし、tyvmはすべて同じです。明確にするために、追加する必要もあります...派生クラスは、隅々まで使用できます。まだで...非常に混乱して試してみて描画します。
RISM

12
[NotMapped]が見つからない場合は、「System.ComponentModel.DataAnnotations」への参照を「Assembly Framework」からプロジェクトに追加してください。
XandrUu 2014年

9
System.ComponentModel.DataAnnotations.Schemaを使用します。
ygaradon 2014

6
しかし、私の場合、子クラスを使用してdbテーブルに列を追加するクラスを継承しました。したがって、このnotmapped属性を使用して機能させることはできません。この場合、私の解決策は何ですか?
sohaib javed

4
私の場合、マップされていないものを追加しても役に立ちませんでした。すべてのビューモデルにマッピングしていません
Heemanshu Bhalla '21

44

Fluent API構文は次のとおりです。

http://blogs.msdn.com/b/adonet/archive/2010/12/06/ef-feature-ctp5-fluent-api-samples.aspx

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName { 
        get {
            return this.FirstName + " " + this.LastName;
        }
    }
}

class PersonViewModel : Person
{
    public bool UpdateProfile { get; set; }
}


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // ignore a type that is not mapped to a database table
    modelBuilder.Ignore<PersonViewModel>();

    // ignore a property that is not mapped to a database column
    modelBuilder.Entity<Person>()
        .Ignore(p => p.FullName);

}

[NotMapped]属性を追加するだけの方がいいのではないでしょうか。
キース

1
@キース私の答えは、[NotMapped]などの属性を使用しないFluent APIを使用して列を無視する方法です
Walter Stabosz

1
キースこれは私がコードファーストの標準に向かっているので、私が思う好ましい答えであり、特にdbマイグレーションを使用することになる場合、ウォルターの答えはこのシナリオにより適しています。
Tahir Khalid

反対の問題(つまり、POCOクラスから継承するEFバインドクラス)がある場合、これは、EFでデータモデルを汚染せずに動作させる唯一の方法でした。
ポールマイケルズ

8

私はこれに遭遇しましたが、私の問題は両方ともSystem.ComponentModel.DataAnnotations.Schema.TableAttribute同じテーブルを参照している2つのエンティティがあるために発生しました。

例えば:

[Table("foo")]
public class foo
{
    // some stuff here
}

[Table("foo")]
public class fooExtended
{
    // more stuff here
}

から2番目のものを変更する foofoo_extendedこれを修正し、Table Per Type(TPT)を使用しています


これは私にはうまくThe entity types 'AtencionMedica' and 'AtencionMedicaAP' cannot share table 'AtencionMedicas' because they are not in the same type hierarchy
いき

ありがとう、私を助けて、Fluent APIを使用して同じ問題が発生しました。var entity = modelBuilder.Entity<EntityObject>().ToTable("ENTITY_TABLE")次に、同じEntityObjectまたは同じを使用する別の行がありましたENTITY_TABLE
Mathijs Flietstra 2017年

4

これが発生する別のシナリオは、基本クラスと1つ以上のサブクラスがあり、少なくとも1つのサブクラスが追加のプロパティを導入する場合です。

class Folder {
  [key]
  public string Id { get; set; }

  public string Name { get; set; }
}

// Adds no props, but comes from a different view in the db to Folder:
class SomeKindOfFolder: Folder {
}

// Adds some props, but comes from a different view in the db to Folder:
class AnotherKindOfFolder: Folder {
  public string FolderAttributes { get; set; }
}

これらがDbContext以下のようにマップされている場合、基本型に基づくFolder型にアクセスすると、「 '無効な列名' Discriminator '」エラーが発生します。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<Folder>().ToTable("All_Folders");
  modelBuilder.Entity<SomeKindOfFolder>().ToTable("Some_Kind_Of_Folders");
  modelBuilder.Entity<AnotherKindOfFolder>().ToTable("Another_Kind_Of_Folders");
}

問題を修正するために、のプロップをFolder基本クラス(にマッピングされていないOnModelCreating())に抽出しOnModelCreatingます。変更しないでください。

class FolderBase {
  [key]
  public string Id { get; set; }

  public string Name { get; set; }
}

class Folder: FolderBase {
}

class SomeKindOfFolder: FolderBase {
}

class AnotherKindOfFolder: FolderBase {
  public string FolderAttributes { get; set; }
}

これで問題は解決しましたが、理由はわかりません!


おかげで、meataxe-1時間か2時間かかったが、最悪の部分は、以前にこの問題があったに違いない。なぜなら、基本クラスをすべてセットアップしていたからだ。1年後の私をよそよそしく言って、「ねえ、この基本クラスは何もしていないようです。私はそれを削除するだけだと思います...」そして、私は二度と戻らない人生の1時間を過ごしました。なぜこれが必要なのですか?EFをもっとよく理解したいです。
Wellspring

2

別の状況でエラーが発生しました。問題と解決策を次に示します。

LevledItemという名前の同じ基本クラスから派生した2つのクラスがあります。

public partial class Team : LeveledItem
{
   //Everything is ok here!
}
public partial class Story : LeveledItem
{
   //Everything is ok here!
}

しかし、それらのDbContextで、いくつかのコードをコピーしましたが、クラス名の1つを変更するのを忘れていました。

public class MFCTeamDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Other codes here
        modelBuilder.Entity<LeveledItem>()
            .Map<Team>(m => m.Requires("Type").HasValue(ItemType.Team));
    }

public class ProductBacklogDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Other codes here
        modelBuilder.Entity<LeveledItem>()
            .Map<Team>(m => m.Requires("Type").HasValue(ItemType.Story));
    }

はい、2番目のMap <Team>はMap <Story>である必要があります。そして、それを理解するのに半日かかりました!


2

私は同様の問題を抱えていましたが、まったく同じ条件ではなく、この投稿を見ました。それが誰かを助けることを願っています。どうやら私は自分のEFエンティティモデルの1つを、dbcontextでdbセットとして指定されていないタイプの基本クラスを使用していたようです。この問題を修正するには、2つの型に共通のすべてのプロパティを持ち、2つの型の間で新しい基本クラスから継承する基本クラスを作成する必要がありました。

例:

//Bad Flow
    //class defined in dbcontext as a dbset
    public class Customer{ 
       public int Id {get; set;}
       public string Name {get; set;}
    }

    //class not defined in dbcontext as a dbset
    public class DuplicateCustomer:Customer{ 
       public object DuplicateId {get; set;}
    }


    //Good/Correct flow*
    //Common base class
    public class CustomerBase{ 
       public int Id {get; set;}
       public string Name {get; set;}
    }

    //entity model referenced in dbcontext as a dbset
    public class Customer: CustomerBase{

    }

    //entity model not referenced in dbcontext as a dbset
    public class DuplicateCustomer:CustomerBase{

       public object DuplicateId {get; set;}

    }

1

このエラーは私が次のことをしたために発生します

  1. データベースのテーブルの列名を変更しました
  2. (私は使用しませんでした Update Model from database Edmxして)データベーススキーマの変更に合わせてプロパティ名を手動で変更しました
  3. Edmxのデータベーススキーマおよびモデルと同じになるようにクラスのプロパティの名前を変更するために、いくつかのリファクタリングを行いました

これはすべてですが、このエラーが発生しました

そう what to do

  1. Edmxからモデルを削除しました
  2. 右クリックして Update Model from database

これによりモデルが再生成され、エンティティフレームワークwill give you this error

これがお役に立てば幸い


1

古いQですが、後世のために...自己参照ナビゲーションプロパティ(同じタイプの「親」または「子」)があるが、Idプロパティ名がそうでない場合にも発生します(.NET Core 2.1) EFは期待しています。つまり、私はと呼ばれる自分のクラスに「Id」プロパティWorkflowBaseがあり、それにはタイプWorkflowBaseである関連する子ステップの配列があり、存在しない「WorkflowBaseId」(名前iそれが自然/慣習的なデフォルトとして好むと仮定してください)。私は明示的に使用してそれを設定しなければならなかったHasMany()WithOne()HasConstraintName()どのように横断するためにそれを伝えるために。しかし、問題はオブジェクトの主キーを「ローカルに」マッピングすることに問題があると考えて数時間を費やしました。これは、さまざまな方法を修正しようとしましたが、おそらく常に機能していました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.