views:

150

answers:

2

Hi,

I'm facing several problems trying to apply DDD with EF4 (in ASP MVC2 context). Your advaice would be greatly appreciated.

First of all, I started to use POCO because the dependacy on ObjectContext was not very comfortable in many situations.

Going to POCO solved some problems but the experience is not what I was used to with NHibernate.

I would like to know if it's possible to use designer and to generate not only entities but also a Value Objects (ComplexType?). If I mean Value Object is a class with one ctor without any set properties (T4 modification needed ?).

The only way I found to add behavior to anemic entities is to create partial classes that extends those generated by edmx. I'm not satisfied with this approach.

I don't know how to create several repositories with one edmx. For now I'm using a partial classes to group methods for each aggregate. Each group is a repository in fact.

The last question is about IQueryable. Should it be exposed outside the repository ? If I refer to the ble book, the repository should be a unit of execution and shouldn't expose something like IQueryable. What do you think ?

Thanks for your help.

Thomas

+1  A: 

It's fine to use POCOs, but note that EntityObject doesn't require an ObjectContext.

Yes, Complex Types are value objects and yes, you can generate them in the designer. Select several properties of an entity, right click, and choose refactor into complex type.

I strongly recommend putting business methods in their own types, not on entities. "Anemic" types can be a problem if you must maintain them, but when they're codegened they're hardly a maintenance problem. Making business logic separate from entity types allows your business rules and your data model to evolve independently. Yes, you must use partial classes if you must mix these concerns, but I don't believe that separating your model and your rules is a bad thing.

I think that repositories should expose IQueryable, but you can make a good case that domain services should not. People often try to build their repositories into domain services, but remember that the repository exists only to abstract away persistence. Concerns like security should be in domain services, and you can make the case that having IQueryable there gives too much power to the consumer.

Craig Stuntz
Thanks for your response. Generaly I put obvious behavioral methods to the entities. When it's not obvious I create a service for that. How do you solve that point ? If repositories expose IQueryable so there is no guarantee that it will be disposed at any time or if it's disposed there will be issue while converting Iqueryable to List or Enumarable because the connection will be already closed.
Thomas Jaskula
Regarding disposing connections, the public face of my domain services is a unit of work object. The unit of work implements IDisposable. The unit of work keeps a private reference to an ObjectContext instance which is passed to the repositories via constructor injection. In my case, the unit of work is consumed by ASP.NET MVC Controllers, which are not themselves disposed until views have rendered, etc. So disposing everything at the correct time is quite natural; I never have to think about it.
Craig Stuntz
Regarding where to put business methods, I find it much more natural to put everything in domain services rather than some in domain services and others in different places. This is especially important when you use data services like ADO.NET data services/Astoria.
Craig Stuntz
+1  A: 

I think it's OK to expose IQueryable outside of the repository, only because not doing so could be unnecessarily restrictive. If you only expose data via methods like GetPeopleByBirthday and GetPeopleByLastName, what happens when somebody goes to search for a person by last name and birthday? Do you pull in all the people with the last name "Smith" and do a linear search for the birthday you want, or do you create a new method GetPeopleByBirthdayAndLastName? What about the poor hapless fellow who has to implement a QBE form?

Back when the only way to make ad hoc queries against the domain was to generate SQL, the only way to keep yourself safe was to offer just specific methods to retrieve and change data. Now that we have LINQ, though, there's no reason to keep the handcuffs on. Anybody can submit a query and you can execute it safely without concern.

Of course, you could be concerned that a user might be able to view another's data, but that's easy to mitigate because you can restrict what data you give out. For example:

public IQueryable<Content> Content
{
    get { return Content.Where(c => c.UserId == this.UserId); }
}

This will make sure that the only Content rows that the user can get are those that have his UserId.

If your concern is the load on the database, you could do things like examine query expressions for table scans (accessing tables without Where clauses or with no indexed columns in the Where clause). Granted, that's non-trivial, and I wouldn't recommend it.

Gabe