【问题标题】:EF Code First "Invalid column name 'Discriminator'" but no inheritanceEF Code First“无效的列名'鉴别器'”但没有继承
【发布时间】:2011-09-27 02:11:16
【问题描述】:

我的数据库中有一个名为 SEntries 的表(请参阅下面的 CREATE TABLE 语句)。它有一个主键,几个外键,没有什么特别之处。我的数据库中有许多与该表类似的表,但由于某种原因,该表在 EF 代理类上以“鉴别器”列结束。

这是在 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

【问题讨论】:

  • 对于下一个会花一些时间试图弄清楚这一点的人来说,发生的事情是在代码的另一个地方,我有一个继承自 SEntry 的类,即使它不是一个类那将永远存储在数据库中。所以我需要做的就是添加 [NotMapped] 作为该类的属性!
  • 如果我没有将 [NotMapped] 放在 Identitymodel.cs 中的 ApplicationUser 类上,我会收到此错误

标签: entity-framework ef-code-first


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,但条件不完全相同,然后我看到了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;}
    
        }
    

    【讨论】:

      【解决方案3】:

      事实证明,实体框架将假定任何继承自 POCO 类的类(该类映射到数据库上的表)都需要一个鉴别器列,即使派生类不会保存到数据库中也是如此。

      解决方法很简单,只需将[NotMapped]添加为派生类的属性即可。

      例子:

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

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

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

      【讨论】:

      • 好的,所以我的生命有 3 个小时了;(但 tyvm 都一样。我还应该添加以明确...派生类可以一直在角落而不是在以任何方式使用 re:持久性和 EF 仍会尝试将它们吸引进来......非常令人困惑。
      • 如果没有找到[NotMapped],请在“Assembly Framework”项目中添加对:“System.ComponentModel.DataAnnotations”的引用。
      • 使用 System.ComponentModel.DataAnnotations.Schema;
      • 但在我的情况下,我继承了一个类来使用子类在 db 表中添加列。所以我不能使用这个未映射的属性来让它工作。在这种情况下,我的解决方案应该是什么?
      • 在我的情况下,添加未映射并没有帮助。我没有在所有视图模型中映射
      【解决方案4】:

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

      1. 我更改了数据库中表的列名
      2. (我没有在 Edmx 中使用Update Model from database)我手动重命名了属性名称以匹配数据库架构中的更改
      3. 我进行了一些重构,将类中的属性名称更改为与 Edmx 中的数据库架构和模型相同

      虽然这一切,我得到了这个错误

      所以what to do

      1. 我从 Edmx 中删除了模型
      2. 右击和Update Model from database

      这将重新生成模型和实体框架will give you this error

      希望对你有帮助

      【讨论】:

        【解决方案5】:

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

        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 基类型的类型时,会出现“'Invalid column name '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 的 props 提取到一个基类(未映射到 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; }
        }
        

        这样就解决了这个问题,但我不知道为什么!

        【讨论】:

        • 谢谢,肉斧——这花了我一两个小时,但最糟糕的是,我以前一定遇到过这个问题,因为我已经设置了所有基类。一年后笨蛋我说,“嘿,看起来这个基类没有做任何事情。我想我会删除它......”我生命中有一个小时我永远不会回来。为什么需要这样做?我希望我能更好地理解 EF。
        【解决方案6】:

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

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

        是的,第二个地图应该是地图。 我花了半天时间才弄明白!

        【讨论】:

          【解决方案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 为我解决了这个问题,我现在正在使用 Table Per Type (TPT)

          【讨论】:

          • 这对我不起作用:The entity types 'AtencionMedica' and 'AtencionMedicaAP' cannot share table 'AtencionMedicas' because they are not in the same type hierarchy
          • 谢谢,帮助了我,使用流畅的 API 遇到了同样的问题:var entity = modelBuilder.Entity&lt;EntityObject&gt;().ToTable("ENTITY_TABLE"),然后使用相同的 EntityObject 或相同的 ENTITY_TABLE 的另一行。
          【解决方案8】:

          这是 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]属性不是更好吗?
          • @Keith 我的回答是如何使用 Fluent API 忽略列,它不使用 [NotMapped] 等属性
          • 您遇到相反的问题(即从 POCO 类继承的 EF 绑定类),这是我可以让它工作而不用 EF 污染数据模型的唯一方法。
          猜你喜欢
          • 1970-01-01
          • 2012-09-11
          • 1970-01-01
          • 2012-12-08
          • 2013-12-04
          • 1970-01-01
          • 2011-03-26
          • 1970-01-01
          相关资源
          最近更新 更多