前面的文章讨论了使用SQL语句和存储过程两种数据访问层的实现方式,这一篇里,将讨论使用ORM方式实现数据访问层的方法。

  对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。

  目前.NET平台上有许多ORM框架可供选择,如NBear、NHibernate等等。这里我们选择NBear实现ORM。

  NBear是由博客园的Teddy's Knowledge Base团队开发的一个开源框架,主要用来提高.NET平台的开发效率,其中包含了ORM、IoC、MVP等多个组件,这里仅仅用到其中的ORM功能。关于NBear的详细使用方法本文不再详述,请参考NBear入门教程。NBear的最新版本下载地址为http://files.cnblogs.com/hjf1223/NBearV3.7.2.11_src.rar。

  下面我们一步一步实现数据访问层的ORM实现。

  1.创建实体设计工程

  使用NBear实现ORM功能,首先要创建一个实体设计工程,这个工程最终不会应用到系统中,但是必须通过它来生成NBear实体类以及配置文件。

  首先,我们在解决方案下新建一个工程,名字为NBearEntityDesign,并为这个工程添加到文件NBear.Common.Design.dll的引用,这个文件在NBear文件包的dist目录下。

  完成后,在这个工程下新建一个C#文件,名为EntityDesign.cs,这个文件就是设计文件,根据对实体和数据库的设计,编写完整代码如下:

  EntityDesign.cs

1using System;
2using System.Collections.Generic;
3using System.Text;
4using NBear.Common.Design;
5
6namespace NGuestBook.NBearEntityDesign
7{
8  public interface TAdmin : Entity
9  {
10    [PrimaryKey]
11    int ID { get; }
12    [SqlType("nvarchar(20)")]
13    string Name { get; set; }
14    [SqlType("nvarchar(50)")]
15    string Password { get; set; }
16  }
17
18  public interface TComment : Entity
19  {
20    [PrimaryKey]
21    int ID { get; }
22    [SqlType("ntext")]
23    string Content { get; set; }
24    DateTime Time { get; set; }
25    int MessageID { get; set; }
26  }
27
28  public interface TMessage : Entity
29  {
30    [PrimaryKey]
31    int ID { get; }
32    [SqlType("nvarchar(20)")]
33    string GuestName { get; set; }
34    [SqlType("nvarchar(100)")]
35    string GuestEmail { get; set; }
36    [SqlType("ntext")]
37    string Content { get; set; }
38    DateTime Time { get; set; }
39    [SqlType("ntext")]
40    string Reply { get; set; }
41    [SqlType("nvarchar(10)")]
42    string IsPass { get; set; }
43  }
44}

  设计完后,将这个工程编译备用。

  2.创建NBear专用实体类及配置文件

  在NBear文件包的dist目录下,有一个NBear.Tools.EntityDesignToEntity.exe程序,打开它,点击“Browse”按钮,选择刚才编译生成的NGuestBook.NBearEntityDesign.dll文件,并在Output Namespace文本框里输入相应的命名空间,这里我们应输入“NGuestBook.NBearDAL”。然后点击“Generate Entities”按钮,这时会在底下的文本框里生成NBear专用实体类代码。

  在解决方案下新建一个工程NBearDAL,用于存放所有ORM数据访问层的实现代码。在这个工程下新建Entities.cs,将刚才自动生成的代码覆盖掉这个文件的代码,专用实体类就做好了。

  另外,需要给工程NBearDAL添加到NBear.Common.dll和NBear.Data.dll的引用,这两个文件都在dist目录下。

  点击“Generate Configuration”按钮,这时会生成配置代码。在Web工程下新建文件NBearConfig.xml,将生成的代码复制到这个文件里保存。

  最后还要修改一下Web.config文件。增加如下配置代码:

   <configSections>
    <section name="entityConfig" type="NBear.Common.EntityConfigurationSection, NBear.Common"/>
   </configSections>
   <entityConfig>
    <includes>
     <add key="Sample Entity Config" value="~/NBearConfig.xml"/>
    </includes>
   </entityConfig>

  然后再在<connectionStrings>节点下增加如下项:

   <add name="NBearConnectionString" connectionString="Server=LOCALHOSTSQLEXPRESS;Database=NGuestBook;Uid=WebUser;Pwd=123456" providerName="NBear.Data.SqlServer.SqlDbProvider"/>

  其中connectionString是连接字符串,根据个人不同情况进行修改。这里使用的是SQLServer2005。

  因为数据库在上一篇中已经创建好了,这里就不需要创建数据库了。

  3.编写转换器

  这里出现了一个矛盾:业务逻辑层和表示层需要使用通用的实体类,如AdminInfo,而NBear需要使用专用实体类。怎么解决这个矛盾呢?我这里使用的方法是一个我称之为“转换器”的方法。 即为没一个实体写一个专门的转换器,实现两种实体类的转换。这里以管理员实体为例,这个转换器写在NBearDAL工程下的AdminConvertor.cs文件中。具体代码如下:

  AdminConvertor

