This project is read-only.

Adding a derived collection throws an exception

Nov 27, 2012 at 10:02 PM

I have followed the instructions on section 3.4.3 in the developer manual and created a derived collection for my "Customer" domain object.

When I run the app and navigate to Customers->All Instances, an exception is thrown - the same self-explanatory one I've been dealing with before: 

System.Data.Entity.DynamicProxies.Customer_D3528800DEA3C449DFB2B1B953541BB765397CEE0E37766722C4D87D214AB41B is not a IEntityWithChangeTracker (all properties must be made virtual/Overrideable and all collection properties should be of type ICollection<T>)

The example in the manual indeed doesn't include the virtual prefix, but even after I added it, I got the same exception.

The derived collection code is:

public virtual ICollection<ContentFolder> RootContentFolders
       return _contentFolders.Where(cf => cf.Parent == null).ToList();

ContentFolder is a domain object and _contentFolders is the collection defined and used within the customer entity.

What am I missing?


p.s. My motivation for creating this derived collection is that I want to see only the root content folders in the Customer view.  

All content folders are associated with a customer, and are also structured hierarchically, based on their Parent property (which is null in the case of a root folder).

I can probably find a recursive solution in which the customer is only associated with root folders, but I'm not sure that's what I want to do...

Nov 27, 2012 at 10:13 PM

I assume from your posting that if you were to comment out that RootContentFolders property that everything works fine, yes?  So the problem is definitely caused by the addition of that code?  Please just confirm that first.

Strangely, I'm thinking that I've seen something like this myself quite recently, and I'm wondering if there has been a change in the way EF works between 4 & 5.  I'm guessing that EF is interpreting this property as being persistable even though it only has a get.  Try adding a [NotPersisted] attribute on the property and see if that makes any difference.

Nov 28, 2012 at 8:41 AM

Thanks Richard,

The issue is definitely the RootContentFolders, based on "comment out / comment in test.

I have already tried the NotPersisted attribute, to no avail...

If I can provide any additional useful information, please let me know.

Nov 28, 2012 at 9:27 AM

OK we'll work with you to try to find the problem (though rather busy today).  First, try converting this derived collection property into an action  -  just to check that that works OK i.e.:

public ICollection<ContentFolder> RootContentFolders()
       return _contentFolders.Where(cf => cf.Parent == null).ToList();

(No need for virtual, though it won't harm it).  If that action isn't working then the problem is with the content being returned  -  but let us know the point of failure i.e. is it when displaying a Customer, or when invoking that action on a Customer

Nov 28, 2012 at 9:47 AM

With the action it's working great.

Nov 28, 2012 at 9:54 AM

Well that's a step forward.  We'll try to look into the problem of treating it as a property later  -  but won't be immediate.

Nov 28, 2012 at 9:56 AM

I'll wait patiently :)


Nov 28, 2012 at 10:13 PM
Edited Nov 28, 2012 at 10:16 PM

Well I've discovered after some experimentation that the answer is to add a [NotMapped] attribute to the derived collection.

I must say that I'm surprised by this  -  I've been using derived collections for a long time  -  but I'm guessing that something changed between EF4 and EF5 such that a collection property with only a getter is still being picked up by EF.  

Possibly, it is not a change in EF, it is that previously I have always done this working with a .edmx, but now we are focussing on Code First  and that's different  (I think you said in an earlier post that you are now working Code First).

Either way, I'll now raise a ticket to investigate this further and, at minimum, update our documentation.

Nov 29, 2012 at 9:53 PM

Got it, and it works now.