Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a layered architecture using Entity Framework, should I return POCO classes from the BLL? (Architecture guidance needed)

I've been reading too much probably and am suffering from some information overload. So I would appreciate some explicit guidance.

From what I've gathered, I can use VS2010's T4 template thingy to generate POCO classes that aren't tied directly to the EF. I would place these in their own project while my DAL would have an ObjectContext-derived class, right?

Once I have these classes, is it acceptable practice to use them in the UI layer? That is, say one of the generated classes is BookInfo that holds stuff about books for a public library (Title, edition, pages, summary etc.).

My BLL would contain a class BooksBLL for example like so:

public class BooksBLL
{
    ObjectContext _context;

    public void AddBook(BookInfo book) { ... }
    public void DeleteBook(int bookID) { ... }
    public void UpdateBook(int bookID, BookInfo newBook) { ... }

    //Advanced search taking possibly all fields into consideration
    public List<BookInfo> ResolveSearch(Func<BookInfo, bool> filter) { ... }

    //etc...
}

So, my ViewModels in my MVVM UI app will be communicating with the above BLL class and exchanging BookInfo instances. Is that okay?

Furthermore, MVVM posts on the Web suggest implementing IDataErrorInfo for validation purposes. Is it okay if I implement said interface on the generated POCO class? I see from samples that those generated POCO classes contain all virtual properties and stuf and I hope adding my own logic would be okay?

If it makes any difference, at present, my app does not use WCF (or any networking stuff).

Also, if you see something terribly wrong with the way I'm trying to build my BLL, please feel free to offer help in that area too.

Update (Additional info as requested):

I'm trying to create a library automation application. It is not network based at present.

I am thinking about having layers as follows:

  • A project consisting of generated POCO classes (BookInfo, Author, Member, Publisher, Contact etc.)
  • A project with the ObjectContext-derived class (DAL?)
  • A Business Logic Layer with classes like the one I mentioned above (BooksBLL, AuthorsBLL etc)
  • A WPF UI layer using the MVVM pattern. (Hence my sub-question about IDataErrorInfo implementation).

So I'm wondering about stuff like using an instance of BooksBLL in a ViewModel class, calling ResolveSearch() on it to obtain a List<BookInfo> and presenting it... that is, using the POCO classes everywhere.

Or should I have additional classes that mirror the POCO classes exposed from my BLL?

If any more detail is needed, please ask.

like image 819
ForeverLearnNeverMaster Avatar asked Apr 12 '11 15:04

ForeverLearnNeverMaster


2 Answers

What you're doing is basically the Repository pattern, for which Entity Framework and POCO are a great fit.

So, my ViewModels in my MVVM UI app will be communicating with the above BLL class and exchanging BookInfo instances. Is that okay?

That's exactly what POCO objects are for; there's no difference between the classes that are generated and how you would write them by hand. It's your ObjectContext that encapsulates all the logic around persisting any changes back to the database, and that's not directly exposed to your UI.

I'm not personally familiar with IDataErrorInfo but if right now your entities will only be used in this single app, I don't see any reason not to put it directly in the generated classes. Adding it to the T4 template would be ideal if that's possible, it would save you having to code it by hand for every class if the error messages follow any logical pattern.

Also, if you see something terribly wrong with the way I'm trying to build my BLL, please feel free to offer help in that area too.

This isn't terribly wrong by any means, but if you plan to write unit tests against your BLL (which I would recommend), you will want to change your ObjectContext member to IObjectContext. That way you can substitute any class implementing the IObjectContext interface at runtime (such as your actual ObjectContext), which will allow you to do testing against an in-memory (i.e. mocked) context and not have to hit the database.

Similarly, think about replacing your List<BookInfo> with an interface of some kind such as IList<BookInfo> or IBindingList<BookInfo> or the lowest common denominator IEnumerable<BookInfo>. That way you're not tied directly to the specific class List<T> and if your needs change over time, which tends to happen, it will reduce the refactoring necessary to replace your List<BookInfo> with something else, assuming whatever you're replacing it with implements the interface you've chosen.

like image 93
Joel C Avatar answered Nov 11 '22 14:11

Joel C


You don't need to do anything in particular... as Mark said, there is no "right" answer. However, if your application is simple enough that you would simply be duplicating your classes (e.g. BookInfoUI & BookInfoBLL), then I'd recommend just using the business classes. The extra layer wouldn't serve a purpose, and so it shouldn't exist. Eric Evans in DDD even recommends putting all your logic in the UI layer if you app is simple and has very little business logic.

To make the distinction, the application layer should have classes that model what happens within the application, and the domain layer should have classes that model what happens in the domain. For example, if you have a search page, your UI layer might retrieve a list of BookSearchResult objects from a BookSearchService in the application layer, which would use the domain to pull a list of BookInfo.

like image 36
Misko Avatar answered Nov 11 '22 12:11

Misko