views:

85

answers:

4

Solution setup:

  • DAL (class library)
  • BLL (class library)
  • Common (class library (some common functionality - enums, logging, exceptions,...))
  • Application1 (Windows Application)
  • Application2 (Windows Application)
  • WebApp (Web application)
  • ...

Let's say I have a Customer entity, which is:

  • a table in SQL server
  • a CustomerDataTable in DAL
  • a Customer class in BLL
  • a BLL.Customer class in all the applications

What kind of objects should BLL and DAL use for communication - DataTable or List<Customer> (for example)? In first case, BLL logic should transform Customer object to DataTable and send it to DAL. In secod case, DAL layer should be aware of Customer class, which is in BLL layer. But originaly DLL references DAL and not opposite...

Should I put all classes into seperate assembly, which is referenced by all others (Common, BusinessObjects, ...)? In this case I could use Customer class in all my projects.

Should I even bother to seperate DAL and BLL when I know, that only one BLL will use my DAL. In this case I could merge them together into one project.

PS - I am reading about DataTables and a lot of people say that we shouldn't use them at all. What are better options? Maybe it is time for me to learn some ORM mapping tools :)

+1  A: 

I would use the following pattern as it allows you to upgrade to a different persistence strategy later.

UI/Consumer  <--- (view models) --> BLL <--- Models ----> DAL/Persistence

Here the View models are consumed outside the BLL and models are communicated across the BLL/DAL layers.

In your case the model can be anything the DAL uses - DataTables for example or later perhaps ORM entities. The BLL is responsible to mapping between the model and view model.

As to keeping types in their own assemblies - yes for view models and in order to maintain a consistency, yes for the models as well.

Keeping the models and view models separate stops leakage of the persistence strategies outside of the BLL and thus permits future design changes to the persistence.

One advantage of this separation is that that different view model consumers can have differing view models for the same persistence model/entity. Some could be small and have few attributes and others large and rich in functionality. It also permits you to introduce offline/disconnectedness capability as the view models could be returned at differing times allowing you decide data merging strategies. This also allows you're persistence entities (e.g. tables to grow and change shape). Since this looks like a .net implementation things like AutoMapper will provide a lot of functionality out of the box

Of course this may be way overkill for your app - however I'd still maintain a BLL mapping that only talks view models to all BLL consumers. This should give you enough decoupling.

Preet Sangha
+1  A: 

Pushing the domain entities into the dal is an option that would remove the crcular dependency, but may not match your intent. This isn't unheard of, though; for example LINQ-to-SQL gnerated entities would live in the DAL.

Other options:

  • put them into a common lower assembly (but that may leave your BL rather empty)
  • use IOC to remove / reverse the reference between BL/DAL

There are no single right answers here.

Re DataTable; personally I agree - I'm not a fan ;) However, they can be used successfully and reasonably. But if I had to use them, I'd be keeping them in the DAL as an implementation detail - and not exposing them above that.

Marc Gravell
+1  A: 

it's hard to answer this general question without knowing the application domain well enough. I would start with thinking about where future changes are most likely and try to figure out from that where flexibility is required.

my following thought are just a suggestion. feel free to consider them and change/ignore what you feel is irrelevant.

separating the DAL from the BLL is almost always a good idea. the data scheme is one thing that should be encapsulated and hidden from the rest of the application, so leave your DataTables, DataSets, ORMs or any other solution hidden in the DAL. the BLL (and layers above it) should use simple data types (meaning simple classes). I think it would be a good idea to put those classes in a Model class library that has no references and can be used everywhere.

it feels like you have a bit too much layering...do you really need a Customer class in the BLL and another one in the Application layer? could be, but I would make sure and think it twice over.

from my experience in one of my recent project (a weather web site with 200K unique visitors daily), we used link2sql for data access (mostly read only data), and simple data classes all over our ASP.Net MVC application (of course as part of models/view models). it worked quite smoothly, and we could easily change the data scheme without breaking down other layers.

as for your last question about DataTables, these objects, should you decide to use them (I would vote against), belong solely in your DAL. they should not be exposed to other layers as that would create coupling to that specific class. what if tomorrow MS invents a much better class? would you switch over now that you have a gazillion references all over your projects to the DataTables, its method and properties? would be nicer to just change your DAL to work with the NewAwsomeDataTable class and the rest of your app is blissfully ignorant.

hope that helped :)

Ami
Re: ...do you really need a Customer class in the BLL and another one in the Application layer?... There is only one Customer class, wherever it is, sorry for misunderstanding :) That's why I wrote that Application uses BLL.Customer class and not just Customer class.
_simon_
+3  A: 

In my opinion you should have another Layer (seperate dll). Like "domain", where would you keep all entities like Customer. Then simply include in all higher levels(DAL, BLL, UI and others) in hierarchy this assembly.

Sample architecture can look like this:

(Database) <-> DAL <-> BL <-> UI

and on all levels you will have access to "domain" layer. DAL should return List not a DataTable. On some stage your development process you may want to use in DAL some OMR like NHibernate with would also return a List, probably.

klm_
I like this one. One question though - if I have Customer class in Model (or Domain, Entities) assembly, should this class also have all the methods, like GetAllCustomers, GetCustomer(int id),...? Or should the model have only properties and the methods should be in BLL?
_simon_
I would have the Customer class serve as a data entity only, so just properties and no methods like "GetAllCustomers". that method I would put in the BLL that would use the DAL to make the query.
Ami
In this case I could add partial classes to BLL, which extend my base classes from Model assembly and add them methods?
_simon_
No, GetAllCustomers, GetCustomer(int id) should be placed in DAL (where you will get them from database, fill in to entities like Customer and return to BLL). In 99% in BLL you will have a method like GetCustomer(int id) that will contain one line "return DAL.GetCustomer(id);" just to pass business data to UI. "domain" layer contains only business objects.
klm_
So classes in Model assembly should contain only Properties and constructor, everything else should be in BLL?
_simon_
Yes, in most of the scenarios. Sometimes in Model assembly you can put also some validation. But logic like filtering customers or creating reports should be in DAL/BLL. In general, everything what manipulates data should be in BLL
klm_