3

I am trying to build a three tier architecture with UI, BLL, and DAL. I am using the Entity Framework with the repository pattern.

My question is: Are the Entities generated by the Entity Framework supposed to act as a part of my BLL or are these just DAL objects?

Reason for asking is because It feels like I am duplicating code. For example: I have a DAL.CatEntity which is generated by the Entity Framework directly from my database. This all fine and dandy. I then use my repository (which is part of my DAL) to pull data into a DAL.CatEntity. I then use this DAL.CatEntity in my BLL, pull out all of it's data, and transform it into a BLL.Cat. I then use this BLL.Cat in my UI layer.

Below is some super simplified code.

BLL

public Cat GetCat(string catName){
    CatEntityRepository _repository = new CatEntityRepository;
    Cat cat = null;
    CatEntity catEntity = _repository.GetSingleCat();
    cat = ConvertToCat(catEntity);
    return cat;
}

private Cat ConvertToCat(CatEntity entity){
    return new Cat(){
        Name = entity.Name,
        Color = entity.Color,
        //....
    }
}

UI:

public ActionResult method(){
    Cat cat = BLL.GetCat();
    //......
}

It seems unnecessary to have BOTH Cat and CatEntity. Can I just use my EntityFramework Entities as part of my BLL while using the Repository as my DLL?

Thanks.

Josh Claxton
  • 410
  • 4
  • 14
  • 2
    You may be better off using something like AutoMapper rather than creating your own custom mapping classes. A lot less effort involved. – Erik Funkenbusch Sep 08 '12 at 18:49

3 Answers3

3

Ultimately, whatever you do is up to you. Most apps are somewhere between ideal and horrible, in the land of pragmatic and practical.

What you need to do is look at the complexity of your app. The more complex it is, the more it will benefit from high degrees of separation. Often times the simplicity of the app just doesn't justify the large amount of work needed to create clear layers.

Having said that, in my opinion, in a large number of small to medium complexity apps, you can effectively treat your entities as business objects. In particular, if you make the entities POCO's and part of your business layer, then use those entities in your EF DAL, it can be quite efficient.

I would always caution, however, sending business or data objects directly to the UI. You should have dedicated UI objects that are translated between business and UI.

I think it makes the most sense to keep a strong separation between business and data when you might change your data access methods. For instance, if you think you may change to a web service to get your data rather than using EF directly. Also, strong separation of concerns helps a great deal with unit testing.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • Great points. My application is going to consist of a website as well as a separate web service. Both of these will need to access the same BLL. Furthermore, changing to use a web service to access my data is something that very well may happen in the future. Sounds like this minor duplication of code may very well pay off in the future. – Josh Claxton Sep 08 '12 at 19:00
  • @Kiwi: returning ef entities from repositories and converting them outside is one of worst approaches. If you want to convert, do it inside the repository and expose converted objects. Refer to Mark Seemann's Dependency Injection in .NET book. – Wiktor Zychla Sep 08 '12 at 21:55
2

If you feel that you are duplicating code then you probably don't need a service layer and your EF entities could act as business models. This is often the case with simple CRUD applications in which you don't need a business layer.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

An alternative approach is not to CONVERT between tewo types of objects but rather, create interfaces out of your domain entities and code your repositories against interfaces.

This way you bake two cakes in the same time. You don't convert your data layer entities to bll entities snd still you are not messing layers (in a sense that your repositories don't work on concrete data layer types).

This approach is suprisingly useful and yet rarely described.

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • I actually use a generic repository interface for accessing all my data. (I simplified the code above.) Is this what you were talking about? If so, I'm still not seeing how I wouldn't need to convert. – Josh Claxton Sep 08 '12 at 19:04
  • No. I talk about interfaces on your entities. For the Cat entity, create the ICat interface and code your repository against these domain interfaces. This way there's NO conversion as your EF classes will implement these domain interfaces. If someday in future you change the implementation of the repository, you will make your new domain classes implement the same domain interfaces. Also, it is easy to implement in memory repositories using in memory store and auxiliary domain classes implementing the same interfaces. And still, no conversion needed. – Wiktor Zychla Sep 08 '12 at 19:17
  • No conversion means that your code is cleaner and faster. And you still retain the benefit of not coding against concrete classes. The difference is that with your approach you code your bll layer against bll entities. In my approach, you code against interfaces. – Wiktor Zychla Sep 08 '12 at 19:19
  • @WiktorZychla - The problem with your approach is that it makes your data layer depend on your business layer, rather than the other way around. That's not necessarily a problem, but it is something to be aware of. – Erik Funkenbusch Sep 08 '12 at 19:35
  • @MystereMan: can you elaborate more on that? Why do you think there's a dependency? I don't see one. Domain interfaces are defined in the domain layer, one below the data layer, two layers below the bll layer. The data layer has NO awareness of the bll layer at all. – Wiktor Zychla Sep 08 '12 at 19:47
  • @WiktorZychla - you have some strange definitions. I've never heard of anyone claiming a domain layer below a data layer. The domain layer is typically the same as the business layer. – Erik Funkenbusch Sep 08 '12 at 20:09
  • @MystereMan: why do you discuss definitions now? I thought you saw a dependency which I don't see. We build applications with domain interfaces in repositories for some time now with success and frankly, I am really curious why people insist on expensive copying instead of coding against interfaces. I might blog on this soon. – Wiktor Zychla Sep 08 '12 at 20:16
  • @WiktorZychla - why do I discuss definitions? Because the usual definition of "domain" is "business", and when you said that your data layer implements "domain interfaces", the natural assumption was that you meant the data layer was dependent upon the business (ie domain) layer. I'm not sure how you don't understand that. Still, there are other issues here. For instance, when using certain technologies you do not want to pays the data layer object (the instance itself) to a vulnerable part of the app (like the UI). Using interfaces does not mitigate that problem. – Erik Funkenbusch Sep 08 '12 at 20:31
  • @WiktorZychla - Entity Framework auto generates my entities. Therefore, if I were to create an interface, I would essentially be copying over the datatypes of the entity. Which is what I am already doing with the BLL. I could see this maybe being useful if I need to use it more than twice, but I won't. I may be misunderstanding you, but this seems excessive for my needs. Especially if it means making another layer. – Josh Claxton Sep 08 '12 at 20:46
  • @MystereMan: true about this possible problem. I don't believe it is severe as you pass objects using interfaces but also I don't deny the problem exists. However, the problem with copying domain entities is that is it expensive. From the two possibilities, one just can pick up his favourite. – Wiktor Zychla Sep 08 '12 at 21:06
  • @kiwi: the same way your ef classes are autogenerated, your interfaces can be generated. Duplication is not an issue here. The issue is separation. You have only two options. Either you COPY your entities or you HIDE them behind interfaces. The remaining option, to not do to anything, is not a choice as you have your ef classes in the business layer which is against the reporitory pattern. You say you won't be doing it twice then why do you need the repository at all and not to code your bll against ef directly? If you are misusing the repository then why do you need it at all? – Wiktor Zychla Sep 08 '12 at 21:10
  • @WiktorZychla - My repository accesses my DB and returns the EF object. This EF Object is then manipulated in my BLL which will return BLL objects to be used by my UI. How is this misusing the repository pattern? If my repository starts returning BLL objects, I have broken the UI->BLL->DAL layering in which my DAL references my BLL. – Josh Claxton Sep 08 '12 at 22:31