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


前面的文章讨论了使用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的最新版本下载地址:附件: NBearV3.7.2_src.rar

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

1.创建实体设计工程

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

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

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


EntityDesign.cs

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

  1. <configSections>
  2. <section name="entityConfig" type="NBear.Common.EntityConfigurationSection, NBear.Common"/>
  3. </configSections>
  4. <entityConfig>
  5. <includes>
  6. <add key="Sample Entity Config" value="~/NBearConfig.xml"/>
  7. </includes>
  8. </entityConfig>
复制代码

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

  1. <add name="NBearConnectionString" connectionString="Server=LOCALHOST/SQLEXPRESS;Database=NGuestBook;Uid=WebUser;Pwd=123456" providerName="NBear.Data.SqlServer.SqlDbProvider"/>
复制代码

其中connectionString是连接字符串,根据个人不同情况进行修改。这里使用的是SQLServer2005。
因为数据库在上一篇中已经创建好了,这里就不需要创建数据库了。

3.编写转换器

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


AdminConvertor

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

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


AdminDAL.cs

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


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn