0

I've got a collection of addresses which can contain multiple addresses for a Customer (delivery, invoice, etc.)

Now, I'm trying to use .Include(s => s.Addresses) on my Customer class. Addresses and the derivative DeliveryAddress are defined like this:

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);
}

Since it's a protected property, I've found a solution for this on Mapping but not exposing ICollections in Entity Framework

I Also found the following post, but this is about mappings instead of includes: How to map a protected property in EF 4.3 code first

Here they add the following to the class containing the protected property public static Expression<Func<Parent, ICollection<Child>>> ChildrenAccessor = f => f.ChildrenStorage;.

So I've added the same to my Customer class like so: public static Expression<Func<Customer, ICollection<Address>>> AddressesAccessor = f => f.Addresses;

And then i'm able to use the include with Include(Customer.AddressesAccessor) This works great for mappings, but I'm not getting it to work with the Include method. It keeps telling me the following:

System.InvalidOperationException: A specified Include path is not valid. The EntityType 'Web.DataAccess.Customer' does not declare a navigation property with the name 'Addresses'.

When I change the signature of the Addresses property from protected back to public all works fine.

Does anyone know how to make this work for protected collections?

Community
  • 1
  • 1
rdvanbuuren
  • 596
  • 6
  • 13
  • It looks like you need it to be `public`. So why do you want it to be set to `protected`? What's the problem with leaving it as `public` since you want other classes to be able to access the property? – CodeThug Mar 04 '16 at 05:13
  • The collection was already present on the customer. I want to add some extra `public`properties that expose the addresses by type, instead of having to do a linq query on the collection all the time. And with those extra `public` properties, there's no need for the collection to be `public` too anymore. – rdvanbuuren Mar 04 '16 at 07:40

1 Answers1

0

I tested this out, and it worked great for me. A sample project can be found at https://github.com/codethug/EF.Experiments/blob/master/EF.Test/SubCollectionTests.cs with tests that pass.

Are you using the Fluent Mapping syntax, like this:

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

Or are you using Data Annotations?

I found that when I used Data Annotations instead of the Fluent Mapping, I would get the exception you found. But using Fluent Mapping made everything work without trouble.

I'm guessing that what's happening is when you use Data Annotations, there is a lot of convention being used to figure out what should be considered a Navigation Property, and since the Addresses property is protected, the convention says that it shouldn't be a Navigation property. However, if you use the Fluent Mapping, you are explicitly telling EF that Addresses should be a Navigation property.

If you really want to use Data Annotations, you can probably code up some custom conventions, but I'm not too familiar with how that could be done.

CodeThug
  • 3,054
  • 1
  • 21
  • 17