Mar*_*cci 144 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; }
...
}
Run Code Online (Sandbox Code Playgroud)
当我尝试向该表添加新行时,我收到错误:
System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'.
Run Code Online (Sandbox Code Playgroud)
只有从其他类继承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...
Run Code Online (Sandbox Code Playgroud)
有任何建议或想法可以解决这个问题的根源吗?我尝试重命名表,主键和其他一些东西,但没有任何作用.
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
Run Code Online (Sandbox Code Playgroud)
Mar*_*cci 305
事实证明,Entity Framework将假定从映射到数据库中的表的POCO类继承的任何类都需要Discriminator列,即使派生类不会保存到DB.
解决方案非常简单,您只需要添加[NotMapped]为派生类的属性.
例:
class Person
{
public string Name { get; set; }
}
[NotMapped]
class PersonViewModel : Person
{
public bool UpdateProfile { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在,即使将Person类映射到数据库上的Person表,也不会创建"Discriminator"列,因为派生类具有[NotMapped].
作为附加提示,您可以使用[NotMapped]不希望映射到DB上的字段的属性.
Wal*_*osz 42
这是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);
}
Run Code Online (Sandbox Code Playgroud)
我刚刚遇到这个问题,我的问题是由两个实体同时System.ComponentModel.DataAnnotations.Schema.TableAttribute引用同一个表引起的.
例如:
[Table("foo")]
public class foo
{
// some stuff here
}
[Table("foo")]
public class fooExtended
{
// more stuff here
}
Run Code Online (Sandbox Code Playgroud)
将第二个foo改为foo_extended固定这个,我现在使用Table Per Type(TPT)
Another scenario where this occurs is when you have a base class and one or more subclasses, where at least one of the subclasses introduce extra properties:
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; }
}
Run Code Online (Sandbox Code Playgroud)
If these are mapped in the DbContext like below, the "'Invalid column name 'Discriminator'" error occurs when any type based on Folder base type is accessed:
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");
}
Run Code Online (Sandbox Code Playgroud)
I found that to fix the issue, we extract the props of Folder to a base class (which is not mapped in OnModelCreating()) like so - OnModelCreating should be unchanged:
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; }
}
Run Code Online (Sandbox Code Playgroud)
This eliminates the issue, but I don't know why!
我遇到了类似的问题,条件不完全相同,然后我看到了这篇文章。希望它可以帮助某人。显然,我正在使用我的一个 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;}
}
Run Code Online (Sandbox Code Playgroud)