程序架构
如今比較经典的架构,看看以下图片。
怎样实现
在一个N层应用程序中我们怎样使用LINQ to SQL呢?这给刚刚入门的朋友的确是个难题,使用LINQ to SQL就是ORM技术,能够非常轻松的实现对数据库记录增删查改操作,可是我们怎样去“构建它”才更合理,更科学,更好用?这才是我们真正要学习的。使用面向对象的接口、抽象达到这个目的,面向接口编程就是更好的选择。能够更好的维护和測试。
以下一步一步完毕这个程序吧,看到标题了吗?这篇是打破旧观念。看看接下来有什么神奇的地方。
首先新建一个project,有两个类库分别为:数据訪问层DataAccess和单元測试UnitTest,看看截图:
数据訪问层
这篇先创建一个数据訪问对象,因为使用LINQ to SQL作为ORM,我们新建一个LINQ to SQL类DataAccessEntities.dbml作为数据訪问对象DataContext。一切可视化的操作,为了展示,在O/R设计器中新建一个Customer类(数据訪问对象)。加入CustomerId、FirstName、LastName三个成员属性。并在成员属性的属性窗体改动对应的属性。
为了展示,这里简单描写叙述下我的操作,设置成员属性例如以下:
- CustomerId:成员属性的类型Int。属性的名称CustomerId,数据库列的名称CustomerId。数据库列參与表的主键True。插入时在数据库中自己主动生成值True,指定插入时自己主动同步属性。
- FirstName:属性的名称FirstName,数据库列的名称FirstName,其他默认
- LastName:属性的名称LastName,数据库列的名称LastName,其他默认
好了,简单的数据訪问对象创建好了,以下測试了~~
单元測试层
单元測试用于測试用例的成功与失败,在软件开发中起着尤为重要的地位。当然使用单元測试的要求非常严格。这个系列我将严格遵守,我整理的要求例如以下
1.尽量在断言中提供错误信息描写叙述,这能够非常easy的发现你的错误。
2.每一个測试全然独立。体现面向对象中的单一职责原则。
3.不要假设数据库中有什么数据或者哪些数据不在数据库中,在每一个測试方法前保证数据库为空的。
4.測试时须要的一些原始数据要作为測试的一部分在測试方法前载入到数据库中。
遵守上面的要求,就可能面临以下的麻烦:
- 在測试前删除每张表的每行数据,PK关联须要另外写删除SQL语句脚本。
- 业务逻辑层创建了你没有预料到的数据,你不优点理。
- 假设你測试失败,在数据库中查看数据不在数据库中,没有不论什么提示信息你不知道系统做了什么。
- 因为记录被锁定,插入数据不写入数据库。也不能在不同数据库连接中读取。
幸好LINQ to SQL做到了上面的一切,LINQ to SQL的DataContext能够用来管理数据架构,它提供了DatabaseExists()、DeleteDatabase()、CreateDatabase()方法能够非常轻松的创建删除数据库。
注意。这个系列我使用NUnit.Framework測试,所以要引用nunit.framework.dll程序集。另外因为代码编写中涉及了这个类库引用System.configuration.dll、System.Data.Linq.dll程序集和Business项目。
1.创建一个測试基类
測试一般是非常复杂的,我们创建一个測试基类用于编写一些通用的方法,然后全部測试类都继承这个測试基类,这个基类主要完毕以下功能。
第一步:手动配置DataContext连接和日志
在我们的数据訪问层只创建了一个数据訪问对象,没有和数据库打交道,測试时须要对DataContext连接到数据库。
另外为了測试显示具体的信息,我们还要使用DataContext的日志功能。
public string ConnectionString { get { if (ConfigurationManager.ConnectionStrings["conn"] == null || String.IsNullOrEmpty(ConfigurationManager.ConnectionStrings["conn"].ConnectionString) == true) { throw new InvalidOperationException("默认的连接字符串不存在或者为空"); } return ConfigurationManager.ConnectionStrings["conn"].ConnectionString; } } private DataAccessEntitiesDataContext m_dataContext; public DataAccessEntitiesDataContext DataContext { get { if (m_dataContext == null) { m_dataContext = new DataAccessEntitiesDataContext(ConnectionString); m_dataContext.Log = Console.Out; } return m_dataContext; } }
第二步:创建数据库
在測试之前。打开暂时连接用于创建数据库。使用DataContext提供了DatabaseExists()、DeleteDatabase()、CreateDatabase()方法,先使用DatabaseExists()验证数据库是否存在,假设存在使用DeleteDatabase()方法删除。使用CreateDatabase()方法创建一个数据库架构,及时释放这个连接。
[TestFixtureSetUp] public void Init() { DataAccessEntitiesDataContext context = new DataAccessEntitiesDataContext(ConnectionString); context.Log = Console.Out; if (context.DatabaseExists() == true) { context.DeleteDatabase(); } context.CreateDatabase(); context.Connection.Close(); context.Dispose(); context = null; }
第三步:关闭全部连接
在測试结束关闭全部的连接,这一步非常必要哦。
[TestFixtureTearDown] public void Tear() { DataContext.Connection.Close(); }
第四步:设置连接字符串
新建一App.config文件。设置连接字符串:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="conn" connectionString="Data Source=.SQLEXPRESS;Initial Catalog=LINQ;Integrated Security=True"/> </connectionStrings> </configuration>
2.測试类
我们新建一个測试类用于測试数据訪问对象。这里简单測试创建一个Customer对象。新建CustomerFixture.cs类继承UnitTestBase
编写创建Customer对象方法例如以下,创建一个Customer对象,调用InsertOnSubmit()方法插入,调用DataContext.SubmitChanges()方法提交数据库。
[Test] public void CreateCustomerTest() { Customer customer = new Customer() { FirstName = "YJing", LastName = "Lee" }; Assert.AreEqual(0, customer.CustomerId, "測试前CustomerId为0"); DataContext.Customer.InsertOnSubmit(customer); DataContext.SubmitChanges(); Assert.AreNotEqual(0, customer.CustomerId, "调用SubmitChanges()方法后CustomerId不为0"); }
測试成功,看看输出结果:
OH!非常酷!首先创建了数据库架构,然后插入了一条数据。再次測试一下这种方法将是什么结果呢?这个问题就留给大家了。
结语
看到了吗?这就是全新的方式来完毕非常酷的工作!
从面向对象入手。利用LINQ to SQL生成其关系型数据库。一切就是这么easy!这篇只在数据訪问层上新建一数据訪问对象,在測试中调用DataContext提供的方法完毕数据操作!
下篇更精彩!