数据访问层之Repository

数据访问层之Repository

接上文 项目架构开发:数据访问层之Logger

本章我们继续IRepository开发,这个仓储与领域模式里边的仓储有区别,更像一个工具类,也就是有些园友说的“伪仓储”,

这个仓储只实现单表的CURD与Query,都是通过主键ID或拉姆达表达式进行操作的,返回的都是单表的实体或实体集合,

多表的在IQuery接口中再讲;虽然如此,但是如果与“活动记录”开发模式搭配的话,会非常合适,可以减少开发的时间

及出错几率,更符合开发人员的类型调用习惯

IRepository.cs

 1     public interface IRepository<T> where T : class
 2     {
 3         void Add(T entity);
 4         void AddBatch(IEnumerable<T> entitys);
 5         void Update(T entity);
 6         void Delete(T entity);
 7         void Delete(string Id);
 8         void Delete(int Id);
 9         void Delete(Guid Id);
10         T Get(string Id);
11         T Get(Guid Id);
12         T Get(int Id);
13         T Get(T entity);
14         T Get(Expression<Func<T, bool>> func);
15         IEnumerable<T> GetAll();
16         IEnumerable<T> GetList(Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null);
17         Tuple<int, IEnumerable<T>> GetPage(Page page, Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null);
18         long Count(Expression<Func<T, bool>> where = null);
19     }

仓储的实现

这里我们只实现dapper的适配,EF有时间再搞吧

dapper大家应该都比较熟悉吧,不懂的朋友可以在园中搜索一下啊,很多案例

DapperRepository.cs

  1 using Dapper.Contrib.Extensions;
  2 using LjrFramework.Common;
  3 using LjrFramework.Interface;
  4 using System;
  5 using System.Collections.Generic;
  6 using System.Data;
  7 using System.Linq;
  8 using System.Linq.Expressions;
  9
 10 namespace LjrFramework.Data.Dapper
 11 {
 12     public class DapperRepository<T> : IRepository<T> where T : class
 13     {
 14         protected IDbConnection Conn { get; private set; }
 15
 16         public DapperRepository()
 17         {
 18             Conn = DbConnectionFactory.CreateDbConnection();
 19         }
 20
 21         public void SetDbConnection(IDbConnection conn)
 22         {
 23             Conn = conn;
 24         }
 25
 26         public void Add(T entity)
 27         {
 28             Conn.Insert<T>(entity);
 29         }
 30
 31         public void AddBatch(IEnumerable<T> entitys)
 32         {
 33             foreach (T entity in entitys)
 34             {
 35                 Add(entity);
 36             }
 37         }
 38
 39         public void Update(T entity)
 40         {
 41             Conn.Update(entity);
 42         }
 43
 44         public void Delete(T entity)
 45         {
 46             Conn.Delete(entity);
 47         }
 48
 49         public void Delete(string Id)
 50         {
 51             var entity = Get(Id);
 52             if (entity == null) return;
 53
 54             Delete(entity);
 55         }
 56
 57         public void Delete(int Id)
 58         {
 59             var entity = Get(Id);
 60             if (entity == null) return;
 61
 62             Delete(entity);
 63         }
 64         public void Delete(Guid Id)
 65         {
 66             var entity = Get(Id);
 67             if (entity == null) return;
 68
 69             Delete(entity);
 70         }
 71
 72         public T Get(T entity)
 73         {
 74             return Conn.Get<T>(entity);
 75         }
 76
 77         public T Get(Guid Id)
 78         {
 79             return Conn.Get<T>(Id);
 80         }
 81
 82         public T Get(string Id)
 83         {
 84             return Conn.Get<T>(Id);
 85         }
 86
 87         public T Get(int Id)
 88         {
 89             return Conn.Get<T>(Id);
 90         }
 91
 92         public T Get(Expression<Func<T, bool>> func)
 93         {
 94             var linqToWhere = new LinqToWhere<T>();
 95             linqToWhere.Parse(func);
 96
 97             return Conn.GetByFunc<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
 98         }
 99
100         public IEnumerable<T> GetAll()
101         {
102             return Conn.GetAll<T>();
103         }
104
105         public IEnumerable<T> GetList(Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null)
106         {
107             where = where.And(order);
108
109             var linqToWhere = new LinqToWhere<T>();
110             linqToWhere.Parse(where);
111
112             return Conn.GetListByFunc<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
113         }
114
115         public Tuple<int, IEnumerable<T>> GetPage(Page page, Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null)
116         {
117             where = where.And(order);
118
119             var linqToWhere = new LinqToWhere<T>();
120             linqToWhere.Parse(where);
121
122             var multi = Conn.GetPage<T>(page.PageIndex, page.PageSize, linqToWhere.Order, linqToWhere.Where, linqToWhere.KeyValuePairs);
123             var count = multi.Read<int>().Single();
124             var results = multi.Read<T>();
125
126             return new Tuple<int, IEnumerable<T>>(count, results);
127         }
128
129         public long Count(Expression<Func<T, bool>> where = null)
130         {
131             var linqToWhere = new LinqToWhere<T>();
132             linqToWhere.Parse(where);
133
134             return Conn.Count<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
135         }
136     }
137 }

