前言

好多年前,DAL 作为数据库访问层,其实是非常流行的命名方式。

不知道从什么时候开始,仓储层成了新的时尚名词。目前了解到,许多人只要在项目中看见 DAL 就会觉得很 low,但是比较可笑的一点是,多数的仓储层与 DAL 实质在做同样的事情。

本文正要介绍这种比较 low 的方式,来现实通用的仓储层。

参考规范

与其他规范标准一样,仓储层也有相应的规范定义。FreeSql.Repository 参考 abp vnext 代码,定义和实现基础的仓储层(CURD),应该算比较通用的方法吧。

IBasicRepository.cs 增删改接口

using System.Threading.Tasks;

namespace FreeSql {
public interface IBasicRepository<TEntity> : IReadOnlyRepository<TEntity>
where TEntity : class {
TEntity Insert(TEntity entity);
Task<TEntity> InsertAsync(TEntity entity); void Update(TEntity entity);
Task UpdateAsync(TEntity entity);
IUpdate<TEntity> UpdateDiy { get; } void Delete(TEntity entity);
Task DeleteAsync(TEntity entity);
} public interface IBasicRepository<TEntity, TKey> : IBasicRepository<TEntity>, IReadOnlyRepository<TEntity, TKey>
where TEntity : class {
void Delete(TKey id);
Task DeleteAsync(TKey id);
}
}

IReadOnlyRepository.cs 查询接口

using System.Threading.Tasks;

namespace FreeSql {
public interface IReadOnlyRepository<TEntity> : IRepository
where TEntity : class {
ISelect<TEntity> Select { get; }
} public interface IReadOnlyRepository<TEntity, TKey> : IReadOnlyRepository<TEntity>
where TEntity : class {
TEntity Get(TKey id);
Task<TEntity> GetAsync(TKey id); TEntity Find(TKey id);
Task<TEntity> FindAsync(TKey id);
}
}

IRepository.cs 仓储接口

using System;
using System.Linq.Expressions;
using System.Threading.Tasks; namespace FreeSql { public interface IRepository {
//预留
} public interface IRepository<TEntity> : IReadOnlyRepository<TEntity>, IBasicRepository<TEntity>
where TEntity : class {
void Delete(Expression<Func<TEntity, bool>> predicate);
Task DeleteAsync(Expression<Func<TEntity, bool>> predicate);
} public interface IRepository<TEntity, TKey> : IRepository<TEntity>, IReadOnlyRepository<TEntity, TKey>, IBasicRepository<TEntity, TKey>
where TEntity : class {
}
}

现实 BaseRepository.cs 通用的仓储基类

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks; namespace FreeSql {
public abstract class BaseRepository<TEntity> : IRepository<TEntity>
where TEntity : class {
protected IFreeSql _fsql;
public BaseRepository(IFreeSql fsql) : base() {
_fsql = fsql;
if (_fsql == null) throw new NullReferenceException("fsql 参数不可为空");
} public ISelect<TEntity> Select => _fsql.Select<TEntity>();
public IUpdate<TEntity> UpdateDiy => _fsql.Update<TEntity>(); public void Delete(Expression<Func<TEntity, bool>> predicate) => _fsql.Delete<TEntity>().Where(predicate).ExecuteAffrows();
public void Delete(TEntity entity) => _fsql.Delete<TEntity>(entity).ExecuteAffrows();
public Task DeleteAsync(Expression<Func<TEntity, bool>> predicate) => _fsql.Delete<TEntity>().Where(predicate).ExecuteAffrowsAsync();
public Task DeleteAsync(TEntity entity) => _fsql.Delete<TEntity>(entity).ExecuteAffrowsAsync(); public TEntity Insert(TEntity entity) => _fsql.Insert<TEntity>().AppendData(entity).ExecuteInserted().FirstOrDefault();
async public Task<TEntity> InsertAsync(TEntity entity) => (await _fsql.Insert<TEntity>().AppendData(entity).ExecuteInsertedAsync()).FirstOrDefault(); public void Update(TEntity entity) => _fsql.Update<TEntity>().SetSource(entity).ExecuteAffrows();
public Task UpdateAsync(TEntity entity) => _fsql.Update<TEntity>().SetSource(entity).ExecuteAffrowsAsync();
} public abstract class BaseRepository<TEntity, TKey> : BaseRepository<TEntity>, IRepository<TEntity, TKey>
where TEntity : class {
public BaseRepository(IFreeSql fsql) : base(fsql) {
} public void Delete(TKey id) => _fsql.Delete<TEntity>(id).ExecuteAffrows();
public Task DeleteAsync(TKey id) => _fsql.Delete<TEntity>(id).ExecuteAffrowsAsync(); public TEntity Find(TKey id) => _fsql.Select<TEntity>(id).ToOne();
public Task<TEntity> FindAsync(TKey id) => _fsql.Select<TEntity>(id).ToOneAsync(); public TEntity Get(TKey id) => Find(id);
public Task<TEntity> GetAsync(TKey id) => FindAsync(id);
}
}

