FreeSql.Repository 通用仓储层功能

摘要:
前言好多年前,DAL作为数据库访问层,其实是非常流行的命名方式。不知道从什么时候开始,仓储层成了新的时尚名词。目前了解到,许多人只要在项目中看见DAL就会觉得很low,但是比较可笑的一点是,多数的仓储层与DAL实质在做同样的事情。本文正要介绍这种比较low的方式,来现实通用的仓储层。参考规范与其他规范标准一样,仓储层也有相应的规范定义。FreeSql.Repository参考abpvnext代码,定义和实现基础的仓储层,应该算比较通用的方法吧。

前言

好多年前,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 通用仓储层功能》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇2019-11-29-dotnet-core-使用-GBK-编码iOS 部分机制下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

IDEA 运行键是灰色

版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议。转载请附上原始来源链接和本声明。本文链接:https://blog.csdn.net/Butterfly_resting/article/details/89388149原因是我们的新项目没有选择源目录,如图所示:解决方案:IDEA提供了选择源目录的快速设置。右键单击src并选择MarkDire...

MySQL高可用集群方案

资源不足的小团队或小项目直接建议阿里云和腾讯云II。一些常见解决方案介绍1。MySQL主从架构2。MHA架构参考:生产环境MySQL数据库集群MHA在线实现解决方案MHA目前是MySQL高可用性中比较成熟的解决方案。...

当微信小程序遇到AR(二)

当微信小程序遇到AR,会擦出怎么样的火花?期待与激动......通过该教程,可以从基础开始打造一个微信小程序的AR框架,所有代码开源,提供大家学习。注册地址=˃注册成功之后,需要下载微信小程序开发工具。下载地址=˃目前笔者的开发环境是:Windows10下载的微信小程序版本为:RCv1.0.2.1909111 打开,微信开发者工具之后,会看到如下的页面。...

oracle触发器调试

如果触发器执行成功,不会出现第4个图,不成功,会出现数据调试信息,具体报错位置会定位到。F7单步执行4.出错时,会出现调试数据,双击调试数据,可以复制出来...

Windows 远程桌面连接ubuntu及xrdp的一些小问题(远程桌面闪退、连接失败、tab补全功能,无菜单栏,error

想要修改,在windowsmanager中,keyboard里将用到Super+Tab的快捷键clear掉即可。解决:通过设置sesman.in文件内的参数解决:cat/etc/xrdp/sesman.inivi/etc/xrdp/sesman.ini可以修改会话设置:将最大会话限制该大MaxSessions=50;将KillDisconnected=1;则...

关于异常STATUS_IN_PAGE_ERROR(0xC0000006)

表示0x%p处的指令引用了位于0x%p的内存。由于0x%x的I/O错误状态,未将所需数据放入内存。设备如果读取出错,驱动程序可以返回此异常。其定义如下:////MessageId:STATUS_IN_PAGE_ERROR////MessageText:////Theinstructionat0x%preferencedmemoryat0x%p.Therequ...