C# 将导航属性映射到主表

C# 将导航属性映射到主表,c#,entity-framework-core,C#,Entity Framework Core,我有一个classContract,有两个属性TotalAmount和InstallmentAmount public class Contract { public int ContractId { get; set; } public Amount TotalAmount { get; set; } public Amount InstallmentAmount { get; set; } //other Amounts } public class Amo

我有一个class
Contract
,有两个属性
TotalAmount
InstallmentAmount

public class Contract
{
    public int ContractId { get; set; }
    public Amount TotalAmount { get; set; }
    public Amount InstallmentAmount { get; set; }
    //other Amounts
}

public class Amount
{
    public decimal Value { get; set; }
    public string Currency { get; set; }
} 
是否可以配置实体框架,以便它可以创建一个具有如下结构的表
合同

------------------------------------------------------------
| ContractId | TotalAmountValue | TotalAmountCurrency | ... 
|     999    |       1000       |         USD         | ...
------------------------------------------------------------  

回答你的具体问题。通过将
Amount
类映射为,可以实现您的请求

最简单的方法是使用
[Owned]
属性:

[Owned] // <--
public class Amount
{
    public decimal Value { get; set; }
    public string Currency { get; set; }
}

您可以使用自有类型,但首先您应该考虑是否真的需要这样的设计。首先,它不是标准化的,这将永远困扰着你。特别是,(由于非规范化),当所有内容都在一个表中时,每个金额与其货币之间存在一种松散的关系:只有字段名才能显示这种关系。在一个单独的金额表中,每个金额都明确地与一种货币挂钩。我会选择这个金额表,其中金额将有一个类型(总计、分期付款等)。我特别喜欢命名部分。只有一个问题,就是
。其中(p=>!p.IsKey()
是必要的还是只是一个一般的预防措施?@Gert是的,这是为了跳过所拥有实体的自动阴影PK/FK而需要的。没有这个标准我会出错。。啊,很高兴知道这一点。我喜欢人们测试他们的代码……;)@用户3373603关于方法。。。这完全取决于你要用这些钱做什么。如果只是一些信息只会显示,而不会在后续流程/查询中使用,则可以将金额存储为一个简单的记录。一旦您要做进一步的处理,例如聚合,或查询特定类型的金额,您会很高兴将它们放在一个单独的表中。然后,您必须分离XML对象——嗯,是可行的。此外,在平面设计中,如果要有新的数量类型,则需要更改数据库架构。(续)。。。对于平面表,让货币引用货币表更麻烦,这在任何数据库设计中都是很自然的事情。
modelBuilder.Owned<Amount>();
modelBuilder.Entity<Contract>(builder =>
{
    var amounts = builder.Metadata.GetNavigations()
        .Where(n => n.ClrType == typeof(Amount));
    foreach (var amount in amounts)
    {
        var amountBuilder = builder.OwnsOne(amount.ClrType, amount.Name);
        var amountProperties = amountBuilder.OwnedEntityType.GetProperties()
            .Where(p => !p.IsKey());
        foreach (var property in amountProperties)
            amountBuilder.Property(property.Name).HasColumnName(amount.Name + property.Name);
    }
});