BL, DAL, DTO = model

Apr 26, 2012 at 1:08 PM

Hallo,

as I mentioned, I am going to convert a old Delphi app to .NET/WPF. I want to have a clean seperation of concerns, so I'm going for a 3 Layer architecture.

I want to use DAL seperated from BusinessLayer, because of the different dataprovider it has to implement (Some data from COM, ORM, Datasets...). I thought about a DTO model which gets it's data filled by any dataprovider (IDataprovider) and then passes it to BL/MVVM Model?

But this would be some kind of have the "model" 3 times declared (ORM entity, DTO, MVVM Model). Can I use the dto directly as model in the business layer and put the business logic (DataBaseObject, Validation,..) in the dto classes?

Thanks,

Mark

Coordinator
Apr 26, 2012 at 1:17 PM

Very strictly, you can't. Because a DTO is a Data Transfer Object and should not contain any logic. But maybe it's not a DTO at all, because you use them as models. This model is the centralized representation of data for different persistent store services and can therefore be called a model.

In a case where you have so many data services, I would also create a single model class which contains the validation. However, keep in mind that this model is probably merged client side? I would go a step further and merge all this data on the server. Then there is only one model all the client interacts with, and you can share the validation logic on both the server and client. Only the server is responsible for dispatching all data to the right target persistence store which makes it easier to hook other systems in as well (SL, html, mobile, etc).

Apr 26, 2012 at 1:49 PM

Yes, model data can be merged data (from different dataproviders).

So simply, I declare a single model (with all logic) in business layer. The DAL creates directly objects of this models and just pass them and the provider themselves care of converting. So no need of dtos and any kind of model mapping?

But then the DAL need knowing about the BL models? I this not a wrong way? Or am I missunderstanding sth.

Coordinator
Apr 26, 2012 at 2:25 PM

You need a helper class (on the server) which can fill the model with data and retrieve it afterwards again. Then all your clients can work with a single model object which contains all the data.

May 3, 2012 at 12:18 PM
Edited May 3, 2012 at 12:18 PM

At the moment there is no Client/server. I just have one physical machine, except of DB Servers. Just for future I want to be prepared to to seperate the layers into real tiers.

I read your article about MVVM and 3 tier and the diferent situations (good, wrong,.. ).

This I want to go: UI -> BL (.dll) -> DAL (.dll)

In the article you wrote about "the fact that the business layer provides DTO objects that are used as Models",..., "The DTO objects are defined inside the BL so the BL is responsible for translating entities from the DAL into DTO objects which are accessible from the UI layer."

