zoukankan      html  css  js  c++  java
  • FreeSql.Repository 通用仓储层功能

    前言

    好多年前,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

  • 相关阅读:
    17.1.2.1 Advantages and Disadvantages of Statement-Based and Row-Based Replication
    17.1.2 Replication Formats
    Setting the Master Configuration on the Slave
    17.1.1.9 Introducing Additional Slaves to an Existing Replication Environment
    17.1.1.8 Setting Up Replication with Existing Data
    17.1.1.7 Setting Up Replication with New Master and Slaves
    17.1.1.6 Creating a Data Snapshot Using Raw Data Files
    列出display的值,并说明它们的作用
    CSS设置DIV居中
    CSS选择符有哪些?哪些属性可以继承?优先级算法如何计算?
  • 原文地址:https://www.cnblogs.com/kellynic/p/10406319.html
Copyright © 2011-2022 走看看