[英]Entity Framework 5 - Enum based Discriminator for derived classes
我有以下內容(為清楚起見而縮寫) - 一個枚舉,一個帶有該枚舉的基類,以及兩個將枚舉設置為特定值的派生類。
public enum MyEnum
{
Value1, Value2
}
public class MyBaseClass
{
public MyEnum { get; protected set; }
}
public class DerivedOne: MyBaseClass
{
public DerivedOne { MyEnum = MyEnum.Value1; }
}
public class DerivedTwo: MyBaseClass
{
public DerivedTwo { MyEnum = MyEnum.Value2; }
}
我想要做的是讓實體框架 5 自動區分 DerivedOne 和 DerivedTwo,並使用基於 MyEnum 值的 discriminator 。 我應該能夠這樣做,因為按照慣例,每個 MyEnum == MyEnum.Value1 代表 DerivedOne,而 MyEnum == MyEnum.Value2 代表 DerivedTwo。
我在我的 DbContext 中試過這個:
public class MyDbContext : DbContext
{
DbSet<MyBaseClass> MyBaseClass { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyBaseClass>()
.Map<DerivedOne>(m => m.Requires(x => x.MyEnum == MyEnum.Value1));
base.OnModelCreating(modelBuilder);
}
}
但是,這會引發以下 InvalidOperationException:
表達式 'x => (Convert(x.MyEnum) == 0)' 不是有效的屬性表達式。 表達式應該代表一個屬性 (...)
編輯:我相信我使用這個可以走得更遠:
modelBuilder.Entity<MyBaseClass>().Map<DerivedOne>(m => m.Requires("MyEnum")
.HasValue((Int32)MyEnum.Value1));
現在我得到這個 EntityCommandCompilationException:
映射從第 (...) 行開始的片段問題 映射條件成員 'MyBaseClass.MyEnum' 的條件不是 'IsNull=False'。 刪除 MyBaseClass.MyEnum 上的條件或將其從映射中刪除。
關於我如何解決這個問題的任何提示? 謝謝!
據我所知,你不能那樣做。 做顯式Requires
指定鑒別器只是給它一個name
- 而不是將它連接到您的財產。
據我所知,這總是會導致您所描述的錯誤(稍后)。 如果你想指定鑒別器,它必須是“自動”的(至少我從來沒有設法這樣定義它)
但你真的不需要那個。 “枚舉”和鑒別器built into
您返回的類型中——基於鑒別器值,EF/CF 正在構建“Base”或“DerivedOne”或“DerivedTwo”。
因此,要實現您想要的功能,您可以執行以下操作...
public class MyBaseClass
{
[NotMapped()]
public virtual MyEnum MyEnum { get { return MyEnum.Base; } }
}
public class DerivedOne: MyBaseClass
{
public string OneProp { get; set; }
public override MyEnum MyEnum { get { return MyEnum.One; } }
}
public class DerivedTwo: MyBaseClass
{
public string TwoProp { get; set; }
public override MyEnum MyEnum { get { return MyEnum.Two; } }
}
或者只是使用is
代替(如果它適合你)......
if (entity is MyBaseClass) // instead of enum
或查詢...
.OfType<MyBaseClass>();
從 EF 6.1 開始,我實際上能夠使用枚舉作為鑒別器列,盡管有這個錯誤:
附加信息:“MyEnum”類型的值不能用作類型鑒別器值。 支持的類型包括字節、有符號字節、bool、int16、int32、int64 和 string。
我所要做的就是這樣:
public enum MyEnum
{
Value1, Value2
}
public class MyBaseClass
{
public MyEnum { get; protected set; }
}
public class DerivedOne: MyBaseClass
{
public DerivedOne()
{
MyEnum = MyEnum.Value1;
}
}
public class DerivedTwo: MyBaseClass
{
public DerivedTwo()
{
MyEnum = MyEnum.Value2;
}
}
public class MyDbContext : DbContext
{
DbSet<MyBaseClass> MyBaseClass { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations
.Add(new DerivedOneConfiguration())
.Add(new DerivedTwoConfiguration());
}
}
public class DerivedOneConfiguration : EntityTypeConfiguration<DerivedOne>
{
public DerivedOneConfiguration()
{
Map<DerivedOne>(_ => _.Requires("MyEnum").HasValue((int)MyEnum.Value1).IsRequired());
}
}
public class DerivedTwoConfiguration : EntityTypeConfiguration<DerivedTwo>
{
public DerivedTwoConfiguration()
{
Map<DerivedTwo>(_ => _.Requires("MyEnum").HasValue((int)MyEnum.Value2).IsRequired());
}
}
所以秘密是使用(int)MyEnum.Value*
而不是MyEnum.Value*
...
從 EF Core 開始,您可以直接在 Fluent API 上使用枚舉。 如果您的 MyBaseClass 未映射,您可以刪除描述基本鑒別器的第一行HasValue 。
modelBuilder.Entity<MyBaseClass>()
.HasDiscriminator<MyEnum>("MyEnum")
.HasValue<MyBaseClass>(MyEnum.Value0)
.HasValue<DerivedOne>(MyEnum.Value1)
.HasValue<DerivedTwo>(MyEnum.Value2);
基於@rsenna 的回答,但更新了基於 Microsofts Fluent Api 原始文檔的映射。
https://msdn.microsoft.com/en-us/library/jj591617%28v=vs.113%29.aspx?f=255&MSPPError=-2147217396
public enum MyEnum
{
Value1, Value2
}
public class MyBaseClass
{
[NotMapped]
public MyEnum MyEnum { get; protected set; }
}
public class DerivedOne: MyBaseClass
{
public DerivedOne()
{
MyEnum = MyEnum.Value1;
}
}
public class DerivedTwo: MyBaseClass
{
public DerivedTwo()
{
MyEnum = MyEnum.Value2;
}
}
public class MyDbContext : DbContext
{
DbSet<MyBaseClass> MyBaseClass { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<MyBaseClass>()
.Map<DerivedOne>(x => x.Requires("MyEnum").HasValue((int)MyEnum.Value1))
.Map<DerivedTwo>(x => x.Requires("MyEnum").HasValue((int)MyEnum.Value2));
}
}
我想知道向MyEnum
添加第三個值來表示基類是否會有所幫助。 然后在構造函數中將MyBaseClass.MyEnum
設置MyBaseClass.MyEnum
特定的“默認” enum
值。
我認為 Table-per-heirarchy 結構需要每個類型都必須有一個有效的鑒別器。 因此,您有 3 種類型:
MyBaseClass
DerivedOne
DerivedTwo
即使您的應用程序永遠不會以其基本形式使用 MyBaseClass,EF 仍然需要一個有效的鑒別器映射。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.