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

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

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

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

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

IRepository.cs

     public interface IRepository<T> where T : class
{
void Add(T entity);
void AddBatch(IEnumerable<T> entitys);
void Update(T entity);
void Delete(T entity);
void Delete(string Id);
void Delete(int Id);
void Delete(Guid Id);
T Get(string Id);
T Get(Guid Id);
T Get(int Id);
T Get(T entity);
T Get(Expression<Func<T, bool>> func);
IEnumerable<T> GetAll();
IEnumerable<T> GetList(Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null);
Tuple<int, IEnumerable<T>> GetPage(Page page, Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null);
long Count(Expression<Func<T, bool>> where = null);
}

仓储的实现

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

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

DapperRepository.cs

 using Dapper.Contrib.Extensions;
using LjrFramework.Common;
using LjrFramework.Interface;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions; namespace LjrFramework.Data.Dapper
{
public class DapperRepository<T> : IRepository<T> where T : class
{
protected IDbConnection Conn { get; private set; } public DapperRepository()
{
Conn = DbConnectionFactory.CreateDbConnection();
} public void SetDbConnection(IDbConnection conn)
{
Conn = conn;
} public void Add(T entity)
{
Conn.Insert<T>(entity);
} public void AddBatch(IEnumerable<T> entitys)
{
foreach (T entity in entitys)
{
Add(entity);
}
} public void Update(T entity)
{
Conn.Update(entity);
} public void Delete(T entity)
{
Conn.Delete(entity);
} public void Delete(string Id)
{
var entity = Get(Id);
if (entity == null) return; Delete(entity);
} public void Delete(int Id)
{
var entity = Get(Id);
if (entity == null) return; Delete(entity);
}
public void Delete(Guid Id)
{
var entity = Get(Id);
if (entity == null) return; Delete(entity);
} public T Get(T entity)
{
return Conn.Get<T>(entity);
} public T Get(Guid Id)
{
return Conn.Get<T>(Id);
} public T Get(string Id)
{
return Conn.Get<T>(Id);
} public T Get(int Id)
{
return Conn.Get<T>(Id);
} public T Get(Expression<Func<T, bool>> func)
{
var linqToWhere = new LinqToWhere<T>();
linqToWhere.Parse(func); return Conn.GetByFunc<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
} public IEnumerable<T> GetAll()
{
return Conn.GetAll<T>();
} public IEnumerable<T> GetList(Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null)
{
where = where.And(order); var linqToWhere = new LinqToWhere<T>();
linqToWhere.Parse(where); return Conn.GetListByFunc<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
} public Tuple<int, IEnumerable<T>> GetPage(Page page, Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null)
{
where = where.And(order); var linqToWhere = new LinqToWhere<T>();
linqToWhere.Parse(where); var multi = Conn.GetPage<T>(page.PageIndex, page.PageSize, linqToWhere.Order, linqToWhere.Where, linqToWhere.KeyValuePairs);
var count = multi.Read<int>().Single();
var results = multi.Read<T>(); return new Tuple<int, IEnumerable<T>>(count, results);
} public long Count(Expression<Func<T, bool>> where = null)
{
var linqToWhere = new LinqToWhere<T>();
linqToWhere.Parse(where); return Conn.Count<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
}
}
}

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

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

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

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

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

 public class DbConnectionFactory
{
private static readonly string connectionString;
private static readonly string databaseType; static DbConnectionFactory()
{
var collection = ConfigurationManager.ConnectionStrings["connectionString"];
connectionString = collection.ConnectionString;
databaseType = collection.ProviderName.ToLower();
} public static IDbConnection CreateDbConnection()
{
IDbConnection connection = null;
switch (databaseType)
{
case "system.data.sqlclient":
connection = new System.Data.SqlClient.SqlConnection(connectionString);
break;
case "mysql":
//connection = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
break;
case "oracle":
//connection = new Oracle.DataAccess.Client.OracleConnection(connectionString);
//connection = new System.Data.OracleClient.OracleConnection(connectionString);
break;
case "db2":
connection = new System.Data.OleDb.OleDbConnection(connectionString);
break;
default:
connection = new System.Data.SqlClient.SqlConnection(connectionString);
break;
}
return connection;
}
}

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

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

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

测试仓储功能

 [TestClass]
