实体框架6 TPT和外键

时间:2018-11-13 16:01:00

标签: c# inheritance entity-framework-6

我一直想让EF在TPT方案中与外键一起工作。我认为一个表具有一对多关系而另一个表具有一对一关系是很复杂的。

将这段代码简化为说明问题(对于VS项目,GitHub:https://github.com/Dash/EFTest)。

当我在基本Persons表中创建外键时,出现有关类型不匹配的错误:

  

产品:FromRole:NavigationProperty'产品'无效。类型   AssociationType中FromRole'Product_Buyers_Target'的'Buyer'   “ Product_Buyers”必须与类型“ Person”完全匹配   此NavigationProperty声明为打开。

要尝试解决此问题,我将Product导航属性移至子级,但是由于数据库中不存在ProductId列,因此出现错误-它试图在派生表中查找,而在基本表。

我尚不完全清楚如何解决此问题,并且一直绕着圈子兜圈子,直到我的眼睛流血为止。有人可以帮忙吗?

模型

public abstract class Person
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Product Product { get; set; }
}

public class Buyer : Person
{
    public string ShipTo { get; set; }
}

public class Seller : Person
{
    public int Rating { get; set; } = 0;
}

public class Product
{
    public int Id { get; set; }

    public string Description { get; set; }
    public virtual Seller Seller { get; set; }
    public virtual IList<Buyer> Buyers { get; set; }
}

架构

public class ProductSchema : EntityTypeConfiguration<Product>
{
    public ProductSchema()
    {
        HasKey(p => p.Id)
            .Property(p => p.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(p => p.Description)
            .HasMaxLength(256);

        HasOptional(p => p.Seller)
            .WithRequired(i => i.Product)
            .Map(m => m.MapKey("ProductId"));

        HasMany(p => p.Buyers)
            .WithRequired(i => i.Product)
            .Map(m => m.MapKey("ProductId"));
    }
}

public class PersonSchema : EntityTypeConfiguration<Person>
{
    public PersonSchema()
    {
        ToTable("Persons");

        HasKey(p => p.Id)
            .Property(p => p.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(p => p.Name)
            .HasMaxLength(128);
    }
}

public class SellerSchema : EntityTypeConfiguration<Seller>
{
    public SellerSchema()
    {
        ToTable("Sellers");

        HasKey(s => s.Id)
            .Property(s => s.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(s => s.Rating);
    }
}

public class BuyerSchema : EntityTypeConfiguration<Buyer>
{
    public BuyerSchema()
    {
        ToTable("Buyers");

        HasKey(b => b.Id)
            .Property(b => b.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(b => b.ShipTo)
            .HasMaxLength(256);
    }
}

SQL

CREATE TABLE Products (
Id INT IDENTITY PRIMARY KEY,
[Description] nvarchar(256),
)

create table Persons (
    Id int IDENTITY PRIMARY KEY,
    [Name] nvarchar(128),
    ProductId INT NOT NULL,
    FOREIGN KEY (ProductId) REFERENCES Products(Id)
)

CREATE TABLE Buyers (
    Id INT PRIMARY KEY,
    ShipTo nvarchar(256)
)

CREATE TABLE Sellers (
    Id INT PRIMARY KEY,
    Rating INT NOT NULL DEFAULT 0
)

DECLARE @ProductId int;
INSERT INTO Products ([Description]) VALUES ('Widget');
SET @ProductId = @@IDENTITY;

INSERT INTO Persons ([Name], ProductId) VALUES ('Bob the seller', @ProductId);
INSERT INTO Sellers (Id, Rating) VALUES (@@IDENTITY, 0);

INSERT INTO Persons ([Name], ProductId) VALUES ('Bert the buyer', @ProductId);
INSERT INTO Buyers (Id, ShipTo) VALUES (@@IDENTITY, 'Somewhere');

1 个答案:

答案 0 :(得分:0)

我从来没有找到让EF来处理这个概念的方法。

最后,我不得不放弃Persons的ProductId外键,并在EF打球之前在买卖双方中都有重复的副​​本。这有悖于规范化,但可以。