2016-03-03 47 views
0

我有可以包含多个地址的客户(提货,发票等)实体框架:如何包含受保护的Collection <>?

现在地址的集合,我想在我的Customer类使用.Include(s => s.Addresses)。地址和衍生是DeliveryAddress的定义是这样的:

protected virtual ICollection<Address> Addresses 
{ 
    get { return _addresses ?? (_addresses = new Collection<Address>()); } 
    set { _addresses = value; } 
} 

[NotMapped] 
public Address DeliveryAddress 
{ 
    get { return GetAddress(AddressType.Delivery); } 
} 

private Address GetAddress(AddressType type) 
{ 
    return Addresses.FirstOrDefault(a => a.Type == type); 
} 

,因为它是一个受保护的财产,我发现了一个解决方案上Mapping but not exposing ICollections in Entity Framework

我还发现了下面的帖子,但是这是关于映射代替包括: How to map a protected property in EF 4.3 code first

在这里,他们将以下内容添加到包含受保护属性public static Expression<Func<Parent, ICollection<Child>>> ChildrenAccessor = f => f.ChildrenStorage;的类中。

所以我已经添加了相同的到我的Customer类,像这样: public static Expression<Func<Customer, ICollection<Address>>> AddressesAccessor = f => f.Addresses;

,之后我就能够使用与Include(Customer.AddressesAccessor) 这个伟大的工程的映射关系包括,但我没有得到它使用Include方法。它总是告诉我以下内容:

System.InvalidOperationException:指定的Include路径无效。 EntityType'Web.DataAccess.Customer'没有声明名称为'Addresses'的导航属性。

当我将Addresses属性的签名从protected更改回public时,一切正常。

有谁知道如何使这项工作的受保护的集合?

+0

它看起来像你需要它是'公共'。那么你为什么要把它设置为'protected'?因为您希望其他类能够访问该属性,因此将它作为“公共”留下的问题是什么? – CodeThug

+0

收集已经在客户身上。我想添加一些额外的'public'属性来按类型公开地址,而不必一直对集合执行linq查询。有了这些额外的“公共”特性,集合就不再需要“公共”了。 – rdvanbuuren

回答

0

我测试了一下,它对我很好。样本项目可在https://github.com/codethug/EF.Experiments/blob/master/EF.Test/SubCollectionTests.cs找到,并通过测试。

您是否使用流利的映射语法,就像这样:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Customer>() 
      .HasMany(Customer.AddressesAccessor) 
      .WithRequired(); 
    } 

或者,您在使用数据注释?

我发现当我使用数据注释而不是流利映射时,我会得到你发现的异常。但是使用Fluent Mapping可以让所有的工作都毫无困难

我在猜测发生了什么,当你使用数据注释,有很多约定被用来找出什么应该被视为一个导航属性,并且由于Addresses属性是受保护的,所以约定表示它不应该是导航属性。但是,如果使用Fluent Mapping,则明确告知EF地址应该是导航属性。

如果你真的想使用数据注解,你可能会编写一些自定义约定,但我不太熟悉如何完成。