繁体   English   中英

实体框架:重用外键

[英]Entity Framework: Reusing foreign key

我正在重构别人的涉及EF6的代码,代码优先。 我正在尝试重用数据库列,以便它们涉及多个外键关系。

我知道这样做可以使我的模式非规范化,但是这样做可以使我在原始设计中缺少的模型之间建立更直接的关系。 我希望在对底层数据库架构进行最小更改的情况下就可以做到这一点,因为会有手写的sproc和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它引用两个FrameType以及Moulding

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属性而不是使用反向装饰装饰导航属性 ,因为虽然bot允许映射单个FK字段,但前者是通过数据注释映射复合FK字段的唯一方法。

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

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM