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

程序架构

现在比较经典的架构,看看下面图片。

如何实现

在一个N层应用程序中我们如何使用LINQ to SQL呢?这给刚刚入门的朋友的确是个难题,使用LINQ to SQL就是ORM技术,可以很轻松的实现对数据库记录增删查改操作,但是我们如何去“构建它”才更合理,更科学,更好用?这才是我们真正要学习的,使用面向对象的接口、抽象达到这个目的,面向接口编程就是更好的选择,可以更好的维护和测试。

下面一步一步完成这个程序吧,看到标题了吗?这篇是打破旧观念!看看接下来有什么神秘的地方。首先新建一个工程,有两个类库分别为:数据访问层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.尽量在断言中提供错误信息描述,这可以很容易的发现你的错误。

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生成其关系型数据库,一切就是这么容易!这篇仅仅在数据访问层上新建一数据访问对象,在测试中调用DataContext提供的方法完成数据操作!下篇更精彩!

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

时间: 2024-08-25 05:45:42

LINQ to SQL活学活用(1):这要打破旧观念的相关文章

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活学活用(3):嗅出“臭味”烟消云散

改进 知道程序的"臭味",我们如何改进呢?想想,通过接口隐藏实体.我们利用接口实现,为Customer创建分部类,创建ICustomer接口,Customer实现ICustomer接口,利用ICustomer接口编写CustomerFacade,根据新的ICustomer接口更新单元测试,而不是上一节的对Customer对象做单元测试,这样客户就不知道数据访问层中具体实现了.这就是我们这一节做的工作. 数据访问层 进一步改进我们的程序,看看数据访问层的类图设计: 1.新建ICustom

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