注意标红的那行,Conn的所有方法都是在命名空间(Dapper.Contrib.Extensions)下的扩展方法

我们看看其中的Insert实现方式,为什么直接传递T就可以,而不用写sql语句

可以看到,dapper后台是遍历实体的属性,最后也是拼凑成符合格式的sql语句;

这一点也可以自己扩展,有很大的便利性,所以他写在Extensions中

DbConnectionFactory.cs 也很简单,是dapper支持多数据库的工厂类

 1 public class DbConnectionFactory
 2     {
 3         private static readonly string connectionString;
 4         private static readonly string databaseType;
 5
 6         static DbConnectionFactory()
 7         {
 8             var collection = ConfigurationManager.ConnectionStrings["connectionString"];
 9             connectionString = collection.ConnectionString;
10             databaseType = collection.ProviderName.ToLower();
11         }
12
13         public static IDbConnection CreateDbConnection()
14         {
15             IDbConnection connection = null;
16             switch (databaseType)
17             {
18                 case "system.data.sqlclient":
19                     connection = new System.Data.SqlClient.SqlConnection(connectionString);
20                     break;
21                 case "mysql":
22                     //connection = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
23                     break;
24                 case "oracle":
25                     //connection = new Oracle.DataAccess.Client.OracleConnection(connectionString);
26                     //connection = new System.Data.OracleClient.OracleConnection(connectionString);
27                     break;
28                 case "db2":
29                     connection = new System.Data.OleDb.OleDbConnection(connectionString);
30                     break;
31                 default:
32                     connection = new System.Data.SqlClient.SqlConnection(connectionString);
33                     break;
34             }
35             return connection;
36         }
37     }

自此,dapper适配的仓储就完成了

我们在测试项目中看看效果,这里我们不在继续在基础设施里添加仓储了,用另一种方式:IOC

项目引用Autofac,用依赖出入来初始化IRepository<T>接口

测试仓储功能

 1 [TestClass]
 2     public class DapperRepositoryTest
 3     {
 4         private IRepository<LoginUser> repository;
 5
 6         public DapperRepositoryTest()
 7         {
 8             var builder = new ContainerBuilder();
 9             builder.RegisterType<DapperRepository<LoginUser>>().As<IRepository<LoginUser>>();
10
11             var container = builder.Build();
12             repository = container.Resolve<IRepository<LoginUser>>();
13         }
14
15         [TestMethod]
16         public void Add()
17         {
18             var loginUser = new LoginUser()
19             {
20                 Id = Guid.NewGuid(),
21                 LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
22                 Password = "mima1987",
23                 IsEnabled = 1,
24                 CreateTime = DateTime.Now
25             };
26
27             repository.Add(loginUser);
28
29             long count = repository.Count(t => t.LoginName == loginUser.LoginName);
30
31             Assert.AreEqual(true, count == 1);
32         }
33
34         [TestMethod]
35         public void Get()
36         {
37             var loginUser = new LoginUser()
38             {
39                 Id = Guid.NewGuid(),
40                 LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
41                 Password = "mima1987",
42                 IsEnabled = 1,
43                 CreateTime = DateTime.Now
44             };
45             repository.Add(loginUser);
46
47             var tmp = repository.Get(loginUser.Id);
48             Assert.AreEqual(loginUser.Id, tmp.Id);
49
50             var tmp2 = repository.Get(w => w.Id == loginUser.Id && w.IsEnabled == loginUser.IsEnabled);
51             Assert.AreEqual(loginUser.Id, tmp2.Id);
52         }
53         ...//限于篇幅,只写这么多了,大部分代码都差不多
54     }

注意这句:container.Resolve<IRepository<LoginUser>>(); 这句就是实现初始化IRepository<T>接口;

如何初始化呢?看上一句:builder.RegisterType<DapperRepository<LoginUser>>().As<IRepository<LoginUser>>(); 直接注册DapperRepository就可以了

其实这里也可以用配置的方式初始化IRepository<T>,这样就可以避免DapperRepository<T>与业务层耦合了

测试项目,我们就暂且这么写吧。

我们来看看效果

下边都是这次测试生成的数据

自此 IRepository 就开发完成了

项目架构开发系列

分类: 架构设计

时间: 2024-10-13 22:04:13

数据访问层之Repository的相关文章

项目架构开发:数据访问层之Query

