EF Code First“无效的列名'Discriminator'”但没有继承

时间:2011-07-01 22:51:41

标签: entity-framework ef-code-first

我的数据库中有一个名为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

8 个答案:

答案 0 :(得分:298)

事实证明,Entity Framework将假定从映射到数据库中的表的POCO类继承的任何类都需要Discriminator列,即使派生类不会保存到数据库中。

解决方案非常简单,您只需添加[NotMapped]作为派生类的属性。

示例:

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

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

现在,即使将Person类映射到数据库上的Person表,也不会创建“Discriminator”列,因为派生类具有[NotMapped]

作为附加提示,您可以将[NotMapped]用于您不想映射到数据库字段的属性。

答案 1 :(得分:41)

以下是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);

}

答案 2 :(得分:7)

我刚刚遇到这个问题,我的问题是由两个实体同时引用同一个表System.ComponentModel.DataAnnotations.Schema.TableAttribute引起的。

例如:

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

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

将第二个从foo更改为foo_extended为我解决此问题,我现在正在使用每种类型的表格(TPT)

答案 3 :(得分:3)

发生这种情况的另一种情况是,当你有一个基类和一个或多个子类时,其中至少有一个子类引入了额外的属性:

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基类型的任何类型时,会出现“'无效列名'判别器'”错误:

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应该保持不变:< / p>

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; }
}

这消除了这个问题,但我不知道为什么!

答案 4 :(得分:2)

我在另一种情况下得到错误,这是问题和解决方案:

我有2个派生自同一个名为LevledItem的基类:

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

但在他们的DbContext中,我复制了一些代码,但忘记更改其中一个类名:

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));
    }

是的,第二张地图&lt;团队及GT;应该是Map&lt;故事取代。 我花了半天时间才想出来!

答案 5 :(得分:1)

这个错误发生在我身上,因为我做了以下

  1. 我更改了数据库中表格的列名
  2. (我没有在Edmx中使用Update Model from database)我手动重命名属性名称以匹配数据库架构中的更改
  3. 我做了一些重构,将类中属性的名称更改为与Edmx中的数据库模式和模型相同
  4. 尽管如此,我收到了这个错误

    所以what to do

    1. 我从Edmx
    2. 删除了模型
    3. 右键单击并Update Model from database
    4. 这将重新生成模型,实体框架will give you this error

      希望这能帮到你

答案 6 :(得分:1)

我遇到了类似的问题,条件并不完全相同,然后我看到了this post。希望它可以帮助某人。显然,我使用的是我的EF实体模型之一,该类的基类未在dbcontext中指定为数据库集。要解决此问题,我必须创建一个具有两种类型共有的所有属性的基类,并从这两种类型中的新基类继承。

示例:

//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;}

    }

答案 7 :(得分:0)

旧Q,但是对于后代来说,如果您具有自引用导航属性(相同类型的“父”或“子”),但Id属性名称不是,也将发生(.NET Core 2.1)这不是EF的期望。也就是说,我在我的类上有一个名为WorkflowBase的“ Id”属性,它具有一系列相关的子步骤,这些子步骤的类型也为WorkflowBase,并且它一直尝试将它们与一个不存在的“ WorkflowBaseId”(我认为它更喜欢使用自然/常规默认名称)。我必须使用HasMany()WithOne()HasConstraintName()对其进行显式配置,以告诉它如何遍历。但是我花了几个小时认为问题出在“本地”映射对象的主键上,我试图修复一堆不同的方法,但是这种方法可能一直有效。