在使用LINQ to SQL时,如何抽象出持久性代码?

时间:2021-01-21 07:32:45

I love LINQ to SQL but it has been bugging me that in using it, my repository code becomes generated by the LINQ to SQL framework and hence tightly coupled to an SQL Server database.

我喜欢LINQ to SQL但它一直困扰我,在使用它时,我的存储库代码由LINQ to SQL框架生成,因此与SQL Server数据库紧密耦合。

Are any of you using LINQ to SQL in an abstracted, loosely coupled fashion and if so, how did you approach the problem of keeping your code database-independent?

你是否有人以抽象的,松散耦合的方式使用LINQ to SQL,如果是这样,你是如何解决保持代码数据库无关的问题的?

4 个解决方案

#1


For myself; I'm content to re-use the object model that LINQ/dbml generates, since in reality the attributes don't hurt me, and any other implementation could provide a similar-enough model - but I don't use my data-context outside the DAL. So I have something like:

为了我自己;我满足于重用LINQ / dbml生成的对象模型,因为实际上属性不会伤害我,任何其他实现都可以提供类似的模型 - 但我不使用我的数据上下文在DAL之外。所以我有类似的东西:

  • IFooRepository - defines the methods available using both the generated dbml objects and some POCO model classes
  • IFooRepository - 使用生成的dbml对象和一些POCO模型类定义可用的方法

  • FooRepository - the implementation that knows about the data-context
  • FooRepository - 了解数据上下文的实现

My repository methods don't expose LINQ concepts like IQueryable<T> and Expression<...>, since they are leaky abstractions; other implementations will work differently (EF supports different aspects of both, for example).

我的存储库方法不公开LINQ概念,如IQueryable 和Expression <...>,因为它们是漏洞抽象;其他实现将以不同的方式工作(例如,EF支持两者的不同方面)。

Further - I've taken to marking most association properties as internal, and only using them during DAL queries (not so much during the OO work).

进一步 - 我已经将大多数关联属性标记为内部属性,并且仅在DAL查询期间使用它们(在OO工作期间没有那么多)。

I could map to pure POCOs, but I don't see the benefit. I have some more thoughts on this here: Pragmatic LINQ.

我可以映射到纯POCO,但我没有看到好处。我在这里有更多的想法:务实的LINQ。

#2


You can use a similar approach like the one used in NerdsDinner. This project uses the dat a context as a gateway to the database and builds a repository around it.

您可以使用类似于NerdsDinner中使用的方法。该项目使用dat作为数据库的网关,并围绕它构建一个存储库。

This kind of repository pattern adds some conditions, filters, sorting command ... etc according to the called method and then returns an IQuerable to the caller leaving the door open for further modifications.

这种存储库模式根据被调用的方法添加了一些条件,过滤器,排序命令等,然后将IQuerable返回给调用者,让门打开以进行进一步修改。

Actually you do almost the same way when building a repository around a NHibernate ISession.

实际上,在围绕NHibernate ISession构建存储库时,您的工作方式几乎相同。

If you decided to replace LinqtoSql with NHibernate for example, you have just to query a Linq session inside you repository instead of the datacontext one. Of course you will need although to complete your partial classes with the properties, which LinqtoSql adds automatically.

例如,如果您决定用NHibernate替换LinqtoSql,那么您只需查询存储库中的Linq会话而不是datacontext。当然,您需要使用LinqtoSql自动添加的属性来完成您的部分类。

#3


Hey nathan, good question.

嘿nathan,好问题。

As others have said, the best thing to do is abstract all your GET/WRITE methods, and hide away the DataContext completely from your Business Logic.

正如其他人所说,最好的办法是抽象所有GET / WRITE方法,并将DataContext完全隐藏在业务逻辑中。

My approach to this has been to write a DAL with a bunch of Generic methods which use reflection to do to whatever is necessary.