如何使用?

1、安装

dotnet add package FreeSql.Repository

2、声明 FreeSql,为单例

var fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10")
.UseLogger(loggerFactory.CreateLogger<IFreeSql>())
.UseAutoSyncStructure(true) //自动迁移实体的结构到数据库
.Build();

ps: FreeSql 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite。

3、创建实体

public class Song {
[Column(IsIdentity = true)]
public int Id { get; set; }
public string Title { get; set; }
}

4、创建仓储层

public class SongRepository : BaseRepository<Song, int> {
public SongRepository(IFreeSql fsql) : base(fsql) {
}
}

解释:<Song, int> 泛值第一个参数Song是实体类型,第二个参数int为主键类型

至此,通过继承 BaseRepository 非常方便的实现了仓储层 SongRepository,他包含比较标准的 CURD 现实。

参考资料:https://github.com/2881099/FreeSql/wiki/Repository

结束语

FreeSql.Repository 的版本号目前与 FreeSql 同步更新,查看更新说明

FreeSql 特性

  • CodeFirst 迁移。
  • DbFirst 从数据库导入实体类,支持三种模板生成器。
  • 采用 ExpressionTree 高性能读取数据。
  • 类型映射深入支持,比如pgsql的数组类型,匠心制作。
  • 支持丰富的表达式函数。
  • 支持导航属性查询,和延时加载。
  • 支持同步/异步数据库操作方法,丰富多彩的链式查询方法。
  • 支持事务。
  • 支持多种数据库,MySql/SqlServer/PostgreSQL/Oracle/Sqlite。

Github:https://github.com/2881099/FreeSql

