views:

135

answers:

2

I want to write a rich domain class such as

public class Product    
{    
   public IEnumerable<Photo> Photos {get; private set;}    
   public void AddPhoto(){...}    
   public void RemovePhoto(){...}
 }

But the entity framework (V4 code first approach) requires an ICollection type for lazy loading! The above code no longer works as designed since clients can bypass the AddPhoto / RemovePhoto method and directly call the add method on ICollection. This is not good.

public class Product    
{    
   public ICollection<Photo> Photos {get; private set;} //Bad    
   public void AddPhoto(){...}    
   public void RemovePhoto(){...}    
 }

It's getting really frustrating trying to implement DDD with the EF4. Why did they choose the ICollection for lazy loading?

How can i overcome this? Does NHibernate offer me a better DDD experience?

+1  A: 

You can't insert into an IEnumerable. This applies to the EF just as much as it does to your clients. You don't have to use ICollection, though; you can use IList or other writeable types. My advice to get the best of both worlds is to expose DTOs rather than entities to your clients.

Craig Stuntz
So true. Exposing DTOs and optionally generating view models from those DTOs is the path I choose. I think too many people get scared away but how much more code it sounds like they will have to write to accomplish it.
joseph.ferris
+2  A: 

I think i found the solution...See here for more details: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/47296641-0426-49c2-b048-bf890c6d6af2/

Essentially you want to make the ICollection type protected and use this as the backing collection for the public IEnumerable

public class Product
{

   // This is a mapped property
   protected virtual ICollection<Photo> _photos { get; set; }

   // This is an un-mapped property that just wraps _photos
   public IEnumerable<Photo> Photos
   {
      get  { return _photos; }
   }

   public void AddPhoto(){...}
   public void RemovePhoto(){...}

} 

For lazy loading to work the type must implement ICollection and the access must be public or protected.

Ekk
As an FYI, NHibernate requires you to use IList, which implements ICollection, so you'd have to use this same trick with NHibernate.
Kevin Berridge