Level of separation of database objects in DAL - c#

Looking for some general advice here.
Option 1.
Would it be best to have all of the main database objects (say Contact, User, Customer, etc. have their general classes in DAL with nested classes for db objects that depend on the main objects (ContactAddress, UserEmail, etc... these would have multiple values so they are contained in separate tables).
OR
Option 2.
Would it be better to have completely separate DAL classes for things like ContactAddress, etc. and combine these elements in a business layer?
Let me know if I'm not making sense here.

I usually define my objects in the business logic layer and do some translation between DAL objects and business objects. My DAL objects are usually autogenerated by some ORM framework (such as EF or LinqToSQL). The reason for this is that my business logic layer objects are not POCO's but also contains business logic, whereas the DAL objects are purely poco (although they may be decorated with some ORM logic).

It usually aids in discovery if you put all public classes at the namespace level (instead of as inner classes).
The two examples you cited, could be generalized with no harm:
ContactAddress becomes Address
UserEmail becomes Email
This way, you can reuse them later if you wish.

Related

Repository Pattern with multiple tables

Recently I have been reading up on using the repository pattern and DI to help create easily testable code, I think I understand it for the most part. However I'm having difficulty with one issue. I need to create a Rules object for my applications business layer. To create a rule, I need the ability to read and write to two tables. How would you go about implementing a repository that uses two tables for one object?
for example:
ICollection<type> GetAllRules();
What would I put in for type as it requires two tables?
Thanks
Steve
I wouldn't insist on having a repository for that.
As Fowler says
Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer.
This is probably why most implementations tend to expose pure domain objects rather than derivatives (which your Rule object seems to be).
I would have two repositories for the two tables you mention, then I would have a unit of work to expose all repositories and then I would have a business layer service responsible for the compound processing.
An advantage of such approach would be that the repository layer remains clean, there is no business processing involved here, no unclear rules introduced to the persistence layer.

How do you implement a business logic layer when using entity framework as data access layer?

Say i have 3 layers
layer 1: WPF Project (contains: xaml, viewmodels, mvvm framework)
layer 2: business logic layer (contains: plain c# classes)
layer 3: entity framework (contains: repository/data access classes)
when you dont want to expose your DAL(layer 3) to View(layer 1)
how do you implement the business logic layer well?
im having a hard time putting values back and forth the BLL objects and DAL entities.
can you please help?
Entity Framework doesn't work really well in a "disconnected" model. Unless something has changed, I've never been able to get it to work great easily.
You could use AutoMapper in Layer 2 to create ViewModels to present to Layer 1, but then you'd still have to send the changes back to Layer 3, which could be a pain.
If you're only developing a small app that will not change in the foreseeable, then just do whatever is quickest now. If you want a long-term maintainable app, then let me put forth the following.
The problem with this vertical layer approach is that whenever you need something in the view, you will have to add it to both the Business Layer (even if the business layer doesn't care about it), and the Data Layer. This requires your business layer to look like 1) UI views of the data 2) business views of the data and 3) the database representation of the data. That and/or you need a lot of mapping in-between layers. All of which dilutes business layer's actual purpose of representing business logic. What tends to happen then is that all the business logic gets migrated into transaction methods (that could just as well be static methods) to just change states on data objects. There's nothing at all wrong with that if your problem domain is nothing but CRUD with no complex logic. With complex logic, such business methods can get pretty tricky or even have undefined outcomes (because complex interdependencies on "fields" can be contradictory and hard to resolve).
Assuming you have complex logic, user views of data and business representations of data are often very different, and so UI views end up with specialized models of the data. If I were you, I just embrace this and use a simple version of the CQRS principle. That is, have the data for your UI views come from a different place than where your business operations are executed. In your case, I might have an EF Model in your DAL that only services your UI views, and gives them exactly what they need (whether by database views, stored procedures, or pre-compiled report tables). Then create a separate EF model that services only the needs for your Business entities. Then when you are ready to perform an actual business action, the UI's viewmodel action method can load the business object from the business EF model (or better yet, call an object factory from the business layer which does this) and run an appropriate action on the business object. Note that I'm also making the assumption here that your database is highly relational (mostly 2nd and 3rd normal form) and you are set on using EF.
I would not try to make your View Models into business logic. This makes your business logic not easily reusable on other platforms or applications (like web). MVVM should only service the UI. In my mind, the V (view) represents what the user sees and operates. The M (model) represents what the user chose on that view. And the VM (view model) translates between the two. Your program should then take the user's validated choices (UI model) and extract the needed data out of it to perform an appropriate business operation.
Instead of exposing all of your DAL to View Layer, just exchange your domain objects (EF objects) between all layers. The structure may be similar to the following:
Presentation Layer-------- ^
BLL --------------------------- | Data objects
DAL (Repositories etc.)--- |
So, all of your layers will be disconnected; but they will share the same domain objects. In real world, you can implement a similar structure by creating a seperate dll for Entity Framework entities which is shared by all layers. Note that ObjectContext shall be only visible to DAL (by default, entities and object context are generated in the same dll, you need to seperate this into two dlls).
In addition to the answer by Daryal, you can define your business-objects in your BL to be POCO's, and use EF in your DAL layer to read them from or persist them to the database.
If you define an repository-like interface in your BL (or unit-of-work, whatever naming you give it), and implement the interface in your DAL, then all you need is a little DI to get an instance of the repository-class without having to reference the DAL all the time. It works like a charm for me.
See here and here for more information.
Your ViewModels are your application in MVVM, so they should be handling things like data access through your Repository classes, or business logic (either directly, or indirectly using your validation classes).
If you don't want to directly reference the classes, use an Interface but be aware that you'll need to have some way of passing your inherited class to your ViewModel. I once did a project where we had a library of shared interfaces, such IRepository interfaces, and everything was imported/exported using MEF so the layers didn't reference each other directly.
The final (simplified) layout was:
Models -> Contained plain data objects that could do simple validation on their own data (length, min/max values, etc) but that didn't do any advanced validation or business logic. Did not reference any other library.
Common -> Contained interfaces, utilities, and other commonly shared classes. Referenced the Model library only.
DAL -> Contained Data Access and Repositories based on repository interfaces found in Common library. Referenced Common library for interface definitions and utilities, and Model library because it contained the data models used or returned in data access calls
ViewModels -> Contained application and business logic. Referenced Common for its utilities and interfaces, and Models for the data models
Client -> Contained Views. Referenced Models and ViewModels so it could write DataTemplates for both object types
Entity framework is suppouse to be used as "Logic Layer" by itself.
Your idea may have some sense, to use combine technologies.
Howevere, I think some of those Micros. libraries, where designed to be used separately, unless, otherwise explicitly combined & mentioned in their websites.
Good Luck.
I second daryal and I have implemented this in some projects. It is absolutely OK to use POCO as business objects.
Another approach instead of creating 2 projects (one for DB Context and one for Entities) is to use one DAL/DATA project only and reference it in BLL. Then inherit the POCO class in BLL and use that class in UI layer. Below is the basic sample code:
// assume this is EF generated POCO
namespace Owner.Project.Data{
public partial class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
}
}
// this is manually created class in BLL
using Owner.Project.Data;
namespace Owner.Product.Business{
public class StoreProduct : Product {
public bool Add (string productName){
// TODO - add product using EF as you normally do
}
}
}
Now you can reference the BLL in your UI project and use StoreProduct class there. To achieve loosely coupled pattern, Of course you could also inherit the StoreProduct class from an IStoreProduct interface and make use of it in UI or web service but that is another topic.

In which layer entities class must be defined?

When creating a Business Model in which layer (GUI, BLL, DAL) entities class must be defined?
Your entities are a part of your Business Logic. In your entities you define your business rules.
They should be ignorant of the type of Data Access you use. This can be done by using the Repository pattern. In your BLL you define your Repository interfaces which act on your entities. In a separate infrastructure project, you will define an implementation for the Repositories.
If you pass your entities to your GUI is a matter of choice. Sometimes it can be beneficial to use special crafted classes for passing data to your view but in a small project you could opt for passing your entities directly to your GUI.
You can define it in two places
Either create a new Layer Model/Entities (preferred)
or
Define them in Data Access Layer
I would say: in their own layer. The GUI, the business layer and the data access layer all use the entities. But the GUI doesn't depend on the data access layer, and the data access layer doesn't depend on the service layer. So entities must be in their own domain layer.
It depends from the way you want to use your entity. If it's simple POCO object, that used as DTO from db to you application, so i think that best place will be DAL. If you want to use your entity like part of business logic and it has some functional - so BLL will be the best place. But I don't think that there are some cases when it should be used and defined in GUI
I think that it's a good practice to have an ViewModel for any GUI purposes. Because when you use EF than it means that you interact with SQL somehow (in most cases). So you data is normalized. For there other hand many times you need denormalized data for GUI. That why i prefer to use ViewModel for GUI.

Communication between BLL and DAL

Solution setup:
DAL (class library)
BLL (class library)
Common (class library (some common functionality - enums, logging, exceptions,...))
Application1 (Windows Application)
Application2 (Windows Application)
WebApp (Web application)
...
Let's say I have a Customer entity, which is:
a table in SQL server
a CustomerDataTable in DAL
a Customer class in BLL
a BLL.Customer class in all the applications
What kind of objects should BLL and DAL use for communication - DataTable or List<Customer> (for example)? In first case, BLL logic should transform Customer object to DataTable and send it to DAL. In secod case, DAL layer should be aware of Customer class, which is in BLL layer. But originaly DLL references DAL and not opposite...
Should I put all classes into seperate assembly, which is referenced by all others (Common, BusinessObjects, ...)? In this case I could use Customer class in all my projects.
Should I even bother to seperate DAL and BLL when I know, that only one BLL will use my DAL. In this case I could merge them together into one project.
PS - I am reading about DataTables and a lot of people say that we shouldn't use them at all. What are better options? Maybe it is time for me to learn some ORM mapping tools :)
In my opinion you should have another Layer (seperate dll). Like "domain", where would you keep all entities like Customer.
Then simply include in all higher levels(DAL, BLL, UI and others) in hierarchy this assembly.
Sample architecture can look like this:
(Database) <-> DAL <-> BL <-> UI
and on all levels you will have access to "domain" layer.
DAL should return List not a DataTable. On some stage your development process you may want to use in DAL some OMR like NHibernate with would also return a List, probably.
it's hard to answer this general question without knowing the application domain well enough.
I would start with thinking about where future changes are most likely and try to figure out from that where flexibility is required.
my following thought are just a suggestion. feel free to consider them and change/ignore what you feel is irrelevant.
separating the DAL from the BLL is almost always a good idea. the data scheme is one thing that should be encapsulated and hidden from the rest of the application, so leave your DataTables, DataSets, ORMs or any other solution hidden in the DAL. the BLL (and layers above it) should use simple data types (meaning simple classes). I think it would be a good idea to put those classes in a Model class library that has no references and can be used everywhere.
it feels like you have a bit too much layering...do you really need a Customer class in the BLL and another one in the Application layer? could be, but I would make sure and think it twice over.
from my experience in one of my recent project (a weather web site with 200K unique visitors daily), we used link2sql for data access (mostly read only data), and simple data classes all over our ASP.Net MVC application (of course as part of models/view models). it worked quite smoothly, and we could easily change the data scheme without breaking down other layers.
as for your last question about DataTables, these objects, should you decide to use them (I would vote against), belong solely in your DAL. they should not be exposed to other layers as that would create coupling to that specific class. what if tomorrow MS invents a much better class? would you switch over now that you have a gazillion references all over your projects to the DataTables, its method and properties? would be nicer to just change your DAL to work with the NewAwsomeDataTable class and the rest of your app is blissfully ignorant.
hope that helped :)
I would use the following pattern as it allows you to upgrade to a different persistence strategy later.
UI/Consumer <--- (view models) --> BLL <--- Models ----> DAL/Persistence
Here the View models are consumed outside the BLL and models are communicated across the BLL/DAL layers.
In your case the model can be anything the DAL uses - DataTables for example or later perhaps ORM entities. The BLL is responsible to mapping between the model and view model.
As to keeping types in their own assemblies - yes for view models and in order to maintain a consistency, yes for the models as well.
Keeping the models and view models separate stops leakage of the persistence strategies outside of the BLL and thus permits future design changes to the persistence.
One advantage of this separation is that that different view model consumers can have differing view models for the same persistence model/entity. Some could be small and have few attributes and others large and rich in functionality. It also permits you to introduce offline/disconnectedness capability as the view models could be returned at differing times allowing you decide data merging strategies. This also allows you're persistence entities (e.g. tables to grow and change shape). Since this looks like a .net implementation things like AutoMapper will provide a lot of functionality out of the box
Of course this may be way overkill for your app - however I'd still maintain a BLL mapping that only talks view models to all BLL consumers. This should give you enough decoupling.
Pushing the domain entities into the dal is an option that would remove the crcular dependency, but may not match your intent. This isn't unheard of, though; for example LINQ-to-SQL gnerated entities would live in the DAL.
Other options:
put them into a common lower assembly (but that may leave your BL rather empty)
use IOC to remove / reverse the reference between BL/DAL
There are no single right answers here.
Re DataTable; personally I agree - I'm not a fan ;) However, they can be used successfully and reasonably. But if I had to use them, I'd be keeping them in the DAL as an implementation detail - and not exposing them above that.

Should POCOs be derived from DTOs or better not?

When creating an n-tier solution, I don't want to expose my business objects, but use DTO's instead of this. On the other side, I don't want to doubly define objects and write copy-code all the time.
Now my idea would be to write DTOs that contain all necessary fields and properties, but no logic (only state).
Then I would derive my business objects from those DTOs, extending them with my business logic, working on the DTO base classes properties. These objects also would be the objects persisted in the ORM used (NHibernate).
With that approach, on the server side I could work on the business objects and pass them directly to the client (they are derived, so down-castable). I would not be forced to expose my business logic that way and save a lot of code.
Do you think that approach is sensible?
Regards,
Sebastian
You may want to consider the following:
"...,
because keeping the DTO unaware of the
domain objects enables you to reuse
the DTO in different contexts.
Likewise, you do not want the domain
objects to know about the DTO because
that may mean that changing the DTO
would require changing code in the
domain logic, which would lead to a
maintenance nightmare.
The best solution is to use the Assembler pattern, which creates DTOs from business objects and vice versa. Assembler is a specialized instance of the Mapper pattern also mentioned in Patterns of Enterprise Application Architecture...."
from Pattern and Practice: Data Transfer Object
Also, I have not used it by myself, but you may want to check out AutoMapper as well.
Sounds reasonable to me. In Linq to SQL, business objects are derived from the DTO's by the use of partial classes.
"Then I would derive my business objects from those DTOs" Have in mind that DTOs might look different from BO they might contain properties from 2 or 3 BO

Categories

Resources