Entity framework 使用抽象类和fluent api时外键放置错误

Entity framework 使用抽象类和fluent api时外键放置错误,entity-framework,entity-framework-4.1,ef-code-first,fluent-interface,Entity Framework,Entity Framework 4.1,Ef Code First,Fluent Interface,使用抽象类时,我在将外键映射到正确的表时遇到问题。这是我的模型: public abstract class Entity { public Guid UID { get; set; } } public abstract class Product : Entity { public DeviceModel Model { get; set; } public User Operator { get; set; } } public abstract class O

使用抽象类时,我在将外键映射到正确的表时遇到问题。这是我的模型:

public abstract class Entity
{
    public Guid UID { get; set; }
}

public abstract class Product : Entity
{
    public DeviceModel Model { get; set; }
    public User Operator { get; set; }
}

public abstract class OrderEntry : Entity
{
    public Order Order { get; set; }
}

public class Device : Product
{
    public String Reference { get; set; }
    public String Serial { get; set; }
    public String SoftwareVersion { get; set; }
}

public class OrderEntryDevice : OrderEntry
{
    public DeviceModel Model { get; set; }
}
以及fluent api配置(TPT模式):

公共类EntityConfiguration:EntityTypeConfiguration
{
公共实体配置()
{
可转让(“实体”);
HasKey(t=>t.UID);
}
}
公共类ProductConfiguration:EntityTypeConfiguration
{
公共产品配置()
{
ToTable(“产品”);
has可选(t=>t.Operator)
.有很多
.Map(t=>t.MapKey(“FK_运算符”))
.WillCascadeOnDelete(假);
}
}
公共类OrderEntryConfiguration:EntityTypeConfiguration
{
public OrderEntryConfiguration()
{
ToTable(“订单条目”);
HasRequired(t=>t.Order)
.有很多
.Map(t=>t.MapKey(“FK_顺序”))
.WillCascadeOnDelete(假);
}
}
公共类设备配置:EntityTypeConfiguration
{
公共设备配置()
{
可折叠(“装置”);
属性(t=>t.Reference)
.IsRequired();
属性(t=>t.Serial)
.IsRequired();
HasRequired(t=>t.Model)
.有很多
.Map(t=>t.MapKey(“FK_模型”))
.WillCascadeOnDelete(假);
}
}
公共类OrderEntryDeviceConfiguration:EntityTypeConfiguration
{
public OrderEntryDeviceConfiguration()
{
ToTable(“OrderEntriesDevice”);
HasRequired(t=>t.Model)
.有很多
.Map(t=>t.MapKey(“FK_模型”))
.WillCascadeOnDelete(假);
}
}

创建数据库将把“FK_运算符”外键放在“Products”表中(正好在我想要的位置),但“FK_Order”外键放在“Entities”表中,而不是“OrderEntries”表中。如果我将类“OrderEntry”的抽象属性更改为具体属性,那么一切都正常。在这种情况下,我必须避免抽象类吗?

我已经尝试过你的模型,但我无法重现这个问题。我在
OrderEntries
表中获得了
FK_Order
列,而不是在
Entities
表中,这与预期一致

您可以将以下内容复制到控制台应用程序的
Program.cs
(还可以将
EntityFramework.dll
System.ComponentModel.DataAnnotations.dll
添加到引用中)

我已经为
User
DeviceModel
Order
创建了三个虚拟类来编译和运行代码。但其他课程都是你问题的翻版

问题是:下面的代码和您的代码之间的重要区别在哪里,这可能会导致错误的映射

