是否可以首先在实体框架代码中使用PK列作为鉴别器?

时间:2011-11-17 20:26:59

标签: c# .net entity-framework-4.1

我首先尝试使用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不支持吗?

1 个答案:

答案 0 :(得分:0)

这是不可能的。每个列在映射中只能有一个特殊用途。将列作为键和鉴别符是两个特殊目的。 Discriminator列具有选择要实现的正确类型的特殊含义,因为它必须不存在于映射实体中(您无法从应用程序中设置它)。在列上具有必须唯一的鉴别器也是不正确的。