Discussion Layering for an application using EF

  • Monday, January 14, 2013 1:48 PM
     
     

    I have been using EF since .NET 3.5 SP1 was released and is still using that flavour of EF. However I am going to start a new project (MVC 4 / EF 5) and want to take a new look how on the design as well as making use of new feaures in EF 5 (EF 3.5 is primitive in some aspects).

    Of course the traditional 3-layer design (presentation, business and data layer) will be used, but one thing I am thinking about now is what is really going into which layer. For example if we have a method which return all customers does that belong in the DAL or BLL? I don't think it is that clear where things belong especially not when you could for eample have a stored procedure which gets mapped as a method by EF or for that matter other ORMS which will let you create query methods by defining the query in UML/DSL. However a simple query might contain business rules/logic like for example "Only get customers which have active flag = true".

    If you want to really be independant (in your BLL) of the underlying data access method (i.e if you want to replace EF with something else) the BLL should not use the ObjectContext/DBContext directly and instead call methods in the DAL which carry out the actual calls to EF (or whatever you use). However that comes with a price, more complexity (if you need a new query to be calable from the UI you need to put the method in both the BLL and DAL) and if a query is only used once in the BLL then you don't save any coding anyway. Maybe having the dependance on EF (as long as you keep EF specific code out of presentation layer) and making it a bit harder to switch to another ORM is good enough.

    What we have done so far is to have a class (for exaple CustomerService)  for each entity (aggregated to useful level) and having methods for all CRUD operations and validation (I guess you might call it Request/Reply patttern). Every method is self contained (creating contect, returning object(s), disposing contect) so basically entitities are always disconnected from context. This works pretty well and one advantage is that it is easy to move the BLL into a seperate physical tier (like moving them into WCF services). The problem is that you might end up in "method hell" when the application need a lot of different queries, especially if you might want an option to load related entities or not (always loading related entities is bad for performance).

    How do you layer your application and what kind of code do you put in each layer? For example where do you put validation code (i.e. beyond basic validation like checking length, range etc and which might require a lookup like checking if customers credit limit has been reached, checking inventory level etc).

All Replies

  • Tuesday, January 15, 2013 6:32 AM
     
     
  • Tuesday, January 15, 2013 7:13 PM
     
     

    Yes I have seen that and the pattern I had been using is the Repository pattern. However not with unit of work which I don't like. Or actually have not been convinced it is better than having each method you call in your repository class(es) to be self contained and not sharing the context. The behaviour you will get will be dependant on EF (for example if you have one query returning only orders and another query returning customers then EF will map orders to customers automatically if sharing same context). If you change to some other data access method or maybe moving your business logic into a WCF service which you call from your presentation layer then it will behave different.

    However it does solve a lot of headaches sharing same context though. But I think I would only use that pattern if my repository/UoW classes is in DAL and I call them from BLL and not directly from presentation layer.

  • Thursday, January 17, 2013 2:02 PM
     
     

    Hi,

    I agree, EF as well as any other ORM is a  leaking abstraction, so if it anyway leaks, it is better to use this bad leaking lower-level abstraction in higher layers (just use context in BL) than place part of higher-level BL layer code within DAL (like a logic in repositories). In former case you have a design problem, but in the second - one more.

    As for validation - it is crosscuting concern, validation rules should be defined on as lower layer as possible and checked on as higher lever as possible. It means that  most of simple rules will be duplicated on several layers. .Net provides DataAnnotation for this approach and most of platform components including EF, WPF, MVC allows you to work with them in convenient way. Some rules, of course, could be limited to only one layer, such as complex business logic rules that looks more like business logic, not just data consistency rules.