using System;
using System.Linq;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace EFAbstractTest
{
    public class User
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public class DeviceModel
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public class Order
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public abstract class Entity
    {
        public Guid UID { get; set; }
    }

    public abstract class Product : Entity
    {
        public DeviceModel Model { get; set; }
        public User Operator { get; set; }
    }

    public abstract class OrderEntry : Entity
    {
        public Order Order { get; set; }
    }

    public class Device : Product
    {
        public String Reference { get; set; }
        public String Serial { get; set; }
        public String SoftwareVersion { get; set; }
    }

    public class OrderEntryDevice : OrderEntry
    {
        public DeviceModel Model { get; set; }
    }

    public class EntityConfiguration : EntityTypeConfiguration<Entity>
    {
        public EntityConfiguration()
        {
            ToTable("Entities");

            HasKey(t => t.UID);
        }
    }

    public class ProductConfiguration : EntityTypeConfiguration<Product>
    {
        public ProductConfiguration()
        {
            ToTable("Products");

            HasOptional(t => t.Operator)
                .WithMany()
                .Map(t => t.MapKey("FK_Operator"))
                .WillCascadeOnDelete(false);
        }
    }

    public class OrderEntryConfiguration : EntityTypeConfiguration<OrderEntry>
    {
        public OrderEntryConfiguration()
        {
            ToTable("OrderEntries");

            HasRequired(t => t.Order)
                .WithMany()
                .Map(t => t.MapKey("FK_Order"))
                .WillCascadeOnDelete(false);
        }
    }

    public class DeviceConfiguration : EntityTypeConfiguration<Device>
    {
        public DeviceConfiguration()
        {
            ToTable("Devices");

            Property(t => t.Reference)
                .IsRequired();

            Property(t => t.Serial)
                .IsRequired();

            HasRequired(t => t.Model)
                .WithMany()
                .Map(t => t.MapKey("FK_Model"))
                .WillCascadeOnDelete(false);
        }
    }

    public class OrderEntryDeviceConfiguration : EntityTypeConfiguration<OrderEntryDevice>
    {
        public OrderEntryDeviceConfiguration()
        {
            ToTable("OrderEntriesDevice");

            HasRequired(t => t.Model)
                .WithMany()
                .Map(t => t.MapKey("FK_Model"))
                .WillCascadeOnDelete(false);
        }
    }

    public class MyContext : DbContext
    {
        public DbSet<Entity> Entities { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<DeviceModel> DeviceModels { get; set; }
        public DbSet<Order> Orders { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new EntityConfiguration());
            modelBuilder.Configurations.Add(new ProductConfiguration());
            modelBuilder.Configurations.Add(new OrderEntryConfiguration());
            modelBuilder.Configurations.Add(new DeviceConfiguration());
            modelBuilder.Configurations.Add(new OrderEntryDeviceConfiguration());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var ctx = new MyContext())
            {
                // some query, just to trigger database creation
                ctx.Orders.Count();
            }
        }
    }
}
使用系统;
使用System.Linq;
使用System.Data.Entity.ModelConfiguration;
使用System.Data.Entity;
使用System.ComponentModel.DataAnnotations;
命名空间EFAbstractTest
{
公共类用户
{
[关键]
公共Guid UID{get;set;}
公共字符串名称{get;set;}
}
公共类设备模型
{
[关键]
公共Guid UID{get;set;}
公共字符串名称{get;set;}
}
公共阶级秩序
{
[关键]
公共Guid UID{get;set;}
公共字符串名称{get;set;}
}
公共抽象类实体
{
公共Guid UID{get;set;}
}
公共抽象类产品:实体
{
公共设备模型{get;set;}
公共用户运算符{get;set;}
}
公共抽象类OrderEntry:实体
{
公共秩序{get;set;}
}
公共类设备:产品
{
公共字符串引用{get;set;}
公共字符串序列{get;set;}
公共字符串软件版本{get;set;}
}
公共类OrderEntryDevice:OrderEntry
{
公共设备模型{get;set;}
}
公共类EntityConfiguration:EntityTypeConfiguration
{
公共实体配置()
{
可转让(“实体”);
HasKey(t=>t.UID);
}
}
公共类ProductConfiguration:EntityTypeConfiguration
{
公共产品配置()
{
ToTable(“产品”);
has可选(t=>t.Operator)
.有很多
.Map(t=>t.MapKey(“FK_运算符”))
.WillCascadeOnDelete(假);
}
}
公共类OrderEntryConfiguration:EntityTypeConfiguration
{
public OrderEntryConfiguration()
{
ToTable(“订单条目”);
HasRequired(t=>t.Order)
.有很多
.Map(t=>t.MapKey(“FK_顺序”))
.WillCascadeOnDelete(假);
}
}
公共类设备配置:EntityTypeConfiguration
{
公共设备配置()
{
可折叠(“装置”);
属性(t=>t.Reference)
.IsRequired();
属性(t=>t.Serial)
.IsRequired();
HasRequired(t=>t.Model)
.有很多
.Map(t=>t.MapKey(“FK_模型”))
.WillCascadeOnDelete(假);
}
}
公共类OrderEntryDeviceConfiguration:EntityTypeConfiguration
{
public OrderEntryDeviceConfiguration()
{
ToTable(“OrderEntriesDevice”);
HasRequired(t=>t.Model)
.有很多
.Map(t=>t.MapKey(“FK_模型”))
.WillCascadeOnDelete(假);
}
}
公共类MyContext:DbContext
{
公共数据库集实体{get;set;}
公共数据库集用户{get;set;}
公共数据库集设备模型{get;set;}
公共数据库集命令{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
模型建筑
using System;
using System.Linq;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace EFAbstractTest
{
    public class User
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public class DeviceModel
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public class Order
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public abstract class Entity
    {
        public Guid UID { get; set; }
    }

    public abstract class Product : Entity
    {
        public DeviceModel Model { get; set; }
        public User Operator { get; set; }
    }

    public abstract class OrderEntry : Entity
    {
        public Order Order { get; set; }
    }

    public class Device : Product
    {
        public String Reference { get; set; }
        public String Serial { get; set; }
        public String SoftwareVersion { get; set; }
    }

    public class OrderEntryDevice : OrderEntry
    {
        public DeviceModel Model { get; set; }
    }

    public class EntityConfiguration : EntityTypeConfiguration<Entity>
    {
        public EntityConfiguration()
        {
            ToTable("Entities");

            HasKey(t => t.UID);
        }
    }

    public class ProductConfiguration : EntityTypeConfiguration<Product>
    {
        public ProductConfiguration()
        {
            ToTable("Products");

            HasOptional(t => t.Operator)
                .WithMany()
                .Map(t => t.MapKey("FK_Operator"))
                .WillCascadeOnDelete(false);
        }
    }

    public class OrderEntryConfiguration : EntityTypeConfiguration<OrderEntry>
    {
        public OrderEntryConfiguration()
        {
            ToTable("OrderEntries");

            HasRequired(t => t.Order)
                .WithMany()
                .Map(t => t.MapKey("FK_Order"))
                .WillCascadeOnDelete(false);
        }
    }

    public class DeviceConfiguration : EntityTypeConfiguration<Device>
    {
        public DeviceConfiguration()
        {
            ToTable("Devices");

            Property(t => t.Reference)
                .IsRequired();

            Property(t => t.Serial)
                .IsRequired();

            HasRequired(t => t.Model)
                .WithMany()
                .Map(t => t.MapKey("FK_Model"))
                .WillCascadeOnDelete(false);
        }
    }

    public class OrderEntryDeviceConfiguration : EntityTypeConfiguration<OrderEntryDevice>
    {
        public OrderEntryDeviceConfiguration()
        {
            ToTable("OrderEntriesDevice");

            HasRequired(t => t.Model)
                .WithMany()
                .Map(t => t.MapKey("FK_Model"))
                .WillCascadeOnDelete(false);
        }
    }

    public class MyContext : DbContext
    {
        public DbSet<Entity> Entities { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<DeviceModel> DeviceModels { get; set; }
        public DbSet<Order> Orders { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new EntityConfiguration());
            modelBuilder.Configurations.Add(new ProductConfiguration());
            modelBuilder.Configurations.Add(new OrderEntryConfiguration());
            modelBuilder.Configurations.Add(new DeviceConfiguration());
            modelBuilder.Configurations.Add(new OrderEntryDeviceConfiguration());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var ctx = new MyContext())
            {
                // some query, just to trigger database creation
                ctx.Orders.Count();
            }
        }
    }
}