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

    项目架构开发系列

     
    分类: 架构设计
  • 相关阅读:
    自动机实验
    11.11评论
    语法分析
    201406114257 张俊毅 词法分析 修改完
    201406114257 张俊毅 词法分析
    做汉堡
    复利计算5.0-结队
    《构建之法》第4章的感悟
    复利计算4.0单元测试
    实验一 命令解释程序的编写
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6517332.html
Copyright © 2020-2023  润新知