3-tier architecture and data mapper - datamapper

i have an domain object at the BAL that should have a corresponding data mapper at the DAL. as known the data mapper class will hold presistance and retrieval methods like Update, Delete, FindById, FindByName etc.
i understand how those DAL methods should be used at BAL, but what about the UI layer, UI layer should not access DAL directly, so does this mean that i will have to add methods with the exact signature to the domain object class at BAL that should just pass the UI call of a certain database access operation to thier DAL counterpart methods? or what should i do to access DAL through UI?

The purpose of BAL is to perform other operations such as validation, logging, event handling as well. Also, if you plan to change the way you are going to persist data, such as using a web service instead of database, using a BAL abstract away that.

Related

Entity Framework 4.1 and T4 class generation. Is this design overkill?

I am trying to get some design validation on modeling a domain using EF4.1 and T4.
At design time I run a customized a T4 poco generator template that reads edmx and creates 3 partial classes:
1) domain-level class (where any specific business methods will reside). this is only generated one time. Once Gen'd it's owned.
2) poco class just properties and virtual navigation properties to related objects, loaded lazily. this can be regen'ed if/when any underlying columns in the database change.
3) metadata class with an internal class whose properties are decorated with data annotations to provide additional column-level validation before inserting / updating data.
Is this overkill? I liked the separation, namely between the poco and domain object so that I can add methods to the partial domain object at any time without having to worry about method loss when needing to rerun the T4 template after underlying data specs may change. What about the metadata class? Is that unnecessary if my application will be performing field validation?

Question about Domain Objects, A Service Layer, and Using Linq2SQL and ASP.net MVC with the Repository Pattern

First off, apologies for the long description of my brainspace below. I'm still wrapping my head around lots of these new ideas, so I'm sure I'm describing something incorrectly. Please feel free to correct me where I'm wrong.
We are in the R&D phase of a new ASP.net MVC2 site and want to ensure that we can 1) decouple our data store from our application, 2) allow for our application to be tested via unit tests and 3) allow us to change out our datastore or use something other than Linq2SQL down the line.
This seemingly simple goal has opened up a whole new world to me that includes the Repository pattern, IoC, DI, and all sorts of other things that are making my head swim. Here's what is so far coming into focus, or at least what I believe is a somewhat correct plan to reach our goals:
We will have a number of ISpecificRepository interfaces that define the contract between users of the interface and the underlying data store.
The SpecificRepository implementations will query specific datastores and return POCO representing our domain objects (or collections of them).
Our Service Layer will perform the application specific business logic using an instance of ISpecificRepository passed to the various service methods and pass these POCO domain objects back to our presentation layer.
As mentioned, we are planning on using Linq2SQL to implement our specific repositories for the application and have decided to decouple our service layer from this implementation by creating the POCO for our domain objects and create a mapping to and from these objects to the LINQ generated entities. In the service layer, we can then create business logic to query the repository, add data, and do whatever else we need to do for each use case. This seems fine but my concern is that since we're using Linq2SQL, our specific Linq repository implementation will now have to house all of the many Get queries that the service layer requires to implement the business logic efficiently.
I'm curious as to whether this somehow breaks the Repository pattern since we're now housing application specific logic not in the service layer but in the repository instead.
The reason I feel that we need to do it this way is so that I can write more efficient Linq queries on my specific Linq repository using various DataLoadOptions, etc. without returning IQueryable from my repository up to my service layer, where it would seem that sort of logic actually belongs. Also, all of the example IRepository interfaces I've seen seem very lightweight and only provide a few methods to GetByID, GetAll, Find, Insert, Delete, and SubmitChanges to the underlying data store. In my case, it sounds like my specific repositories will be doing a great deal more than that.
Thanks for reading this far. Any and all help that can clarify my misconceptions would be greatly appreciated.
-Mustafa
our specific Linq repository
implementation will now have to house
all of the many Get queries that the
service layer requires to implement
the business logic efficiently.
I'm curious as to whether this somehow
breaks the Repository pattern
Not at all. A Repository is a collection of domain entities. If I have a Repository of Accounts, it is perfectly reasonable to want Accounts.ThatAreOverdue().
I personally prefer fluent naming. Accounts.ThatAreOverdue() feels better than AccountRepository.GetOverdue() .. but I suppose that is a point of preference.
Also, all of the example IRepository
interfaces I've seen seem very
lightweight and only provide a few
methods to GetByID, GetAll, Find,
Insert, Delete, and SubmitChanges to
the underlying data store.
A Repository interface can be thin. Find is meant to be used with the Specification pattern. Encapsulate the criteria in another object. The implementation of the criteria can be passed Linq2Sql objects from which to query - but it will be more difficult to re-use the criteria classes against in-memory domain objects (versus in database, where Linq2Sql is involved).
Our Service Layer will perform the
application specific business logic
using an instance of
ISpecificRepository passed to the
various service methods and pass these
POCO domain objects back to our
presentation layer.
Are you saying that your logic will all be in Services and the "domain objects" will be bags of properties and bound to in the view?
I don't think I'd recommend that.
If the same object that is used in the application logic is also used in the view, then you have tightly coupled the two application layers and experience says that causes problems. It will be very difficult to maintain coherence in the Services and Domain through changes if the View uses the same objects. The View will need pieces of data and they will inevitably get stuck onto places they don't really belong in the domain.

