views:

487

answers:

3

Hi,

Whenever I read an article on linq to entities, I sounds like I should embed my business logic in the generated entity-classes.

This would means that the "user" of the business-objects (controller, service-layer, ...) would have to know about the datacontext-object that's needed to use linq.

It would also mean that the DAL-logic and the business-logic will be mixed up.

A lot of microsoft examples use some kind of DTO-approach. I'm not a big fan of the DTO pattern.

So should I let the business-object encapsulate the linq-entity and provide access to it using properties, or should I stick with the DTO pattern?

What are your suggestions?

Thanks

A: 

I wouldn't edit the generated files as they are likely to change.

What you could do is wrap them some query object and pass that around.

ayende makes a very good point about where the DAL should really live

Also, you should be a fan of viewmodels/dtos ;)

Andrew Bullock
So do you suggest that I should create a bunch of "stateless" manager classes that use the query-object (like the microsoft examples)?Or should my business-classes contain an instance of the query-object and expose this to the underlying layer? This way I could have a save method, load method, ... on the business object.
persistence has nothing to do with business logic. When you say "linq to entites" do you mean "linq to sql" rather than "linq to objects"? if so then i really wouldn't use the auto generator tool, just edit the xml yourself or use fluent linq2sql. Then your entities can be almost POCO and can have business logic on them along with your service classes. bear in mind linq2sql has been dropped by ms because it sucks.
Andrew Bullock
He is obviously talking about linq2entities, not linq2sql. Additionally linq2sql has not been dropped because it "sucks". Microsoft has chosen to focus on the Entity Framework and combine the two diverging efforts into one.
Chrisb
By linq to entities I mean the former ADO.net entities framework. It's comparable to linq to sql, but has more advanced mapping capabilities (not 1:1 with db, more like nHibernate, ...). It should be the "successor" of linq to sql.You can compare it to nHibernate. But still, the question remains, should I embed my bus-logic in the partial classes of the entity model, or should I create an additional layer? And should this additional layer be stateless (static methods) or statefull (like in traditional OO)?Thanks
This is a question I have not answered for myself yet. Personally, I am hoping the ability to leverage the database schema is added to the framework. It would be nice to be able to use it for validation. For now I am going the service layer route.
Chrisb
+2  A: 

The entity model generates partial classes. In a project of mine I'm using an entity model inside a class library and added a few .cs files to it that add functionality to the default entity classes. (Mostly functions related to error and message logging to a database table and a method to import/export all data to XML.)

But true business logic is located in a second class library that refers to this entity class library.


Let's explain. First I created an entity model from a database. It contains a list of company names and addresses. I do this by choosing "New project|Class library" and then add an ADO.NET Entity Data Model to this library. The Entity model will be linked to my SQL Server database, importing the tables I need and auto-creates classes for the tables I want to access. I then add a second .cs file for every table that I want to expand. This would be a few raw methods that are strongly linked to the database. (Mostly import/export methods and error logging.) This I will call Entity.Model, which will compile to Entity.Model.dll.

Then I add a second project which will contain the business logic. Again, I use "New project|Class library" to create it and add Entity.Model.dll to it's references. I then start writing classes which will translate the database-specific classes to more logical classes. In general, I would not have to make many changes except that I will protect or hide certain fields and add a few calculated fields. The business logic would only expose the functionality that I want to access from my client application and not a single method more. Thus, if I don't allow the client to delete companies then the "Delete" function in the entity model will not be exposed in the business layer. And maybe I want to send a notification when a company changes their address, so I'll add an event that gets triggered when the address field of the company is changed. (Which will write a message log or whatever.) I'll call this business.logic and it compiles to Business.Logic.dll.

Finally, I'll create the client application and will add a reference to Business.Logic.dll. (But NOT to the entity model.) I can now start to write my application and access the database through the business layer. The business layer will do validations, trigger a few events and do whatever else in addition to modifying the database through the entity model. And the entity model just serves to keep the database relations simple, allowing me to "walk through" the data through all foreign links in the database.

Workshop Alex
Thanks for the answer,but how does the second class library "use" the entity model (look at my comment on the previous answer).
The entity class library is a public class. It is added to the references of the second class and by using the entity class namespace in my second class. Both class libraries compile to .DLL assemblies. I'll add a longer explanation to my answer above.
Workshop Alex
+1  A: 

I prefer to wrap calls to the entity classes in business classes. (Call it BC for short.) Each BC has several constructors, one or more of which allows the context to be passed to it. This allows one BC to call another BC and load related data in the same context. This also makes working with collections of BCs that need a shared context simpler.

In the constructors that don't take a context, I create a new context in the constructor itself. I make the context available through a read-only property that other BCs can access.

I write using the MVVM pattern. The nice thing about this approach is that so far I have been able to write my viewmodels without ever refering to the data context, just the BCs that form my models. Hence if I need to modify my data access (replace entity framework, or upgrade to version 4 when it is out of beta) my views and viewmodels are isolated from the changes required in the BCs.

Not sure this is the best approach, but so far I have liked the results. It does take tweaking to get the BCs designed correctly, but I end up with a flexible, extensible, and maintainable set of classes.

RB Davidson
Thanks for the response. Do you expose the data as properties on your BC, or just expose the results of your queries using some kind of method (like GetCurrentData()).
I expose specific properties/fields of the entity objects that I need access to, and no more. If I don't need to expose a field or property of an entity object outside the BC I don't create a public or even protected property or method for it. I often create private properties/methods to encapsulate internal logic better.
RB Davidson