1

I used Entity Framework 4.0 for creating my Data Access Layer. Then I found that my Business Logic Layer has the same objects as DAL but with some extensions (i.e, more properties, some functions, and data validation at setters...).

I planned to have DAL and BLL in separate projects and was looking for best practice to use entity classes in BLL and prevent redundancy in code.

As I searched and there are two major ideas:

  1. extending entity classes inside the same project by partial classes
  2. Using interfaces (implemented by entity class and relevant BLL class). Former is more popular among programmers.

Disadvantages for above solutions:

  1. We need to add the code at the same project as part of the partial class. This is good for adding properties and methods but it's not good for overriding something (i.e, adding validations before setting a property at Business Logic Layer)
  2. If the entity model is changed, we need to manually extract the interfaces from entity classes again and also another change in BLL related class is needed (two manual work around).

My question is why we simply doesn't inherit our BLL classes from relevant entity classes and extend/override their methods and properties ?

Xaqron
  • 29,931
  • 42
  • 140
  • 205

1 Answers1

4

One thing that you need to keep in mind is that ORM's like the Entity Framework don't actually create a simple data access layer (when viewed through the general 3-tier architecture). What they give you is much more of a business layer with a slightly more granular level of control over the data access interaction. I think it can be argued that EF essentially becomes your DAL and the context and entity types can be the BLL.

The line's a lot easier to see when viewed through more of an MVC or MVVM architecture, where you have a model (your EF layer), a controller or viewmodel (where the business logic sits, which encapsulates the model), and a view.

Anyhow, because EF actually has to instantiate the entity types directly, inheriting wouldn't do you much good because EF won't use your subtype as the returned entity. The solution for validation and similar tasks in EF is to make use of both partial classes (which you obviously know about) and partial methods. The default code-generation templates in EF produce partial methods for all scalar properties for OnPROPERTYNAMEChanging and OnPROPERTYNAMEChanged.

For instance, if you have an int UserId property on your User entity type, you can create a partial class that looks like this:

public partial class User
{
    partial void OnUserIdChanging(int newUserId)
    {
        // do something
    }

    partial void OnUserIdChanged()
    {
        // do something
    }
}

You can, of course, only use one or the other if you like. The advantage that partial methods would have over an inherited call (assuming it was even possible) is that partial methods are non-virtual (so there's no virtual table lookup to call the correct member) and are only compiled as part of the class if there's an actual implementation.

In other words, even though you can go into the designer code and see the declarations for

partial void OnUserIdChanging(int value);
partial void OnUserIdChanged();

If you don't actually add a method body to the function, then the C# compiler completely removes the function and all calls to it from the code, as if it had never been there in the first place. This makes the types smaller and the calls to other properties faster, since it won't have to bother with calling an empty function.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • As you mentioned like `MVC` where the controller encapsulates the mode, I want to encapsulate entity classes at a higher level of abstraction in a separate project. I still can pass new class to entity framework since inherited class is a type of base entity class. I'm not gonna make any change to EF generated code (entity classes). I need my own `BLL` and want to keep EF generated code unchanged. I don't want EF to return my subtypes. – Xaqron Feb 10 '11 at 22:20
  • @Xaqron: The point is that MVC and similar architectures work via *encapsulation*, not *inheritance*. If you want to adopt an approach like that it's perfectly fine, but inheriting from the entity types themselves is generally not the way that's done. – Adam Robinson Feb 10 '11 at 22:55