接上文 项目架构开发:数据访问层之Repository 上一章我们讲了IRepository接口,这张我们来讲IQuery 根据字面意思就可以知道,这次主要讲数据查询,上一章我们只针对单表做了查询的操作,多表联查并没有实现 其实对于任何一个项目来说,多表联查都是比较麻烦的地方,因为项目的“读”操作,特别是多表的“读”,至少占据所有“读”的一半以上 然而至今,据我所知还没有哪一款ORM工具可以灵活处理多表联查:想要不写sql语句,又想性能高,还想用强类型的ling查询方法:这对于多表查询来说比较难

Spring数据访问层Dao案例

本文描述的是通过spring框架实现数据持久化操作,具体内容如下: 1,POJO类定义: 1 import java.io.Serializable; 2 import java.util.Date; 3 4 public class User implements Serializable{ 5 private int userId; 6 7 private String userName; 8 9 private String password; 10 11 private int cred

一个通用的数据访问层实现类

在java商城开发中以及人事系统开发中我们知道会涉及到很多的数据表,如果每一个数据库都按照我们开发人员所定义的那样一个表,一个实现类,然后是一个数据访问层接口,数据访问层实现类,业务逻辑层接口,业务逻辑层实现类...这样写下去,代码量无疑是很大的. 下面我们就介绍一个基本的数据访问层实现类,至于接口的定义,我想只要明白实现类,接口的定义应该很简单. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

数据访问层的单元测试

出处:http://www.cnblogs.com/wintersun/ 数据访问层在分层结构,比较常见. 有时可能是数据访问模块. 假设数据访问层后端是数据库,那我们如何测试他们的呢? 有时实际这种测试是集成测试了.有时数据库里还有一些逻辑,触发器,约束等. 个人十分不建议把业务逻辑放在数据库里实现. 最常见的数据库表的操作create, read, update和delete(简称CRUD), 例如我们需要测试某个Add方法,在这个测试方法完成后, 希望这条测试数据清除掉. 这样做是 为了不

数据访问层及EntityFramework

数据访问层(Data Access Layer)负责与数据储存设备打交道,为业务层提供数据服务(一般指增.删.改.查).一个好的数据访问层可在不影响其他逻辑的情况下,替换数据访问技术.数据据库. 数据访问层的常见模式与原则 工作单元(Unit of Work) 维护一系列操作的事务性(Transaction),一系列操作要么都成功,如果有一个操作失败,则事务回滚.这里也主要用于对数据库的操作. 如果通过sql脚本直接访问数据库,可以直接用sql调用相应数据库的事务. 如果采用自己写的ORM,则可

微软-创建数据访问层

简介 https://msdn.microsoft.com/zh-cn/cc964016 作为web 开发人员,我们的工作总是在和数据打交道.我们创建数据库来存储数据,编写代码来检索并修改数据,并创建Web 页面来收集和汇总数据.这是探讨在ASP.NET 2.0 中实现这些常用类型的技巧的系列教程中的首篇教程.我们从创建一个 软件架构 开始,包括使用Typed DataSet 的数据访问层(DAL) .实现自定义业务规则的业务逻辑层(BLL) 和共享同一页面布局的ASP.NET 页面组成的表示层

使用Ninject+Moq在单元测试中抽象数据访问层

一.测试方法的业务逻辑时,通常都需要从数据库读取测试数据,但是每次初始化数据库数据都很麻烦,也会影响到其它业务对数据的访问,怎样抽象数据访问层呢?就是用Moq去模拟数据访问的逻辑 二.步骤如下 2.1 定义数据访问接口和实现 public interface IDBAccess { List<string> GetList(string request); } public class DBAccessImp : IDBAccess { public List<string> Ge

企业级应用框架(二)三层架构之数据访问层的封装与抽象

接上一篇我们来对数据访问层进行封装与抽象.在上一篇我们知道,要解除BLL对DAL的依赖,我们就必须抽象出DAL层的接口,同时基于DAL的数据访问技术很多,如EF,ADO.NET,LINQ TO SQL,因此,我们的数据访问层必须对这些技术提供相应的支持.所以今天我们要做的事情有两件,第一,定义我们的数据访问层接口:第二,屏蔽各类数据库访问技术的差异,提供统一的数据库访问模型.举个例子,我们只需要修改一下我们的配置文件,就能够把ADO.NET的实现方式,改变成EF的实现方式.好下面搭建我们的三层构

JavaEE使用三层架构(显示层、业务逻辑层、数据访问层)实现数据的增删改查

实例: 1.功能描述 实现一个简易新闻发布系统,包括查看.添加.修改和删除新闻等基本功能 2.具体要求 (1) 创建数据库 newssystem,创建表 news,要求如下: (2) 程序运行时,显示'发布新闻'页面(如图 1),输入相关内容,单击'提交'按钮,将新闻内容添加到数据库 (3) 单击图 1 中的'查看'按钮,显示'查看新闻'页面(如图 2),增加'修改'和'删除'链接 (4) 单击图 2 中的'update'链接,显示'修改新闻'页面(如图 3),修改后单击'修改'按钮确认,单击'