好多年前,DAL 做爲數據庫訪問層,實際上是很是流行的命名方式。git
不知道從何時開始,倉儲層成了新的時尚名詞。目前瞭解到,許多人只要在項目中看見 DAL 就會以爲很 low,可是比較好笑的一點是,多數的倉儲層與 DAL 實質在作一樣的事情。github
本文正要介紹這種比較 low 的方式,來現實通用的倉儲層。sql
與其餘規範標準同樣,倉儲層也有相應的規範定義。FreeSql.Repository 參考 abp vnext 代碼,定義和實現基礎的倉儲層(CURD),應該算比較通用的方法吧。數據庫
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); } }
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); } }
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 { } }
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); } }
一、安裝數組
dotnet add package FreeSql.Repository
二、聲明 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。async
三、建立實體函數
public class Song { [Column(IsIdentity = true)] public int Id { get; set; } public string Title { get; set; } }
四、建立倉儲層性能
public class SongRepository : BaseRepository<Song, int> { public SongRepository(IFreeSql fsql) : base(fsql) { } }
解釋:<Song, int> 泛值第一個參數Song是實體類型,第二個參數int爲主鍵類型ui
至此,經過繼承 BaseRepository 很是方便的實現了倉儲層 SongRepository,他包含比較標準的 CURD 現實。
參考資料:https://github.com/2881099/FreeSql/wiki/Repository
FreeSql.Repository 的版本號目前與 FreeSql 同步更新,查看更新說明;
FreeSql 特性