我的方法是用一堆通用方法编写一个DAL,这些方法使用反射来做任何必要的事情。

In these instances, once the method receives an object, say "Product", it can do whatever it wants internally independent of you ORM/Data Access technology. If you want it could literally just write a SQL string based on a few parameters, and reflection of the object.

在这些情况下,一旦方法接收到一个对象,比如说“Product”,它就可以在内部做任何想做的事情,而不依赖于你的ORM /数据访问技术。如果你想要,它可以简单地根据一些参数编写一个SQL字符串,并反映该对象。

HOWEVER, doing this alone won't completely de-couple you from LINQ to SQL.

但是,单独执行此操作并不能完全解除LINQ to SQL的错误。

The problem really are the entities themselves. Even if you abstract the method for retrieving data, you'll still be using those Entites all the way up your business logic.

问题实际上是实体本身。即使您抽象出检索数据的方法,您仍然会在业务​​逻辑中一直使用这些Entites。

I feel like, at the moment, thats just something I'm prepared to live with, because re-writing my own disconnected Entities seems like a bridge I'm not prepared to cross yet, just because it seems like a lot of unnecessary work...

我觉得,此刻,这只是我准备好接受的东西,因为重新编写我自己的断开连接的实体似乎是一个我不准备跨越的桥梁,只是因为它似乎是很多不必要的工作...

I'd be very interested to see how others tackle this though.

我很想知道其他人如何解决这个问题。

cheers!

#4


Mouk above mentions the repository pattern in the NerdsDinner, there's also a tutorial of how to quickly set it up here:

上面的Mouk提到了NerdsDinner中的存储库模式,还有一个如何快速设置它的教程:

http://www.asp.net/learn/mvc/tutorial-10-cs.aspx

This a good little series of tutorials that were released before the NerdsDinner. The concept here can be set up in a traditional asp.net web forms app as well.

这是在NerdsDinner之前发布的一系列很好的教程。这里的概念也可以在传统的asp.net Web表单应用程序中设置。

Also, I would suggest using Linq To Entities (newer, and more support for other DBs) instead, some basics on that are here: http://www.asp.net/learn/mvc/tutorial-16-cs.aspx

此外,我建议使用Linq To Entities(更新,以及对其他数据库的更多支持),其中的一些基础知识在这里:http://www.asp.net/learn/mvc/tutorial-16-cs.aspx

#1


For myself; I'm content to re-use the object model that LINQ/dbml generates, since in reality the attributes don't hurt me, and any other implementation could provide a similar-enough model - but I don't use my data-context outside the DAL. So I have something like:

为了我自己;我满足于重用LINQ / dbml生成的对象模型,因为实际上属性不会伤害我,任何其他实现都可以提供类似的模型 - 但我不使用我的数据上下文在DAL之外。所以我有类似的东西:

  • IFooRepository - defines the methods available using both the generated dbml objects and some POCO model classes
  • IFooRepository - 使用生成的dbml对象和一些POCO模型类定义可用的方法

  • FooRepository - the implementation that knows about the data-context
  • FooRepository - 了解数据上下文的实现

My repository methods don't expose LINQ concepts like IQueryable<T> and Expression<...>, since they are leaky abstractions; other implementations will work differently (EF supports different aspects of both, for example).

我的存储库方法不公开LINQ概念,如IQueryable 和Expression <...>,因为它们是漏洞抽象;其他实现将以不同的方式工作(例如,EF支持两者的不同方面)。

Further - I've taken to marking most association properties as internal, and only using them during DAL queries (not so much during the OO work).

进一步 - 我已经将大多数关联属性标记为内部属性,并且仅在DAL查询期间使用它们(在OO工作期间没有那么多)。

I could map to pure POCOs, but I don't see the benefit. I have some more thoughts on this here: Pragmatic LINQ.

我可以映射到纯POCO,但我没有看到好处。我在这里有更多的想法:务实的LINQ。

#2


