问题
To focus on the question here, we can say that I have one database layer and one application layer. So for the application to get access to the database I have to go through the database layer (of course).
Now the thing is that I want to write my queries using LINQ. And I could go two different paths here. One way [A] would be to create about 300 individual functions in the DBLayer, and call them from the Application (eg. GetAllUsers()
).
OR [B] the DBLayer could more or less just offer a DBContext and then I can run the LINQ queries from the Application Layer (DBContext.GetAll<Users>().Where(x => x...
).
I think that the [B] path would be more appealing, or at least less annoying since it wouldn't be so filled up with small functions. But what would you say?
However the problem with the [B] path is that, if I can avoid it I don't want to have a reference to NHibernate in the Application, but I don't seem to get access to the LINQ for NHibernate functions without referencing it. Is there a good solution to this?
回答1:
Option A with the mention what you don't need to create 300 functions, you need to create as many as required by the app needs. And some functions can get a Criteria which reduces the nubmer of functions.
The most important things is that all those functions will return app objects and NOT persistence objects, thus keeping the rest of the app decoupled form the persistence. Of course, the business/ui objects shouldn't know about NH either.
回答2:
The solution with LINQ (B) is of course preferable (in comparison with 300 individual functions described in solution A)
And in fact is very easy to do. Your Data layer will just publish the today's standard: IQueryable.
The native NHibernate LINQ provider will do that for you:
var query = session.Query<TEntity>()
is in fact returning the a var query which is IQueryable<TEntity>
So the Data layer contaract (interface IDao...) could be like this (below is the implementation)
public virtual IQueryable<MyEntity> GetQueryable()
{
var session = ....
return sesion.query<MyEntity>();
}
In this case, no upper layer will ever notice, that it is working with NHibernate. And could in fact in some cases recieve results of a different IQueryable
provider
EXTEND:
I would like also to append one (I even would say controversial) link, to Ayende block post: The DAL should go all the way to UI
A cite:
...My current approach is quite different. I define queries, which contains the actual business logic for the query, but I pass that query onward to higher levels of my application. Any additional processing on the query (projections, paging, sorting, etc) can be done. In that way, my queries are closed for modification and open for extension, since they can be further manipulated by higher level code...
While Ayende in general is not (at least at time of writing this article: Don’t castrate your architecture a fan of data, business, service layer... the logcic above is similar:
Pass the query (IQueryable) to upper layers. Apply some custome filters if needed (restrict the result more), but let the Client application (user) to work with it, to query your API
来源:https://stackoverflow.com/questions/21475616/how-to-organize-database-layer-using-nhibernate