Data Repository - business objects?

I'm reading the book "ASP.NET 3.5 Social Networking - Andrew Siemer" and I got confused when he uses Repositories to access the data.
Here is the idea of his code:
public interface IAccountRepository
{
Account GetAcountByID(int acId);
void SaveAccount(Account account);
List<Account> GetAllAccounts();
}
public class AccountRepositoryLINQ : IAccountRepository
{
Account GetAcountByID(int acId){
..... LINQ query .....
...... return.....
}
void SaveAccount(Account account){
..... LINQ .....
}
List<Account> GetAllAccounts(){
..... LINQ query .....
...... return.....
}
}
The class "Account" is the one generated automatically on the "LINQ to SQL Classes".
Some of the problems I see:
1º
I code my business layer, GUI, etc... and later in time the table Accounts in the database is changed (example: change the name of one column), then I need to rebuild the "LINQ to SQL Classes" and all my code layers will need to be recoded because my "Account" object changed.
2º
If I need to have other repositories (MySQL, Oracle, XML, other), what "Account" class will I use?
What to do?
Shouldn't I use a custom Account class? This will be used in all application layers.
How do the mapping from LINQ to my custom Account class?
Using simple "myClass.Name = linqClass.Name;" ???
Isn't this consuming machine resources if I need to "map" all the classes?
There isn't a easiest/lightest way to do it?
Is this the correct approach? Is there other ways?
Good instinct..
My suggestion is to abstract away the LinqToSQL objects, and create a set of Business Domain Objects. Then the Repository can query for the needed data and map them to the Domain objects that your application uses, and return those. Now your Data Access layer is decoupled from your application, and you can now do all of the things you listed.
The mapping can be a pain, so look at tools like Automapper to accomplish this.
I have a love hate relationship with LINQ to SQL classes myself, but I thought I'd play devils advocate :-), firstly addressing the points you made:-
1º I code my business layer, GUI,
etc... and later in time the table
Accounts in the database is changed
(example: change the name of one
column), then I need to rebuild the
"LINQ to SQL Classes" and all my code
layers will need to be recoded because
my "Account" object changed.
The general approach is that you'd add behaviour to the partial classes generated by LINQ to SQL, these files won't be replaced when you refresh a table from the data context. If you change the name of the column and don't want to change the rest of your code just update the class in the designer to use the old column name?
Even if you used POCOs for persistence with NHibernate for instance you'd still need to change the mapping so I don't really see this as an issue.
2º If I need to have other repositories (MySQL, Oracle, XML, other),
what "Account" class will I use?
Personally I'd call YAGNI on this one, if you really anticipate needing support for multiple databases LINQ to SQL might not be the best solution to start with in any case (simply to keep your infrastructure consistent across the application), tools like NHibernate would have far better support for such situations.
Moving on to adding a custom account class, mapping code can be taken care of by tools like AutoMapper, though this might mean you give up things like lazy loading (which may or may not be a big deal to you).
In the end it can be quite empowering to have full control over your entities (e.g. not having to use a parameterless constructor, control over instatiation etc, simple user types that map to one or two columns) and if you feel that your application might benefit from this it's probably the way to go, but you will pay the price in the repository implementation which will be complicated by mapping code and handling whether things need to be updated / deleted / inserted.
A good middle ground might be to simply code to an interface (e.g. IAccount) this should define the properties and method you expect from an account. Your repository would then become
IAccount GetById(int accountId);
You'll then give yourself freedom over what the implementation is (i.e. whether it's implemented by a LINQ to SQL class or a projection / mapping) and if you do opt for a custom class in future it'd be a simple case of moving the implementation to that class and altering the repository implementation.
In the end it's down to the application, if you think it's going to end up a huge application with extremely complex business logic by all means I would opt for a segregated domain layer that at least tries to be persistence ignorant. If, however, it isn't and opting for the repository pattern is simply a means to achieve good testability and a simple abstraction above your data access. I don't see why explicitly referencing LINQ to SQL classes and using them as a simple domain layer is such a big deal.
I personally use a combination of NHibernate and FluentNHibernate and seperate my domain(business objects) from all other things. I use messages from my other layers, like a GUI, to my domain which has a handler which injects repositories inside that hydrate the object(s) in question and perform the business logic, the interfaces in the repositories above are a nice way to decouple if you want to use other implementations of repositories or data access.

