我有一个客户表和一个地址表。客户可以有多个地址,但他们也有一个标记为他们的主要地址(如果他们有任何地址)。
在代码中是否有某种方式,我可以在 Customer POCO 中放置一个名为“PrimaryAddress”的字段,并使用诸如 Customers.Include(customer => customer.PrimaryAddress) 之类的内容来获取与客户并且设置了主要位?
我认为下一个最好的事情就是在 SQL 中编写一个自定义连接的视图?
谢谢。
我有一个客户表和一个地址表。客户可以有多个地址,但他们也有一个标记为他们的主要地址(如果他们有任何地址)。
在代码中是否有某种方式,我可以在 Customer POCO 中放置一个名为“PrimaryAddress”的字段,并使用诸如 Customers.Include(customer => customer.PrimaryAddress) 之类的内容来获取与客户并且设置了主要位?
我认为下一个最好的事情就是在 SQL 中编写一个自定义连接的视图?
谢谢。
我不认为这是直接可能的。如果您映射某些内容,它将最终成为关系或列。因此,如果您希望您的客户看起来像:
public class Customer
{
...
public Address PrimaryAddress { get; set; }
public ICollection<Address> Addresses { get; set; }
}
它将最终成为表格:
CREATE TABLE dbo.Customers
(
...
PrimaryAddress_ID INT NULL
)
根据Address
实体定义,您将Addresses
映射为 1:N(Customer_ID
在Addresse
s 表中或 M:N(联结表)关系。
这不是很好,因为还应该有一些PrimaryAddress_ID
必须来自与客户相关的地址的约束。这种约束可能需要通过触发器进行检查。
除非您正在构建只读应用程序或者您准备好定义 INSTEAD OF 触发器,否则 View 也不可行。
你可以在没有映射的情况下做到这一点:
public class Customer
{
...
public ICollection<Address> Addresses { get; set; }
[NotMapped]
public Address PrimaryAddress
{
get
{
return Addresses.Single(a => a.IsPrimary);
}
// If you need set you can implement it in similar way
}
}
您也可以在没有属性的情况下定义它,但您需要使用Ignore
on OnModelCreating
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>()
.Ignore(c => c.PrimaryAddress);
}
该方法的缺点是它总是会加载所有地址。
如果您知道您不需要其他主要地址,您可以使用:
context.Entry<Customer(customer)
.Collection(c => c.Addresses)
.Query()
.Where(a => a.IsPrimary)
.Load();
这将只加载主地址,但您必须先加载客户,因此您必须循环访问数据库。