1using System;
2using NGuestBook.Entity;
3
4namespace NGuestBook.NBearDAL
5{
6  /** <summary>
7  /// 实体类转换器-管理员
8  /// </summary>
9  public sealed class AdminConvertor
10  {
11    /** <summary>
12    /// 由普通管理员实体类转化为NBear专用管理员实体类
13    /// </summary>
14    /// <param name="commonEntity">普通实体类</param>
15    /// <returns>NBear专用实体类</returns>
16    public static TAdmin CommonEntityToNBearEntity(AdminInfo commonEntity)
17    {
18      TAdmin nbaerEntity = new TAdmin();
19      nbaerEntity.ID = commonEntity.ID;
20      nbaerEntity.Name = commonEntity.Name;
21      nbaerEntity.Password = commonEntity.Password;
22
23      return nbaerEntity;
24    }
25
26    /** <summary>
27    /// 由NBear专用管理员实体类转化为普通管理员实体类
28    /// </summary>
29    /// <param name="nbearEntity">NBear专用实体类</param>
30    /// <returns>普通实体类</returns>
31    public static AdminInfo NBearEntityToCommonEntity(TAdmin nbearEntity)
32    {
33      AdminInfo commonEntity = new AdminInfo();
34      commonEntity.ID = nbearEntity.ID;
35      commonEntity.Name = nbearEntity.Name;
36      commonEntity.Password = nbearEntity.Password;
37
38      return commonEntity;
39    }
40  }
41}

  4.实现数据访问层

  做完上述工作,我们就可以来实现数据访问层了。借助于NBear框架的支持,我们可以非常方便的使用ORM方式访问数据库。关于NBear的细节,这里不再赘述,以管理员为例,具体代码如下:

  AdminDAL.cs

 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Data.Common;
 5using NGuestBook.IDAL;
 6using NGuestBook.Entity;
 7using NBear.Common;
 8using NBear.Data;
 9
10namespace NGuestBook.NBearDAL
11{
12  public class AdminDAL : IAdminDAL
13  {
14    /** <summary>
15    /// 插入管理员
16    /// </summary>
17    /// <param name="admin">管理员实体类</param>
18    /// <returns>是否成功</returns>
19    public bool Insert(AdminInfo admin)
20    {
21      Gateway.SetDefaultDatabase("NBearConnectionString");
22      DbTransaction transcation = Gateway.Default.BeginTransaction();
23      try
24      {
25        Gateway.Default.Save<TAdmin>(AdminConvertor.CommonEntityToNBearEntity(admin));
26        transcation.Commit();
27        return true;
28      }
29      catch
30      {
31        transcation.Rollback();
32        return false;
33      }
34      finally
35      {
36        Gateway.Default.CloseTransaction(transcation);
37      }
38    }
39
40    /** <summary>
41    /// 删除管理员
42    /// </summary>
43    /// <param name="id">欲删除的管理员的ID</param>
44    /// <returns>是否成功</returns>
45    public bool Delete(int id)
46    {
47      Gateway.SetDefaultDatabase("NBearConnectionString");
48      DbTransaction transcation = Gateway.Default.BeginTransaction();
49      try
50      {
51        Gateway.Default.Delete<TAdmin>(id);
52        transcation.Commit();
53        return true;
54      }
55      catch
56      {
57        transcation.Rollback();
58        return false;
59      }
60      finally
61      {
62        Gateway.Default.CloseTransaction(transcation);
63      }
64    }
65
66    /** <summary>
67    /// 更新管理员信息
68    /// </summary>
69    /// <param name="admin">管理员实体类</param>
70    /// <returns>是否成功</returns>
71    public bool Update(AdminInfo admin)
72    {
73      Gateway.SetDefaultDatabase("NBearConnectionString");
74      DbTransaction transcation = Gateway.Default.BeginTransaction();
75      PropertyItem[] properties = {
76        new PropertyItem("Name"),
77        new PropertyItem("Password")
78      };
79      object[] values ={
80        admin.Name,
81        admin.Password
82      };
83      try
84      {
85        Gateway.Default.Update<TAdmin>(properties, values, null, transcation);
86        transcation.Commit();
87        return true;
88      }
89      catch
90      {
91        transcation.Rollback();
92        return false;
93      }
94      finally
95      {
96        Gateway.Default.CloseTransaction(transcation);
97      }
98    }
99
100    /** <summary>
101    /// 按ID取得管理员信息
102    /// </summary>
103    /// <param name="id">管理员ID</param>
104    /// <returns>管理员实体类</returns>
105    public AdminInfo GetByID(int id)
106    {
107      Gateway.SetDefaultDatabase("NBearConnectionString");
108      TAdmin tAdmin = Gateway.Default.Find<TAdmin>(TAdmin._.ID == id);
109      return tAdmin == null ? null : AdminConvertor.NBearEntityToCommonEntity(tAdmin);
110    }
111
112    /** <summary>
113    /// 按用户名及密码取得管理员信息
114    /// </summary>
115    /// <param name="name">用户名</param>
116    /// <param name="password">密码</param>
117    /// <returns>管理员实体类,不存在时返回null</returns>
118    public AdminInfo GetByNameAndPassword(string name, string password)
119    {
120      Gateway.SetDefaultDatabase("NBearConnectionString");
121      TAdmin tAdmin = Gateway.Default.Find<TAdmin>(TAdmin._.Name == name && TAdmin._.Password == password);
122      return tAdmin == null ? null : AdminConvertor.NBearEntityToCommonEntity(tAdmin);
123    }
124
125    /** <summary>
126    /// 按管理员名取得管理员信息
127    /// </summary>
128    /// <param name="name">管理员名</param>
129    /// <returns>管理员实体类</returns>
130    public AdminInfo GetByName(string name)
131    {
132      Gateway.SetDefaultDatabase("NBearConnectionString");
133      TAdmin tAdmin = Gateway.Default.Find<TAdmin>(TAdmin._.Name == name);
134      return tAdmin == null ? null : AdminConvertor.NBearEntityToCommonEntity(tAdmin);
135    }
136
137    /** <summary>
138    /// 取得全部管理员信息
139    /// </summary>
140    /// <returns>管理员实体类集合</returns>
141    public IList<AdminInfo> GetAll()
142    {
143      IList<AdminInfo> adminCollection = new List<AdminInfo>();
144      Gateway.SetDefaultDatabase("NBearConnectionString");
145      TAdmin[] tAdminCollection = Gateway.Default.FindArray<TAdmin>(null, TAdmin._.ID.Desc);
146      foreach (TAdmin tAdmin in tAdminCollection)
147      {
148        adminCollection.Add(AdminConvertor.NBearEntityToCommonEntity(tAdmin));
149      }
150      return adminCollection;
151    }
152  }
153}

基于.NET平台的分层架构实战(九)——数据访问层的第三种实现:基于NBear框架的ORM实现相关推荐

  1. 基于.NET平台的分层架构实战(二)——需求分析与数据库设计

    基于.NET平台的分层架构实战(五)--接口的设计与实现 · 基于.NET平台的分层架构实战(四)--实体类的设计与实现 · 基于.NET平台的分层架构实战(三)--架构概要设计 · 基于.NET平台 ...

  2. 基于.NET平台的分层架构实战(一)——综述

    通过浏览博客园的文章发现,很多朋友对分层架构特别感兴趣,刚好我刚做完的毕业设计就是专门研究.NET平台上分层架构的(题目叫"基于.NET平台的分层架构与设计模式应用研究").通过做 ...

  3. 一起谈.NET技术,发布NGuestBook(一个基于.NET平台的分层架构留言本小系统)

    发布NGuestBook的动机说明      大约在半年前,我在博客上发表了一个系列文章:<基于.NET平台的分层架构实战>.当时在讲解过程中用到了一个叫NGuestBook的案例,在那以 ...

  4. 发布NGuestBook(一个基于.NET平台的分层架构留言本小系统)

    发布NGuestBook的动机说明 大约在半年前,我在博客上发表了一个系列文章:<基于.NET平台的分层架构实战>.当时在讲解过程中用到了一个叫NGuestBook的案例,在那以后,有很多 ...

  5. 项目架构开发:数据访问层之Cache

    数据访问层简单介绍 数据访问层,提供整个项目的数据访问与持久化功能.在分层系统中所有有关数据访问.检索.持久化的任务,最终都将在这一层完成. 来看一个比较经典的数据访问层结构图 大概可以看出如下信息 ...

  6. 实战 .Net 数据访问层 - 23

      u     使用现成的框架 Ø        首选当然是.NET Framework即将正式推出的ObjectSpaces! Ø        如果希望Total Solution,Borland ...

  7. 实战 .Net 数据访问层 - 19

      6.       ASPECT AOP(Aspect Oriented Programming)可能是最近几年被挖掘出 来的最具震撼力的技术之一,作者并不打算在此花什么篇幅介绍它(网上资料已多如牛 ...

  8. 分层:数据访问层、业务逻辑层、视图层

    分层:开发模式     数据访问层 业务逻辑层:调用数据访问层 视图层:调用业务逻辑层 数据库表 1.创建项目 2.创建包:     com.zking.util         com.zking. ...

  9. 艾伟:基于.NET平台的Windows编程实战(四)—— 数据库操作类的编写

    本系列文章导航 基于.NET平台的Windows编程实战(一)--前言 基于.NET平台的Windows编程实战(二)-- 需求分析与数据库设计 基于.NET平台的Windows编程实战(四)-- 数 ...

  10. 微软账号登陆不上_企业信息化面临的问题,看看解决方案,基于微软平台的IT架构...

    哈喽,今日头条的小伙伴们大家好,我是你们的好朋友IT咨询顾问.小编曾经就工作过程中接触的企业IT环境存在的问题,陆陆续续搜集过一些案例,当时做的笔记是零散的,现在为了方便小伙伴们阅读,整理了一下笔记并 ...

最新文章

  1. CF587F Duff is Mad
  2. 告警系统邮件引擎、运行告警系统
  3. SpringBoot之web开发
  4. 1031 Hello World for U (20 分)【难度: 一般 / 知识点: 找规律】
  5. hadoop常见错误即解决方法
  6. Think in AngularJS :对比 jQuery 和 AngularJS 的不同思维模式
  7. django 热启动_传统的Web框架如何部署在Serverless架构上(以Flask为例)
  8. python异常捕获_Python 异常的捕获、异常的传递与主动抛出异常操作示例
  9. python把英语句子成分字母_英语句子成分分析(最完整版)
  10. oracle拆分分区语法详解大全_Oracle分区表详解
  11. java使用poi导出word并且带图片
  12. 前端开发:遇到提示Invalid prop:type check failed for prop “modelValue“. Expected Number…的解决方法
  13. ESP32开发路程蓝牙篇——BLE(GATT),修改设备名称,添加characteristic,发送数据,接收数据
  14. 键盘录入一个字符串,统计该字符串中的大写字母、小写字母、数字字符和其他字符分别有多少个 例如,键盘录入abcABCD12345!@#$%,输出结果为:小写字母有3个,大写字母有4个,数字字符有5个,
  15. 用python 打印等腰三角形
  16. 黑苹果 10G 网卡(intel Aquantia)解决方案及big sur 11.x 下驱动方式
  17. CentOS 6.4 搭建 Java 开发环境详解
  18. 一、ECharts(各种统计图)
  19. PCB这个工艺,免费了!
  20. 计算机网络(期末详细总结)

热门文章

  1. php session fixation,session fixation攻击
  2. Python利用re正则表达式抓取豆瓣电影Top250排行榜
  3. mysql mtq_mysql实现远程登录
  4. 征信报告 加密文档_如何给PDF文档加密?PDF文档加密的方法
  5. linux 实现不同网段网络互通
  6. Excel VBA单元格数据自增1
  7. java启动后台进程_windows下java -jar 后台运行以及杀死后台进程的操作
  8. 关于查看nginx的访问量的部分总结
  9. 在CAD软件中如何批量打印黑白CAD图纸
  10. 多个excel工作簿合并_Microsoft Excel如何快速合并多个工作簿至一个工作簿中?