【问题标题】:Is it possible to use a PK column as a discriminator in Entity Framework code first?是否可以首先在实体框架代码中使用 PK 列作为鉴别器?
【发布时间】:2011-11-18 19:10:52
【问题描述】:

我首先尝试使用实体框架代码来尝试将简单的查找表映射到类型的层次结构,并希望将表的主键用作“每个层次结构的表”实体的鉴别列。更准确地说,我正在尝试针对现有数据库进行这项工作。

这是一个人为的示例应用程序,我试图弄清楚我是否可以让它工作:

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 根本不支持我正在尝试做的事情吗?

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-29
      • 1970-01-01
      • 2012-05-03
      • 1970-01-01
      • 2011-07-29
      相关资源
      最近更新 更多