LINQ to SQL活学活用(3):嗅出“臭味”烟消云散

改进

知道程序的“臭味”,我们如何改进呢?想想,通过接口隐藏实体。我们利用接口实现,为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还有什么好东西!

版权声明:本文为博主http://www.zuiniusn.com原创文章,未经博主允许不得转载。

时间: 2024-11-09 10:38:35

LINQ to SQL活学活用(3):嗅出“臭味”烟消云散的相关文章

pandas pivot_table 活学活用实例教程

pandas pivot_table 活学活用实例教程 导入相关数据分析的库 首先进行commentTime时间进行数据预处理 查看数据类型信息 最简单的透视表 直接敲击该函数,在notebook中可以查看该函数的参数 多个索引列 特定列的统计 规定特定的聚合函数 传入多个聚合函数 传入columns参数 生成的DataFrame可以导出excel或csv文件 修改index中的数据类型,显示完整的索引列 传入fill_value参数,处理缺失值 设添加margins参数,定margin_nam

LINQ to SQL活学活用(4):监视你的一举一动

改进 这也可以运用GoF23中的观察者模式,让多个观察者对象(对象创建.修改)同时监听某一个主题对象(这里就是数据访问对象Customer).这个主题对象Customer在状态发生变化时,会通知所有观察者对象(对象创建.修改),使它们能够自动更新自己,就可以实现监视Customer的一举一动了. 我们来实现这个功能,先看看这篇完成的整体架构. 数据访问层 1.数据访问基类 我们为整个数据访问对象定义一个公共基类,首先定义定义数据访问基类接口,让抽象数据访问基类实现这个接口,这个基类用于存放数据访

LINQ to SQL活学活用(1):这要打破旧观念

程序架构 现在比较经典的架构,看看下面图片. 如何实现 在一个N层应用程序中我们如何使用LINQ to SQL呢?这给刚刚入门的朋友的确是个难题,使用LINQ to SQL就是ORM技术,可以很轻松的实现对数据库记录增删查改操作,但是我们如何去"构建它"才更合理,更科学,更好用?这才是我们真正要学习的,使用面向对象的接口.抽象达到这个目的,面向接口编程就是更好的选择,可以更好的维护和测试. 下面一步一步完成这个程序吧,看到标题了吗?这篇是打破旧观念!看看接下来有什么神秘的地方.首先新建

LINQ to SQL活学活用(2):躲起来别让我看见

改进 这可以考虑到GoF23中的外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 考虑在数据访问层中建立外观Facade,这样可以为复杂的数据访问方法提供一个简单的类,使得耦合大大降低.增加外观Facade可以只向客户提供一个简单的接口,减少客户与数据访问层之间的依赖,更容易维护和扩展了. 数据访问层 我们就使用这种方法来改进第一篇的程序吧.首先创建一个基类用于存放公共的方法,然后各个数据访问对象(这里只有Custo

活学活用,webapi HTTPBasicAuthorize搭建小型云应用的实践

HTTP使用BASIC认证,WebAPI使用[HTTPBasicAuthorize]标记控制器就是使用了BASIC认证. BASIC认证的缺点HTTP基本认证的目标是提供简单的用户验证功能,其认证过程简单明了,适合于对安全性要求不高的 系统或设备中,如大家所用路由器的配置页面的认证,几乎 都采取了这种方式.其缺点是没有灵活可靠的认证策略,如 无法提供域(domain或realm)认证功能,另外,BASE64的加密强度非常低,可以说仅 能防止sohu的搜索把它搜到了. 当然,HTTP基本认证系统也

活学活用wxPython基础框架

看活活用wxpython这本书,基本框架是这样子的,这里有定义输出,然后打印出整个流程,可以看到是怎样执行的,明天请假了,五一回去玩几天,哈哈,估计假期过来都忘了 import wx import sys class Frame(wx.Frame): def __init__(self,parent,id,title): print "Frame __init__" wx.Frame.__init__(self,parent,id,title) class App(wx.App): d

JVM活学活用——Jvm内存结构

Java内存结构: JVM内存结构主要是有三大块:堆内存.方法区和栈.堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分为三部分,Eden空间.From Survivor空间.To Survivor空间,默认情况下年轻代按照8:1:1的比例来分配: 方法区存储类信息.常量.静态变量等数据,是线程共享的区域,为与Java堆区分,方法区还有一个别名Non-Heap(非堆): 栈又分为Java虚拟机栈和本地方法栈,主要用于方法的执行. 在通过一张图来了解如何通过参数来控制各区域的内存大

xhost命令详解(活学活用)

xhost命令是X服务器的访问控制工具,用来控制哪些X客户端能够在X服务器上显示.该命令必须从有显示连接的机器上运行.可以通过使用-host参数,从访问列表中除去一个名称.不要从访问列表中除去当前的名称.如果已经这样做了,请在作出任何更改之前注销系统. xhost 是用来控制X server访问权限的. 通常当你从hostA登陆到hostB上运行hostB上的应用程序时, 做为应用程序来说,hostA是client,但是作为图形来说, 是在hostA上显示的,需要使用hostA的Xserver,

活学活用 screen

新建桌面 screen 列出所有桌面 screen -ls 离开桌面 ctrl-A  D 进入之前的桌面 screen -RR 干掉当前桌面 ctrl-A  :quit 原文地址:https://www.cnblogs.com/yc2019/p/10459406.html