使用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; }
}
我的映射的这部分工作正常。它位于CustomerAddress上。
this.HasRequired(c => c.Customer)
.WithMany(d => d.CustomerAddresses)
.HasForeignKey(c => c.CustomerId);
但是如何指定在Customer中设置PrimaryAddress的正确映射?或者这是错误的做法?
由于
编辑 - 同时使用Arnolds和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);
我使用存储库来确保首先创建一个新地址,保存,然后再设置为主地址并再次保存。存储库确保主要是“必需的”。
答案 0 :(得分:1)
由于你没有显示异常,我不得不假设你遇到了鸡蛋问题。
如果将PrimaryAddress
设置为必需属性,则EF必须具有现有地址ID才能建立外键(在PrimaryAddressId
中设置Customer
)。但是,由于Address
需要Customer
,因此您无法在其客户之前存储地址。如果您尝试一次保存地址和客户,EF无法确定插入的正确顺序,因为它需要插入具有另一个对象的生成Id的两个对象。
因此,Address
或Customer
必须具有可选的外键。
我会Customer.PrimaryAddressId
选择:
modelBuilder.Entity<Customer>().HasOptional(c => c.PrimaryAddress)
.WithOptionalDependent();
现在,您可以在separeate交易中存储地址并为客户分配主要地址。但是您需要业务逻辑来确保Customer
始终具有主要地址。
如果您想在一个事务中保存cutomers和地址,可能需要将IsPrimary
属性(bool)添加到CustomerAddress
,并确保始终只有一个地址true