FreeSql.Repository 通用仓储层功能的更多相关文章

  1. FreeSql.Repository (一)什么是仓储

    欢迎来到<FreeSql.Repository 仓储模式>系列文档,完整文档请前往 wiki 中心:https://github.com/dotnetcore/FreeSql/wiki F ...

  2. .NET ORM 仓储层必备的功能介绍之 FreeSql Repository 实现篇

    写在开头 2018年11月的某一天,头脑发热开启了 FreeSql 开源项目之旅,时间一晃已经四年多,当初从舒服区走向一个巨大的坑,回头一看后背一凉.四年时间从无到有,经历了数不清的日夜奋战(有人问我 ...

  3. 用MVC5+EF6+WebApi 做一个考试功能(六) 仓储模式 打造EF通用仓储类

    前言 年底工作比较忙,年度总结还没写,项目要上线,回老家过年各种准备.尤其是给长辈给侄子侄女准备礼物头都大了. 原来想年前先出一版能用的,我看有点悬了,尽量先把大体功能弄出来,扔掉一些,保证能考试,然 ...

  4. (译文)MVC通用仓储类

    Generic Repository Pattern MVC Generic Repository Pattern MVC 原文链接:http://www.codeproject.com/Articl ...

  5. .netCore+Vue 搭建的简捷开发框架 (2)--仓储层实现和EFCore 的使用

    书接上文,继续搭建我们基于.netCore 的开发框架.首先是我们的项目分层结构. 这个分层结构,是参考张老师的分层结构,但是实际项目中,我没有去实现仓储模型.因为我使用的是EFCore ,最近也一直 ...

  6. MVC通用仓储类

    原文链接:http://www.codeproject.com/Articles/1095323/Generic-Repository-Pattern-MVC 良好的架构师任何项目的核心,开发人员一直 ...

  7. OSS.Core基于Dapper封装(表达式解析+Emit)仓储层的构思及实现

    最近趁着不忙,在构思一个搭建一个开源的完整项目,至于原因以及整个项目框架后边文章我再说明.既然要起一个完整的项目,那么数据仓储访问就必不可少,这篇文章我主要介绍这个新项目(OSS.Core)中我对仓储 ...

  8. EF通用数据层封装类(支持读写分离,一主多从)

    浅谈orm 记得四年前在学校第一次接触到 Ling to Sql,那时候瞬间发现不用手写sql语句是多么的方便,后面慢慢的接触了许多orm框架,像 EF,Dapper,Hibernate,Servic ...

  9. EFCore+Mysql仓储层建设(分页、多字段排序、部分字段更新)

    前沿 园子里已有挺多博文介绍了EFCore+Mysql/MSSql如何进行使用,但实际开发不会把EF层放在Web层混合起来,需要多个项目配合结构清晰的进行分层工作,本文根据个人实践经验总结将各个项目进 ...

随机推荐

  1. Cesium 云服务

    前言 所有行业内都知道云是未来或者现在的趋势,但是真正的完完全全提供地理信息云服务的恐怕只有 Google 一家,然而今天我居然发现 Cesium 提供了云服务,你没有看错,就是曾经的开源 3D 渲染 ...

  2. 微服务架构的基础框架选择:Spring Cloud还是Dubbo?

    最近一段时间不论互联网还是传统行业,凡是涉及信息技术范畴的圈子几乎都在讨论微服务架构.近期也看到各大技术社区开始组织一些沙龙和论坛来分享Spring Cloud的相关实施经验,这对于最近正在整理Spr ...

  3. Django中的Python高级特性

    本小文的内容实际是作为<Pro Django>第二版第二章的读书笔记简单总结. 1.类的构建:元类,使用带元类的基类----这个特性的案例主要就是models.Model类,用这种方式高效 ...

  4. 简述Action+Service +Dao 功能

    转载:http://blog.csdn.net/inter_peng/article/details/41021727 1. Action/Service/DAO简介: Action是管理业务(Ser ...

  5. Html5列表元素

    <ol> 有序列表: 属性:type(设置样式),reversed(倒序) <ul>无序列表 <li>表示列表中的项(在<ol>和<ul>中 ...

  6. 洛谷 P2725 解题报告

    P2725 邮票 Stamps 题目背景 给一组 N 枚邮票的面值集合(如,{1 分,3 分})和一个上限 K -- 表示信封上能够贴 K 张邮票.计算从 1 到 M 的最大连续可贴出的邮资. 题目描 ...

  7. 读《图解HTTP》有感-(返回结果的HTTP状态码)

    写在前面 HTTP状态码是由服务端产生,用于告诉客户端,服务端处理结果的编码 正文 1.状态码的作用是什么?具有什么特征? 状态码的作用是当客户端向服务器发送请求时,描述服务器的响应结果(如:服务器正 ...

  8. map和set的原理

    1)map:经过排序了的二元组的集合,map中的每个元素都是由两个值组成,其中的key(键值,一个map中的键值必须是唯一的) 是在排序或搜索时使用,它的值可以在容器中重新获取:而另一个值是该元素关联 ...

  9. .Net Core微服务系列--开篇

    记得原来有个项目是用wcf做的分布式,不仅横向根据业务拆分了,纵向把业务处理.数据访问等也拆分了成不同的服务,这个是当时公司的产品我也只是一个小小的开发人员所以就不做太多的评论,只是不得不吐槽下调试真 ...

  10. 那些年,我们追过的RPC

    1974年冬,互联网大师 Jon Postel发表了RFC674:“Procedure Call Protocol Documents,Version 2”,尝试定义一种在包含70个节点的网络中共享资 ...