EF代码第一个“无效的列名'Discriminator'”,但没有继承


154

我的数据库中有一个名为SEntries的表(请参见下面的CREATE TABLE语句)。它有一个主键,几个外键,对此没什么特别的。我的数据库中有许多与该表相似的表,但是由于某种原因,该表以EF Proxy Class的“ 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继承的类,即使它不是一个可以存储在数据库中的类也是如此。 。因此,我要做的就是添加[NotMapped]作为该类的属性!
Marcelo Calbucci 2011年

如果我没有在Identitymodel.cs中的ApplicationUser类上放置[NotMapped],则会收到此错误消息
Heemanshu Bhalla

Answers:


319

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

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

例:

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

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

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

另外,您可以使用[NotMapped]不想映射到数据库中字段的属性。


7
好的,所以我一生要花3个小时;(但是tyvm都一样。仍然会尝试将它们吸引到……非常令人困惑
。– rism

12
如果找不到[NotMapped],请从“组装框架”向项目添加对以下项的引用:“ System.ComponentModel.DataAnnotations”。
XandrUu 2014年

9
使用System.ComponentModel.DataAnnotations.Schema;
ygaradon 2014年

6
但就我而言,我继承了一个使用子类在db表中添加列的类。因此,我无法使用此notmapped属性来使其正常工作。在这种情况下,我该怎么办?
sohaib

4
就我而言,添加未映射没有帮助。我尚未在所有视图模型中进行映射
Heemanshu Bhalla

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
@Keith我的答案是如何使用Fluent API忽略列,该列不使用[NotMapped]等属性
Walter Stabosz

1
Keith这是我认为的首选答案,因为现在正朝着代码优先的标准迈进,而Walter的答案更适合这种情况,尤其是在最终使用数据库迁移的情况下。
塔希尔·哈立德

在您遇到相反问题的情况下(即从POCO类继承的EF绑定类),这是我可以在不使用EF污染数据模型的情况下工作的唯一方法。
Paul Michaels '18

8

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

例如:

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

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

改变第二个从foofoo_extended固定这对我来说,现在我使用的表每个类型(TPT)


这对我不起作用:The entity types 'AtencionMedica' and 'AtencionMedicaAP' cannot share table 'AtencionMedicas' because they are not in the same type hierarchy
James Reategui 2015年

谢谢,帮助我,使用fluent API遇到了相同的问题:var entity = modelBuilder.Entity<EntityObject>().ToTable("ENTITY_TABLE"),然后另一行使用了same EntityObject或same ENTITY_TABLE
Mathijs Flietstra

4

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

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

我发现要解决此问题,我们像这样将我们的props提取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; }
}

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


谢谢,肉轴-花了我一两个小时,但最糟糕的是,我之前一定有这个问题,因为我已经设置了所有的基类。一年后让我呆呆的说:“嘿,看来这个基类没有做任何事情。我想我会把它删除……”而且我一生中有一个小时无法回去。为什么需要这个?我希望我对EF有更好的了解。
Wellspring

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

是的,第二个Map <Team>应该是Map <Story>。我花了半天时间才弄清楚!


2

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

例:

//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,但对于后代...如果您具有自引用导航属性(相同类型的“父级”或“子级”),也会发生(.NET Core 2.1),但是Id属性名称不是EF期望。也就是说,我在类上WorkflowBase有一个名为的“ Id”属性,并且它具有一系列相关的子步骤,它们的类型也都是WorkflowBase,并且一直尝试将它们与不存在的“ WorkflowBaseId”(名称i假设它更喜欢作为自然/常规默认值)。我必须使用HasMany(),明确配置它WithOne(),并HasConstraintName()告诉它如何遍历。但是我花了几个小时认为问题出在“本地”映射对象的主键上,我试图修复许多不同的方法,但是这种方法可能一直有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.