讲解ASP.NET中LINQ to SQL 实现数据访问通用基类
LINQ to SQL让人着迷,在.Net应用程序当中,.它提供了一种安全,强大和非常灵活的方式执行数据访问,在当前微软传道者介绍上看,很容易上手。
不幸的是,当你对LINQ进行仔细研究后,我发现在多层架构中使用LINQ的并不是十分容易。
本文介绍用LINQ to SQL实现数据层的典型的问题点 ,并提供了一个简单,方便和灵活的方式来克服它们。
本文附带的LINQ to SQL 实现数据访问通用类有以下的特点:
- 实现了存储库模式,你可以用不到10行代码执行LINQ实体类型的CRUD (Create, Update, Delete)操作。
- 无缝协作,支持LINQ断开模式(Disconnected LINQ Mode)。
- 在单一数据库和LINQ实体间支持透明的数据库更新和数据加载。
- 提供为一种方便的功能,在调试你的应用程寻时候,它把所有执行的SQL语句输出控制台。
本文将假定您对LINQ to SQL (也称为DLINQ )有一个基本的了解并如何使用它。否则,,,回到此网页,看看本教程入门系列,如何在多层次应用中使用LINQ to SQL。
存在的问题
如果您只是在你的UI层直接用LinqToDataSource对象衔接数据库,那LINQ to SQL太容易使用了。但是,这种做法不完全面向对象,当然也不是一个可取的架构,除非你是为了快速编码和脏乱的应用程序,并且最终没有去扩展的它打算。
相反,大多数开发人员把它们的应用程序划分成若干层,如下:
- 数据访问层(Data Access Layer)
- 业务层 (Business Layer)
- 用户界面层(UI Layer)
这就是所谓的多层数据库应用程序设计。LINQ to SQL将用于数据访问层。
LINQto SQL的问题是-尽管它的许多优点-但是如果要实现数据层并不是很简单。
请看下面的数据库模式(database schema):
一旦你要加载和保存LINQ实体到同一个的数据上下文实例(data context instance)(这就是所谓“连接模式”),用LINQ实现数据层非常直接。
例如,让我们从数据库中获取实体编号为1的客户,改变属性first name为“Homer”后在重新储存到数据库中。在一个多层数据库应用程序中,在UI或业务层的某个地方的代码可能看起来就像这样:
view plaincopy to clipboardprint?
1.
2. //create a new repository instance
3. CustomersRepository customersRepository = new CustomersRepository();
4. //load a customer instance and change it's FirstName;
5. Customer customer = customersRepository.Load(2);
6. customer.FirstName = "Homer";
7. //commmit customer to database
8. customersRepository.Save(customer);
最简单的方法来实现上面使用到的数据层加载和保存功能是:
view plaincopy to clipboardprint?
1.
2. static DataClassesDataContext context=new DataClassesDataContext();
3. public Customer Load(int CustomerID)
4. {
5. return context.Customers.Single(c => c.ID == CustomerID);
6. }
7. public void Save(Customer toSave)
8. {
9. context.SubmitChanges();
10. }
这种方法是使用连接LINQ模式:数据上下文(data context)在当前作用域一直有效(译者注:一直保持连接状态),所以在把实体保存到数据库的时候,它总是可以重复使用。其中仍然连接到它。
当然,这种做法方便并且在上述的单个例子中能运行,但它存在严重的并发问题,因为一个数据库方面是用于所有数据库操作。
当调用方法Save(),bmitChanges提交的不仅仅是当前Save 方法参数相关的LINQ实体,还包括所有改变了的实体。
但是及时把这个缺陷考虑在一边,使用LINQ在一个多层ASP.NET应用程序中,您还不能以相同方式实现数据层。首先,可能要求是这样,在一个页面请求中,LINQ实体被加载,然后在下一个页面请求中,它更新并储存到数据库中的。.同时,您的原始数据上下文在当前作用域内已经无效的(译者住:HTTP协议是无状态的),造成的您的LINQ实体游离。
还有许多其他情况下你需要使用断开LINQ模式:例如您实现的数据库层可能要作为一个Web服务,提交(commit)以前序列化LINQ实体到数据库等等。