数据访问层之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 就开发完成了

项目架构开发系列

 
分类: 架构设计

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

  1. 项目架构开发:数据访问层之Repository

    接上文 项目架构开发:数据访问层之Logger 本章我们继续IRepository开发,这个仓储与领域模式里边的仓储有区别,更像一个工具类,也就是有些园友说的“伪仓储”, 这个仓储只实现单表的CURD ...

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

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

  3. 项目架构开发:数据访问层之Logger

    接上文 项目架构开发:数据访问层之Cache 本章我们继续ILogger的开发 ILogger.cs public interface ILogger { void Info(object messa ...

  4. 项目架构开发:数据访问层之UnitOfWork

    接上文 项目架构开发:数据访问层之IQuery 本章我们继续IUnitOfWork的开发,从之前的IRepository接口中就可以看出,我们并没有处理单元事务, 数据CUD每次都是立即执行的,这样有 ...

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

    接上文 项目架构开发:数据访问层之Repository 上一章我们讲了IRepository接口,这张我们来讲IQuery 根据字面意思就可以知道,这次主要讲数据查询,上一章我们只针对单表做了查询的操 ...

  6. 数据访问模式之Repository模式

    数据访问模式之Repository模式   数据访问层无非就是对数据进行增删改查,其中增.删.改等我们可以抽象出来写一个公共的接口或抽象类来定义这些方法,并采用一个基类实现这些方法,这样该基类派生的子 ...

  7. ClownFish:比手写代码还快的通用数据访问层

    http://www.cnblogs.com/fish-li/archive/2012/07/17/ClownFish.html 阅读目录 开始 ClownFish是什么? 比手写代码还快的执行速度 ...

  8. 使用JDBC构建简单的数据访问层

    本教程的目的是使用Java编写的分离的层去访问数据库中的表,这一层通常称为数据访问层(DAL) 使用DAL的最大好处是通过直接使用一些类似insert()和find()的方法简化了数据库的访问操作,而 ...

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

    一.测试方法的业务逻辑时,通常都需要从数据库读取测试数据,但是每次初始化数据库数据都很麻烦,也会影响到其它业务对数据的访问,怎样抽象数据访问层呢?就是用Moq去模拟数据访问的逻辑     二.步骤如下 ...

随机推荐

  1. 修改IIS7并发连接数目限制

    转自原文 修改IIS7并发连接数目限制 1. 调整IIS 7应用程序池队列长度 由原来的默认1000改为65535. IIS Manager > ApplicationPools > Ad ...

  2. spring接收对象数组实例

    JS var param= new Array(); var one= new Object; one.id = '1'; one.name= 'simba1'; param.push(one); v ...

  3. Android Studio插件推荐-GsonFormat,ButterKnifeZelezny

    原创文章.转载请注明 http://blog.csdn.net/leejizhou/article/details/50557786 本篇介绍的仅仅适用android studio和 Intellij ...

  4. 【Codeforces Round #435 (Div. 2) A】Mahmoud and Ehab and the MEX

    [链接]h在这里写链接 [题意] 在这里写题意 [题解] 让x没有出现,以及0..x-1都出现就可以了. [错的次数] 0 [反思] 在这了写反思 [代码] #include <bits/std ...

  5. IOS RGB颜色转换

    - (UIColor *)getColor:(NSString *)hexColor { unsigned int red,green,blue; NSRange range; range.lengt ...

  6. bootstrap课程3 bootstrap中常用的排版样式有哪些

    bootstrap课程3 bootstrap中常用的排版样式有哪些 一.总结 一句话总结:bootstrap里面对常用表情比如p.h1.code等html中的常用表情都修改了样式,照着手册用就好,样式 ...

  7. sum()函数——MATLAB

    a=sum(A)  %列求和 b=sum(A,2) %行求和 c=sum(A(:)) %矩阵求和 假定A为一个矩阵: sum(A)以矩阵A的每一列为对象,对一列内的数字求和. sum(A,2)以矩阵A ...

  8. 【39.66%】【codeforces 740C】Alyona and mex

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  9. MySql Order By 多个字段 排序规则

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/xlxxcc/article/details/52250963 说在前面 突发奇想,想了解一下mysq ...

  10. 关于用strace工具定位vrrpd进程有时会挂死的bug

    只做工作总结备忘之用. 正在烧镜像,稍总结一下进来改bug遇到的问题. 一个项目里要用到L3 switch的nat,vrrp功能,但实地测试中偶然出现write file挂死的情况,但不是必现.交付在 ...