我首先尝试使用Entity Framework代码尝试将简单的查找表映射到类型的层次结构,并希望使用表的主键作为“每个层次表”实体的鉴别器列。更实际的是,我正在尝试对现有数据库进行此项工作。
这是一个人为设计的示例应用程序,我试图弄清楚我是否可以让它工作:
using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
namespace EfTest
{
public abstract class Base
{
public int LookupId { get; set; }
public String Name { get; set; }
public abstract String GetTest();
}
public class Derived1 : Base
{
public override string GetTest() { return Name + "1"; }
}
public class Derived2 : Base
{
public override string GetTest() { return Name + "2"; }
}
public class Derived3 : Base
{
public override string GetTest() { return Name + "3"; }
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());
using(var context = new MyContext())
{
foreach (var item in context.Lookups)
{
Console.WriteLine("{0} {1} {2}", item.LookupId, item.Name, item.GetType().FullName);
}
}
Console.ReadKey();
}
}
public class MyContext : DbContext
{
public DbSet<Base> Lookups { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var config = modelBuilder.Entity<Base>();
config.HasKey(e => e.LookupId).ToTable("dbo.Lookup");
config.Property(e => e.LookupId)
.HasColumnName("LookupId")
.IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
config.Property(e => e.Name)
.IsRequired()
.HasColumnName("Name")
.HasMaxLength(32)
.HasColumnType("varchar");
config.Map<Derived1>(e => e.Requires("LookupId").HasValue(1).IsRequired());
config.Map<Derived2>(e => e.Requires("LookupId").HasValue(2).IsRequired());
config.Map<Derived3>(e => e.Requires("LookupId").HasValue(3).IsRequired());
//config.Map<Derived1>(e => e.Requires("Name").HasValue("Item1").IsRequired());
//config.Map<Derived2>(e => e.Requires("Name").HasValue("Item2").IsRequired());
//config.Map<Derived3>(e => e.Requires("Name").HasValue("Item3").IsRequired());
}
}
}
然而,这引起了一个例外:
从第24行开始映射片段的问题:条件成员 映射具有除“IsNull = False”以外的条件的“Base.LookupId”。 删除Base.LookupId上的条件或从中删除它 映射。
我也试过用“名称”栏来区别对待,结果相似。
错误看起来像是抱怨我正在尝试映射到数据库中的可空列,但是,实际创建的表的两列都标记为非空,正如我所料。
我试图做的只是EF不支持吗?
答案 0 :(得分:0)
这是不可能的。每个列在映射中只能有一个特殊用途。将列作为键和鉴别符是两个特殊目的。 Discriminator列具有选择要实现的正确类型的特殊含义,因为它必须不存在于映射实体中(您无法从应用程序中设置它)。在列上具有必须唯一的鉴别器也是不正确的。