实体框架代码首先自定义连接

时间:2011-03-19 18:16:09

标签: .net entity-framework ef-code-first entity-framework-4.1

我有一个Customers表和一个Addresses表。客户可以拥有多个地址,但也有一个地址被标记为主要地址(如果他们有任何地址)。

在代码中是否存在某种方式,我可以将一个字段放在名为“PrimaryAddress”的Customer POCO中,并使用Customers.Include(customer => customer.PrimaryAddress)之类的东西来获取地址是否与客户有关并且设置了主要位?

我认为下一个最好的事情就是在SQL中编写一个自定义连接的视图?

感谢。

1 个答案:

答案 0 :(得分:3)

我不认为这是直接可能的。如果您映射某些内容,它将以关系或列结束。因此,如果您希望您的客户看起来像:

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或M:N(联结表)关系。

这不是很好,因为PrimaryAddress_ID必须存在一些约束,必须来自与客户相关的地址。这种约束可能需要通过触发器进行检查。

除非您正在构建只读应用程序或者您已准备好定义INSTEAD OF触发器,否则查看也无法实现。

您可以在没有映射的情况下执行此操作:

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上使用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();

这将仅加载主地址,但您必须首先加载客户,因此您必须将数据汇总到数据库。