实体框架:重复外键



我正在重构其他人的代码,涉及ef6,code-firt。我正在尝试重复使用数据库列,以便它们参与多个外国密钥关系。

我知道,这样做是在使我的架构不正当,但是这样做,这将使我能够在原始设计中缺少的模型之间建立更直接的关系。我希望这种情况发生在最小的基础数据库模式,因为有手写的sprocs和udf会受到影响。

下面的模型代表当前状态:

FrameFrameTypeMoulding组成。帧是唯一的,因为没有重复FrameTypeMoulding,因此我们在FrameType_IdMoulding_Id上有一个复合主键。

public class Frame
{
    [Key,Column(Order = 0)]
    [ForeignKey("Moulding")]
    public int Moulding_Id { get; set; }
    public Moulding Moulding { get; set; }
    [Key, Column(Order = 1)]
    [ForeignKey("FrameType")]
    public int FrameType_Id { get; set; }
    public FrameType FrameType { get; set; }
}

我们可以假设FrameTypeMoulding

的最小实现
public class FrameType
{
    public int Id{get; set;}
    public ICollection<Frame> Frames{get; set;}
}
public class Moulding
{
    public int Id{get; set;}
    public ICollection<Frame> Frames{get; set;}
}

在其他地方,我们有一个Product,它同时引用FrameTypeMoulding

public class Product
{
    public int Id{get; set;}
    [ForeignKey("Moulding")]
    public int Moulding_Id { get; set; }
    public Moulding Moulding { get; set; }
    [ForeignKey("FrameType")]
    public int FrameType_Id { get; set; }
    public FrameType FrameType { get; set; }
}

但是,至关重要的是,不直接引用Frame

我想将属性添加到Frame

public ICollection<Product> Products{get; set;}

Product

public Frame Frame{get; set;}

重新使用Moulding_IdFrameType_Id字段不仅是MouldingFrameType的外国密钥,还可以直接作为Frame的复合外键。

在EF中,这种"重复使用"是否可能?

是的,这是可能的。唯一的EF6要求是(1(引用的实体属性为PK,(2(在重复使用FK的各个部分的情况下,FK属性是明确定义的,因为没有将2个阴影属性映射到一个和同名的方法。幸运的是,您的样本模型满足了这两个条件。

我个人更喜欢流利的配置,因为它更明确,IMO更容易遵循。或者,如果您更喜欢数据注释,请用ForeignKey属性而不是倒数对导航属性进行装饰通过数据账单。

将其应用于您的示例模型如下:

public class Frame
{
    [Key, Column(Order = 0)]
    public int Moulding_Id { get; set; }
    [Key, Column(Order = 1)]
    public int FrameType_Id { get; set; }
    [ForeignKey("Moulding_Id")]
    public Moulding Moulding { get; set; }
    [ForeignKey("FrameType_Id")]
    public FrameType FrameType { get; set; }
    public ICollection<Product> Products { get; set; }
}
public class Product
{
    public int Id { get; set; }
    public int Moulding_Id { get; set; }
    public int FrameType_Id { get; set; }
    [ForeignKey("Moulding_Id")]
    public Moulding Moulding { get; set; }
    [ForeignKey("FrameType_Id")]
    public FrameType FrameType { get; set; }
    [ForeignKey("Moulding_Id,FrameType_Id")]
    public Frame Frame { get; set; }
}

但是,有一个小问题 - 以上引入了多个级联路径,通常需要您关闭级联删除。反过来,哪些将需要流利的配置,一旦您使用流利的配置,就不需要ForeignKey数据注释,因此请将其从Product.Frame属性中删除并使用以下内容:

modelBuilder.Entity<Product>()
    .HasRequired(e => e.Frame)
    .WithMany(e => e.Products)
    .HasForeignKey(e => new { e.Moulding_Id, e.FrameType_Id })
    .WillCascadeOnDelete(false);

相关内容

  • 没有找到相关文章

最新更新