public class DapperRepositoryTest
{
private IRepository<LoginUser> repository; public DapperRepositoryTest()
{
var builder = new ContainerBuilder();
builder.RegisterType<DapperRepository<LoginUser>>().As<IRepository<LoginUser>>(); var container = builder.Build();
repository = container.Resolve<IRepository<LoginUser>>();
} [TestMethod]
public void Add()
{
var loginUser = new LoginUser()
{
Id = Guid.NewGuid(),
LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
Password = "mima1987",
IsEnabled = ,
CreateTime = DateTime.Now
}; repository.Add(loginUser); long count = repository.Count(t => t.LoginName == loginUser.LoginName); Assert.AreEqual(true, count == );
} [TestMethod]
public void Get()
{
var loginUser = new LoginUser()
{
Id = Guid.NewGuid(),
LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
Password = "mima1987",
IsEnabled = ,
CreateTime = DateTime.Now
};
repository.Add(loginUser); var tmp = repository.Get(loginUser.Id);
Assert.AreEqual(loginUser.Id, tmp.Id); var tmp2 = repository.Get(w => w.Id == loginUser.Id && w.IsEnabled == loginUser.IsEnabled);
Assert.AreEqual(loginUser.Id, tmp2.Id);
}
...//限于篇幅,只写这么多了,大部分代码都差不多
}

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

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

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

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

我们来看看效果

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

自此 IRepository 就开发完成了

项目架构开发系列

项目架构开发:数据访问层之Repository的更多相关文章

  1. 数据访问层之Repository

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

  2. 企业级应用架构(三)三层架构之数据访问层的改进以及测试DOM的发布

    在上一篇我们在宏观概要上对DAL层进行了封装与抽象.我们的目的主要有两个:第一,解除BLL层对DAL层的依赖,这一点我们通过定义接口做到了:第二,使我们的DAL层能够支持一切数据访问技术,如Ado.n ...

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

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

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

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

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

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

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

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

  7. 随机获得MySQL数据库中100条数据方法 驾照题库项目 MVC架构 biz业务层的实现类 根据考试类型rand或order通过dao数据访问层接口得到数据库中100或全部数据

    package com.swift.jztk.biz; import java.util.Collections; import java.util.Comparator; import java.u ...

  8. asp.net/wingtip/创建数据访问层

    一. 什么是数据访问层 在wingtip项目中,数据访问层是对以下三者的总称:1. product类等数据相关的实体类(class)2. 数据库(database),对实体类成员的存储3. 上述二者的 ...

  9. servlet层调用biz业务层出现浏览器 500错误,解决方法 dao数据访问层 数据库Util工具类都可能出错 通过新建一个测试类复制代码逐步测试查找出最终出错原因

    package com.swift.jztk.servlet; import java.io.IOException; import javax.servlet.ServletException; i ...

随机推荐

  1. iOS 之 二维码生成与扫描(LBXScan)

    参考:https://github.com/MxABC/LBXScan 步骤如下: 1. 下载 通过参考网址进行下载. 2. 导入 导入整个LBXScan文件夹 3. 配置 在pch中加入 #impo ...

  2. 样式(Style)和主题(Theme)资源——主题资源

    与样式资源非常相似,主题资源的XML文件通常也放在/res/values 目录下,主题资源的XML文档同样以<resources.../>元素作为根元素,同样使用<style.../ ...

  3. 1.4.2.1. FILES(Core Data 应用程序实践指南)

    #define debug 1 #pragma mark - FILES NSString *storeFilename = @"Grocery-Dude.sqlite";

  4. 一点养老APP模式定制系统平台源码

    一点养老APP模式定制系统开发:136.1013.1824电/微:搭建一点养老APP模式定制系统平台.专注于为企业和商家客户提供基于腾讯微信公众平台系统程序和APP等开发服务,中国养老金融50人论坛2 ...

  5. QT第四天学习

    回顾: 1.信号与槽 public slots: //先声明后实现 signals: //只需要声明 connect(sender,SIGNAL(signal()),receiver,SLOT(slo ...

  6. js原生设计模式——10适配器模式之参数适配器

    原理:参数适配器说白了就是给出要带入数据字段的对应字段的默认值,一旦数据字段值不足,就取默认值补足. [写法一]:直接返回 <!DOCTYPE html><html lang=&qu ...

  7. HTML模块化:使用HTML5 Boilerplate模板

    HTML5 Boilerplate 是一个由 Paul Irish(Google Chrome 开发人员.jQuery 项目成员.Modernizr 作者.yayQuery 播客主持人)主导的“前端开 ...

  8. iOS 英语

    allocation:分配 agrregate :聚合,聚集,总计.在iOS中是一种文件类型. atomically:原子级的 archiver:归档.例如,oc专门有归档类NSKeyedArchiv ...

  9. TIMESTAMP和DATETIME哪个好

    日期范围 TIMESTAMP 支持从'1970-01-01 00:00:01′ 到 '2038-01-19 03:14:07′ UTC. 这个时间可能对目前正在工作的人来说没什么问题,可以坚持到我们退 ...

  10. Flex移动应用程序开发的技巧和窍门(四)

    范例文件 flex-mobile-dev-tips-tricks-pt4.zip 这是本系列文章的第四部分,该系列文章涵盖Flex移动开发的秘诀与窍门. 第一部分关注切换视图以及切换执行应用时的数据处 ...