Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
211 views
in Technique[技术] by (71.8m points)

c# - How can I solve this NHibernate Querying in an n-tier architecture?

I've hit a wall with trying to decouple NHibernate from my services layer. My architecture looks like this:

web -> services -> repositories -> nhibernate -> db

I want to be able to spawn nhibernate queries from my services layer and possibly my web layer without those layers knowing what orm they are dealing with. Currently, I have a find method on all of my repositories that takes in IList<object[]> criteria. This allows me to pass in a list of criteria such as new object() {"Username", usernameVariable}; from anywhere in my architecture. NHibernate takes this in and creates a new Criteria object and adds in the passed in criteria. This works fine for basic searches from my service layer, but I would like to have the ability to pass in a query object that my repository translates into an NHibernate Criteria.

Really, I would love to implement something like what is described in this question: Is there value in abstracting nhibernate criterion. I'm just not finding any good resources on how to implement something like this. Is the method described in that question a good approach? If so, could anyone provide some pointers on how to implement such a solution?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

abstracting away the ORM will:

  • bring a lot of work of redefining it's API
  • make it impossible to optimise/batch database access
  • make it a lot harder to understand what queries are executed
  • will lead to tons of SELECT N+1

and all for very little value: the vague option to exchange the ORM framework which will most probably have a lot of other problems

  • missing features
  • subtle difference in implementation
  • learning curve

Update: experience

I was once involved in implementing a new provider of an existing DAL abstraction. It ended up performing badly, introduced a lot of bugs, Errorhandling was a mess and sometimes used stale data because the application assumed the default implementation. Reasons:

  • Caching does not know context
  • Cacheimlementation had different semantics
  • batching APIs too different to be abstracted
  • Errors are specific to implementation (e.g. FileNotFound -> FilesearchDialog is uselesss for a tcp/ip based databases)
  • Error recovery is different (each implementation has it's own set of errors it can recover from)
  • locking mechanism was different
  • no consistent change event in SQL-Databases
  • nested transactions
  • default implementation bleeded in Model classes
  • reimplementing all abstracted Queryies was a lot of work and introduced a lot of copy paste bugs
  • querying without explicitly stating the order will return different ordered results in different implementations

It took a lot of refactoring of the application:

  • strip out features only one implementation provides
  • Cachemanagement for each implementation
  • problem of Identity of Wrappers because of transient data
  • implement Queries over two datastores very hard

Additional points:

  • Migration of Data through the abstract DAL is slow as hell
  • implementing yet another implementation will never occur because of the above stated problems it is too expensive (In the mentioned scenario we began to slowly reimplement the whole project)
  • it was extreme difficult to implement the correct semantics of the DAL API because there is no context of use in the pure API

Porting (of business tasks) would have been a lot less painfull IMO as we did that for a few because of performance.

Update2: experience2: RoadBlocks while trying to port from NHibernate to EntityFramework (impl with NH but couldn't with EF 4 in reasonable time)

  • nested Transactions
  • Enum support
  • references with compositeId (how to get rid of referenceIds)
  • references in Components
  • read batching (Futures) which is handy for page + count in one go
  • mapping CultureInfo (IUserType support)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...