LINQ to SQL活学活用(3):嗅出“臭味”烟消云散
来源:互联网 发布:linux反向域名解析 编辑:程序博客网 时间:2024/03/29 17:27
引入
再次想想上一篇的设计,在第一篇中我说过这个系列的目标是构建一个N层程序,要求这个程序可测试、可维护、可复用、可扩展。我们做到了吗?
可测试:恩,现在可以测试!并且隐藏了具体细节,这个比较满意!
可维护:好像现在没有什么维护的,不就是这点功能吗?
可复用:这点功能叫我怎么复用?我另外写一个程序或许比这个更好呢?
可扩展:恩,需要多多扩展,就这点功能!
好!我就想扩展了!就想开始了!却......不好扩展啊,我们看看上一篇的不足点,虽然我们把所有的数据库操作都封装起来了。但是没有做到彻底的隔离。因为客户端直接使用了Customer这个类。 而这个类是和LINQ to SQL实现捆绑在一起的。所以客户端还是知道你在使用LINQ to SQL,用这种方式依赖还是传递的,使用接口方式可以倒置依赖关系从而完全解除对LINQ to SQL的依赖。感谢朱良雄和possible两位朋友对上篇文章的点评,一针见血!
这就是当前程序嗅出的“臭味”,我们有什么办法呢?如何避免呢?这篇我们还是讨论这个问题吧!
注意:这是我第一次分析设计,我只想通过这个系列来讨论学习设计方面的东西,当然很多思想还不成熟或者有错误,只是希望通过这个系列来学习构架设计方面的东西,希望大牛们指点,大家拍砖头!
系列文章导航
LINQ to SQL活学活用(1):这要打破旧观念
LINQ to SQL活学活用(2):躲起来别让我看见
LINQ to SQL活学活用(3):嗅出“臭味”烟消云散
LINQ to SQL活学活用(4):监视你的一举一动
系列参考代码下载:LINQ to SQL
改进
知道程序的“臭味”,我们如何改进呢?想想,通过接口隐藏实体。我们利用接口实现,为Customer创建分部类,创建ICustomer接口,Customer实现ICustomer接口,利用ICustomer接口编写CustomerFacade,根据新的ICustomer接口更新单元测试,而不是上一节的对Customer对象做单元测试,这样客户就不知道数据访问层中具体实现了。这就是我们这一节做的工作。
数据访问层
进一步改进我们的程序,看看数据访问层的类图设计:
1.新建ICustomer接口
public interface ICustomer{ int CustomerId { get; set; } string FirstName { get; set; } string LastName { get; set; }}
2.新建分部类Customer实现ICustomer接口
public partial class Customer : ICustomer{}
我在这里这个分部类就空实现了,实际上是数据访问对象DataContext中的Customer类(数据访问对象)实现了这个接口。
3.修改数据访问外观基类
增加一个方法实现IQueryable<T>转换为IList<TInterface>接口
protected IList<TInterface> ConvertToList<TInterface, TConcrete>( IEnumerable<TConcrete> convertThis) where TConcrete : TInterface{ if (convertThis == null) { return new List<TInterface>(); } else { IList<TInterface> returnValue = new List<TInterface>(); foreach (TConcrete item in convertThis) { returnValue.Add(item); } return returnValue; }}
4.修改数据访问外观CustomerFacade
这个类中封装了Customer对象的具体CRUD实现,我们需要修改,实现接口。
Step1:新建临时Customer对象
public ICustomer CreateCustomer(){ return new Customer();}
Step2:按CustomerId获取Customer对象
public ICustomer GetCustomerById(int customerId){ return (from p in DataContext.Customer where p.CustomerId == customerId select p).FirstOrDefault();}
Step3:获取Customer对象列表
public IList<ICustomer> GetCustomerList(){ IQueryable<Customer> results = from p in DataContext.Customer select p; return ConvertToList<ICustomer, Customer>(results);}
Step4:更新保存Customer对象
public void UpdateCustomer(ICustomer customer){ Customer tempCustomer = customer as Customer; if (tempCustomer.CustomerId == 0) { DataContext.Customer.InsertOnSubmit(tempCustomer); } DataContext.SubmitChanges();}
数据访问层修改完毕了。
单元测试层
只要把相应的数据访问对象换为数据访问对象接口,可以倒置依赖关系从而完全解除对LINQ to SQL的依赖。
Step1:修改创建并保存Customer方法:
private ICustomer CreateAndSaveNewCustomer(string firstName, string lastName){ ICustomer newCustomer = Facade.CreateCustomer(); newCustomer.FirstName = firstName; newCustomer.LastName = lastName; Facade.UpdateCustomer(newCustomer); return newCustomer;}
Step2:修改测试UpdateCustomer()方法:
[Test]public void UpdateCustomerTest(){ ICustomer newCustomer = CreateAndSaveNewCustomer("YJing", "Lee"); Assert.AreNotEqual(0, newCustomer.CustomerId); Assert.AreEqual("YJing", newCustomer.FirstName);}
Step3:修改GetCustomerByIdTest()方法:
[Test]public void GetCustomerByIdTest(){ ICustomer tempCustomer = CreateAndSaveNewCustomer("YJing", "Lee"); Assert.AreNotEqual(0, tempCustomer.CustomerId); ICustomer reloaded = Facade.GetCustomerById(tempCustomer.CustomerId); Assert.IsNotNull(reloaded); Assert.AreEqual(tempCustomer.CustomerId, reloaded.CustomerId); Assert.AreSame(tempCustomer, reloaded);}
这篇公布一下这个测试方法结果吧:
Step4:修改获取Customer列表方法
[Test]public void GetListTest(){ List<ICustomer> tempCustomers = new List<ICustomer>(); tempCustomers.Add(CreateAndSaveNewCustomer("YJing", "Lee")); tempCustomers.Add(CreateAndSaveNewCustomer("li", "yongjing")); tempCustomers.Add(CreateAndSaveNewCustomer("cnblogs", "com")); var reloaded = Facade.GetCustomerList(); Assert.IsNotNull(reloaded); Assert.AreEqual(tempCustomers.Count, reloaded.Count);}
结语
通过这篇的修改,我们程序的“臭味”基本上没有了,依赖关系从原来的对LINQ to SQL的依赖转为接口,客户直接使用接口。下篇就开始扩展吧,看看LINQ to SQL还有什么好东西!
- LINQ to SQL活学活用(3):嗅出“臭味”烟消云散
- LINQ to SQL活学活用(3):嗅出“臭味”烟消云散
- LINQ to SQL活学活用(1):这要打破旧观念
- LINQ to SQL活学活用(1):这要打破旧观念
- LINQ to SQL活学活用(4):监视你的一举一动
- 让单元测试“嗅出”代码的臭味
- LINQ to SQL活学活用(2):躲起来别让我看见
- LINQ to SQL活学活用(2):躲起来别让我看见
- linq,linq to sql
- Linq初探--Linq to SQL
- LINQ to SQL 学习
- 什么是Linq to sql
- 使用LINQ to SQL
- 深入LINQ to SQL
- Linq To Sql注意事项
- Linq to SQL:基础知识
- LINQ to SQL实例
- 使用LINQ to SQL
- [AHK]用热键生成所选文件的副本
- 人工智能和机器学习方面重要会议
- Unity3D 实现雪花飘飞效果[Shader]
- 拒绝采样(reject sampling)原理详解
- React Native 组件 --TextInput处理文本输入
- LINQ to SQL活学活用(3):嗅出“臭味”烟消云散
- dynamic web project与static web project区别
- mysql备份的三种方式详解
- java上传下载文件,中文文件名不显示或乱码
- OraOLEDB.Oracle.1 未注册
- Jetson TX1板载相机调用测试
- 创建带Tomcat服务的CentOS Docker镜像
- POJ2386 Lake Counting(dfs)
- LINQ to SQL活学活用(4):监视你的一举一动