EF多重关系

4

使用 Entity Framework 5

我有一个客户。客户可能有许多地址,但至少有一个。其中一个地址也将被设置为主要地址(必需的)。我尝试了各种映射,但到目前为止,在构建时或者填充数据库时都会出现错误。

客户:

public class Customer
{
    public int CustomerId { get; set;}
    public String CustomerName { get; set; }
    public int PrimaryAddressId { get; set; }
    public virtual CustomerAddress PrimaryAddress { get; set; }
    public virtual ICollection<CustomerAddress> CustomerAddresses { get; set; }    
}

地址:

public class CustomerAddress : Address
{
    public int CustomerAddressId { get; set; }
    public int CustomerId { get; set; }
    public virtual Customer Customer { get; set; }
}

我的这个映射部分正常工作,它在客户地址上。

        this.HasRequired(c => c.Customer)
            .WithMany(d => d.CustomerAddresses)
            .HasForeignKey(c => c.CustomerId);

但是我应该如何为设置客户的PrimaryAddress指定正确的映射呢?或者这种方法是错误的吗?
谢谢。
编辑 - 使用Arnold和LueTM的答案:
这段代码现在可以正常工作了。
客户:
public class Customer
{
    public int CustomerId { get; set;}
    public String CustomerName { get; set; }
    // public int PrimaryAddressId { get; set; } created in mapping
    public virtual CustomerAddress PrimaryAddress { get; set; }
    public virtual ICollection<CustomerAddress> CustomerAddresses { get; set; }    
}

地址:

public class CustomerAddress : Address
{
    public int CustomerAddressId { get; set; }
    public int CustomerId { get; set; }
    public virtual Customer Customer { get; set; }
}

客户映射:
        modelBuilder.Entity<Customer>
            .HasOptional(c => c.PrimaryAddress)
            .WithOptionalDependent().Map(m => m.MapKey("PrimaryAddressId"));

        modelBuilder.Entity<Customer>
            .HasMany(c => c.CustomerAddresses)
            .WithRequired(c => c.Customer)
            .HasForeignKey(c => c.CustomerId)
            .WillCascadeOnDelete(false);

我使用一个代码库来确保先创建一个新的地址,保存后再将其设置为主要地址并再次保存。这个代码库可以确保主要地址是“必需”的。


2
请通过编辑您的帖子,展示错误和出现错误的代码片段。 - Gert Arnold
1个回答

1

由于您没有显示异常,我必须假设您遇到了一个鸡生蛋的问题。

如果您将PrimaryAddress设置为必需属性,则EF必须有一个现有的地址ID来建立外键(在Customer中设置PrimaryAddressId)。但是,由于Address需要一个Customer,因此您不能在其客户之前存储地址。如果您尝试一次保存地址和客户,EF无法确定插入的正确顺序,因为它需要使用另一个对象的生成ID插入两个对象。

因此,AddressCustomer必须具有可选的外键。

我会使Customer.PrimaryAddressId可选:

modelBuilder.Entity<Customer>().HasOptional(c => c.PrimaryAddress)
    .WithOptionalDependent();

现在您可以在单独的交易中存储地址并为客户分配主要地址。但是,您需要业务逻辑来确保 Customer 始终具有主要地址。

如果您想在一个事务中保存客户和地址,一种方法是向 CustomerAddress 添加一个 IsPrimary 属性(bool),并确保始终只有一个地址为 true


是的,这个可行。你说得对,我试图在一个事务中保存地址并将其分配为主地址。我想我太专注于让主地址“必需”了。总之:它现在生成自己的外键。我能将其映射到我的“PrimaryAddressId”吗? - Sander
1
已解决。我移除了PrimaryAddress id并添加了一个映射: this.HasOptional(c => c.PrimaryAddress) .WithOptionalDependent().Map(m => m.MapKey("PrimaryAddressId")); - Sander
啊,没看到你的评论,但很高兴你找到了! - Gert Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接