Which layers should speak Domain Models?

Let's say I have a method like this in my business layer:
// This is in the business layer
public Result DeleteSomeDomainObject( ???? )
{
//Enforce business logic here.
//Delete records in the database
DAL. DeleteSomeDomainObject( ??? )
}
// This is in the data access layer
public Result DeleteSomeDomainObject( ???? )
{
// Delete records from the database.
}
Should these methods take instances of the domain model or just the primary keys?
I struggle with this often. I usually say that your business/service layer should take domain objects as parameters.
If we are talking web, your web tier will have the ID. It will likely instantiate or retrieve an instance of the object from the service layer. So it makes sense to pass it to your service layer.
However, there are often times where you would end up duplicating the retrieve of the object. Sometimes your services will be loading an object anyways because of some additional data not captured in the web layer. I've even had times where the data access layer has to load objects for dependencies. Caching can solve some of these issues and re-architecting your data/model can fix others. Certainly. But sometimes, in light of performance or other issues, passing an ID just makes more sense.
To summarize, prefer passing domain objects to the business tier. But realize that for other reasons, you might be better off passing an ID and, unfortunately, there needs to be exceptions to your rule.
Anywhere that's reasonable, it makes sense to decouple the policy from the implementation. I would say that if you plan to use some sort of ORM, pass instances of your business objects.

Data Mapper Pattern

Up until now I've been using Active records in all my c# database driven applications. But now my application requires my persistence code being split from my business objects. I have read a lot of posts regarding Martin Fowler's data mapping pattern, but my knowledge of this pattern is still very limited.
Let's use the following example:
If I have 2 tables - Customer and CustomerParameters. The CustomerParameters table contains default Customer values for creating a new Customer.
I will then have to create a CustomersMapper class to handle all of the Customer persistence. My Customer and CustomersList class will then collaborate with this mapper class in order to persist customer data.
I have the following questions:
How would I transfer raw data TO & FROM my Customer class to the mapper without breaking certain business rules? DTO's?
Is it acceptable to have a SaveAll and LoadAll method in my Mapper class for updating and loading multiple customers' data? If so, in case of SaveAll, how will the mapper know when to update or insert data?
Will the Customer mapper class be responsible for retrieving the default values from the CustomerParameters table as well, or will it be better to create a CustomerParameters mapper?
A O/R mapper tool is not really here. The database I'm using is Transactional and requires that I write my own Mapper Pattern.
Any ideas and comments will be greatly appreciated.
Shaun I would answer your questions this way:
ad 1) Mapper is responsible for creating Customer object. Your Mapper object will have something like RetrieveById method (for example). It will accept an ID and somehow (that't he responsibility of the Mapper object) construct the valid Customer object. The same is true the other way. When you call Mapper.Update method with a valid Customer object, the Mapper object is responsible for making sure that all the relevant data are persisted (wherever appropriate - db, memory, file, etc.)
ad 2) As I noted above retrieve/persist are methods on Mapper object. It is its responsibility to provide such a functionality. Therefore LoadAll, SaveAll (probably passing an array of value objects) are valid Mapper methods.
ad 3) I would say yes. But you can separate various aspects of Mapper objects into separate classes (if you want to/need to): default values, rule validation, etc.
I hope it helps. I really suggest/recommend you to read Martin Fowler's book Patterns of Enterprise Application Architecture.
I would suggest that you take a look at an O/R-mapper tool before you try to implement the Data Mapper pattern yourself. It will save you a lot of time. A popular choice of O/R-mapper is NHibernate.
You could check out iBATIS.NET as an alternative to NHibernate. It's also an O/R tool, but I've found it to be a little easier to use than NHibernate.
http://ibatis.apache.org/