You can use a similar approach like the one used in NerdsDinner. This project uses the dat a context as a gateway to the database and builds a repository around it.

您可以使用类似于NerdsDinner中使用的方法。该项目使用dat作为数据库的网关,并围绕它构建一个存储库。

This kind of repository pattern adds some conditions, filters, sorting command ... etc according to the called method and then returns an IQuerable to the caller leaving the door open for further modifications.

这种存储库模式根据被调用的方法添加了一些条件,过滤器,排序命令等,然后将IQuerable返回给调用者,让门打开以进行进一步修改。

Actually you do almost the same way when building a repository around a NHibernate ISession.

实际上,在围绕NHibernate ISession构建存储库时,您的工作方式几乎相同。

If you decided to replace LinqtoSql with NHibernate for example, you have just to query a Linq session inside you repository instead of the datacontext one. Of course you will need although to complete your partial classes with the properties, which LinqtoSql adds automatically.

例如,如果您决定用NHibernate替换LinqtoSql,那么您只需查询存储库中的Linq会话而不是datacontext。当然,您需要使用LinqtoSql自动添加的属性来完成您的部分类。

#3


Hey nathan, good question.

嘿nathan,好问题。

As others have said, the best thing to do is abstract all your GET/WRITE methods, and hide away the DataContext completely from your Business Logic.

正如其他人所说,最好的办法是抽象所有GET / WRITE方法,并将DataContext完全隐藏在业务逻辑中。

My approach to this has been to write a DAL with a bunch of Generic methods which use reflection to do to whatever is necessary.

我的方法是用一堆通用方法编写一个DAL,这些方法使用反射来做任何必要的事情。

In these instances, once the method receives an object, say "Product", it can do whatever it wants internally independent of you ORM/Data Access technology. If you want it could literally just write a SQL string based on a few parameters, and reflection of the object.

在这些情况下,一旦方法接收到一个对象,比如说“Product”,它就可以在内部做任何想做的事情,而不依赖于你的ORM /数据访问技术。如果你想要,它可以简单地根据一些参数编写一个SQL字符串,并反映该对象。

HOWEVER, doing this alone won't completely de-couple you from LINQ to SQL.

但是,单独执行此操作并不能完全解除LINQ to SQL的错误。

The problem really are the entities themselves. Even if you abstract the method for retrieving data, you'll still be using those Entites all the way up your business logic.

问题实际上是实体本身。即使您抽象出检索数据的方法,您仍然会在业务​​逻辑中一直使用这些Entites。

I feel like, at the moment, thats just something I'm prepared to live with, because re-writing my own disconnected Entities seems like a bridge I'm not prepared to cross yet, just because it seems like a lot of unnecessary work...

我觉得,此刻,这只是我准备好接受的东西,因为重新编写我自己的断开连接的实体似乎是一个我不准备跨越的桥梁,只是因为它似乎是很多不必要的工作...

I'd be very interested to see how others tackle this though.

我很想知道其他人如何解决这个问题。

cheers!

#4


Mouk above mentions the repository pattern in the NerdsDinner, there's also a tutorial of how to quickly set it up here:

上面的Mouk提到了NerdsDinner中的存储库模式,还有一个如何快速设置它的教程:

http://www.asp.net/learn/mvc/tutorial-10-cs.aspx

This a good little series of tutorials that were released before the NerdsDinner. The concept here can be set up in a traditional asp.net web forms app as well.

这是在NerdsDinner之前发布的一系列很好的教程。这里的概念也可以在传统的asp.net Web表单应用程序中设置。

Also, I would suggest using Linq To Entities (newer, and more support for other DBs) instead, some basics on that are here: http://www.asp.net/learn/mvc/tutorial-16-cs.aspx

此外,我建议使用Linq To Entities(更新,以及对其他数据库的更多支持),其中的一些基础知识在这里:http://www.asp.net/learn/mvc/tutorial-16-cs.aspx