【问题标题】:One-To-One Entity Framework Code-First Mapping With Composite Keys使用复合键的一对一实体框架代码优先映射
【发布时间】:2013-11-27 03:42:06
【问题描述】:

是否可以在已定义的实体属性上创建一对一的关系?我有以下实体:

public class Asset
{
    public int AssetId { get; set; }
    public int OwningCustomerId { get; set; }
    public virtual Customer OwningCustomer { get; set; }
}

public class CustomerAsset
{
    public int CustomerId { get; set; } // Primary key 0
    public int AssetId { get; set; }    // Primary key 1
    public int CustomerAssetStatusId { get; set; }
    public string Name { get; set; }

    public virtual Customer Customer { get; set; }
    public virtual Asset Asset { get; set; }
}

CustomerAsset 代表资产的各种所有权状态。虽然同一个 AssetId 可以在此表中多次存在,但只有一个实例 CustomerAssetStatusId = 1。为了快速访问资产的当前所有者,我还在 Asset 表中维护了 OwningCustomerId。

我想要一个从 Asset 到 CustomerAsset 的导航属性,称为 OwningCustomerAsset。这是一对一的关系。不幸的是,我不知道如何定义它,因为外键字段已经在 Asset.xml 中定义。通常,我会在 Asset 上创建这样的关系:

HasRequired(e => e.OwningCustomerAsset).WithRequiredDependent().Map(m => m.MapKey("OwningCustomerId", "AssetId"));

当然,这会导致以下错误:“类型中的每个属性名称都必须是唯一的。属性名称‘OwningCustomerId’已被定义。”

我如何告诉 EF OwningCustomerId/AssetId 是 CustomerAsset 的外键?

【问题讨论】:

    标签: c# entity-framework ef-code-first


    【解决方案1】:

    如果您可以修改架构,我建议将资产所有权作为资产本身的属性,而不是客户与资产关系的属性。拥有从AssetCustomer(例如Owner_CustomerID)的不可为空的FK 字段会强制执行“仅限一个所有者”约束,并且可以从CustomerAsset.Asset.Owner(或您选择的任何名称)轻松加载所有者。这种架构更改将大大简化您的查询。

    此外,这将允许您向Customer 添加一个导航属性,该属性引用所有拥有的资产;以Customer.OwnedAssets为例

    更新:

    还可以使用新的Owner_CustomerID 字段通过复合FK ( AssetId, Owner_CustomerId ) 和生成的导航属性将导航属性Asset.OwningCustomerAsset(或任何你想要的)从Asset 添加到CustomerAsset

    【讨论】:

    • 感谢您的评论。我其实已经考虑过了。它确实简化了我的应用程序的某些部分。但是,我已经简化了我的帖子。我的视图返回的还有其他字段可以简化其他事情。例如,当支持客户并按资产名称搜索时,父客户还希望当前所有者的资产名称与他的搜索结果一起出现在他的搜索结果中。拥有一对一的关系确实简化了这一点,因为我可以导航 ca => ca.OwnerCustomerAsset.Name。
    • 混合方法可能是最好的解决方案,然后 - 让 Asset 中的 Owner FK 引用 CustomerAsset 而不是 Customer
    • 实际上我现有的答案已经这样做了 - FK 将持有 CustomerId 并且资产显然已经有自己的 ID,因此新的 Owner_CustomerID 字段可以用作客户的 FK 以及将 FK 与 AssetId 复合到 CustomerAsset
    • 哦,是的,我明白了。我可以使用 OwnerCustomerId 和 AssetId 作为我的键在 Asset 上配置 OwnerCustomerAsset 导航属性。然后在查询 CustomerAsset...ca => ca.Asset.OwnerCustomerAsset.Name 时,我将始终快速访问当前所有者的资产信息。不幸的是,在我想要的视图中还有其他“计算”字段。让我考虑一下,看看这种方法是否真的可以满足我的要求,而不必使用混合方法。
    • 不幸的是,我在尝试创建这种复合键关系时仍然遇到同样的问题。我已经编辑了帖子以简化对问题的解释......这与以前的问题完全相同。
    【解决方案2】:

    自从我在这条路的另一端需要一个导航属性(我不再需要它)以来,我一直坚持一对一的心态。以下得到了我想要的:

    HasRequired(e => e.OwningCustomerAsset).WithMany().HasForeignKey(e =>  new { e.OwningCustomerId, e.AssetId });
    

    【讨论】:

    • 呃,我认为不可能做我想做的事。有一个循环引用。我想我可以在创建数据库后手动删除 OwningCustomerId/AssetId 的 FK 关系。但是,EF 仍然足够聪明,可以在 SubmitChanges() 期间看到循环关系。
    猜你喜欢
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-12
    • 2011-12-17
    相关资源
    最近更新 更多