I Would go for this way: UI -> BL (model) -> DAL (DTO, don't care about the name "dto"). With a mapping between models and dtos. So BL has to transfer dto object to model and backwards.

First of all is this the normal way to handle this behavior? Because you wrote to use DTO as Model in your aticle.

Now I am a bit confused. If the models are defined in the bl and the dal returns directly such models, your sugested helper must reference DAL and  BL. So I have something like a very wrong situation?

 

And the next queation: Often I hear about CRUD should be in the ViewModel. If I have such architecture like UI (view/VM)-> BL -> DAL, shouldn't this stuff lies in the bl? How would the border between BL and viewModels look like?

 

Coordinator
May 3, 2012 at 12:42 PM

The term DTO seems to be handled differently by everyone, but most people treat a DTO as a model. However, in your case you can combine the DAL object (let's call this the entity) and the BL object (let's call this the model).

Most people simple combine the DAL and BL because the entity supports everything a model should (like IDataErrorInfo, INotifyPropertyChanged, etc). The helper class that transforms stuff should be located in your BL. This way, the DAL project will never have a reference to the BL project.

The actual question you should ask is: does the DAL project provide enough support to treat it as a model. For example, when you use Entity Framework or LLBLGen Pro, you can use the DAL entity as model. However, at first you stated that the data would come from several sources so that's why I came up with the idea for the BL itself.

May 3, 2012 at 2:11 PM
Edited May 3, 2012 at 2:34 PM

No the DAL doesn't provide enough support for using direct model. Maybe I had missing sth. in my explanations:

Because I have several ways to get the same object data. Let's say I have Orders. There can be orders from COM/Delphi app. So I have a COM Order Object defined in my DAL. This can't be the same as the model, because COM isn't aware of Generics e.g. (no collections, nullables).

Because in future the data should come from e.g. the entityFramework, I then have the entities objects, which of course I can use directly. But at the moment I have no fully supported object.

So I thought to make a Interface IDataProvider in the dal with sth. like:

 

DALOrder[] GetALLOrders() 

 

and implement this in ComDataProvider and EntityDataProvider. Where the Com object and the entity object get mapped to the dal object (which supports of course generics,...). So in future I just have to change the provider and still get the same object types (dalObjects = my dtos).

In BL I would have my model and call the dal GetAllOrders() and map the result to the model.

What do you mean with "why I came up with the idea for the BL itself."? Combine BL and DAL in one project? This is how I would understand to have just one model class, and no DALObjects, so I can transform the com object into my model and later the entity class.

Do you mean it this way? If not, can you give a short example please.

Coordinator
May 4, 2012 at 3:53 PM
Edited May 4, 2012 at 3:54 PM

For normal situations, you don't need a separate BL because these days, the DAL and BL are combined. For example, in the "old" days, the DAL objects were responsible for saving/loading from/to a datastore. It did not contain any validation whatsoever. However, nowadays the DALS contain so much info because developers were writing too much "dumb mapping code".

In your case, you don't have a clear DAL which can be re-used. In your case, it is good to have a model and a provider which provides the model. In your situation I would indeed create a custom model Order which can be returned by the IOrderService.

Then, you can also implement all validation in this model. The fact that the model uses data from COM should be invisible to the code using the services. So, I would simple create this in the BL. Later, when you switch to entity framework, the entities will be used instead of your custom classes.

You *can* re-use the same objects later when using EF, but keep in mind that you will have to write a lot of mapping code (from entity to your DTO and back). I would consider letting them all implement an interface and in a later stage use the EF entity alone (not your DTO, what's the point of this?).

Then there is 1 issue: how to create new entities? You can't simply create a new Order object (which will behave differently in the future). You can create a "CreateOrder" method on the Order service which returns IOrder. When you switch to EF in a later stage, you only have to change the implementation of the IOrderService, nothing else.

I must say that this issue goes beyond the scope of MVVM, and this is more of an application wide architecture discussion. So, keep in mind that the IOrder will behave as the model in MVVM.

May 7, 2012 at 7:46 AM
Edited May 7, 2012 at 7:49 AM

Thanks for your answers, that's really amazing. You are right, I am not using dtos any more. I have an interface IOrder which lives in the DAL and all objects implement this. So my ComDataProvider returns only IOrders (ComOrderModel). Then in BL I have a class OrderService (with public ObservableCollection<OrderModel> GetAllOrders()), which calls the DAL's IDataProvider and maps the IOrder objects to a my OrderModel objects which than gets validation and the all other stuff like MVVM behavior. So I would have only mapping between my ComModel and the OrderModel. That was the way I thought to do it before reading your post.

But now, I am a bit confused. I still have questions...

Where does IOrderSrervice live, in BL or DAL? Maybe you mean this the same way as I my IDataprovider? Just different names?

 

I understand your post to use directly the ComOrderModel: IOrder as model in the MVVM? But how to add the validation, ... to this model. Make it partial, map it? Or just write the Code to the in the DAL living ComOrderModel?

May 7, 2012 at 12:18 PM
GeertvanHorrik wrote:

...You *can* re-use the same objects later when using EF, but keep in mind that you will have to write a lot of mapping code (from entity to your DTO and back)...

For mapping code AutoMapper (http://automapper.org/) is a great solution.

Coordinator
May 7, 2012 at 12:34 PM

@GEERTD:

excellent tip, thanks for that!

@mrmiagi0101:

The OrderService is a DAL service, which is reponsible to provide the right items. I recommend only to use the ComOrderModel if that supports:

1) IDataErrorInfo

2) IEditableObject

3) INotifyPropertyChanged

If not, you should create a separate model that does this. So, only if the DAL object cannot be treated as a model, create a separate model. Otherwise, simply re-use the DAL object as model. The DAL also contains the BL in that case.

May 7, 2012 at 1:56 PM

@GEERTD: Yes, I already use it, very nice tool.

@Geert: Yes, that was the way I unterstand it. Thanks for you help.