FreeSql.Repository 通用倉儲層功能

前言

好多年前,DAL 做爲數據庫訪問層,實際上是很是流行的命名方式。git

不知道從何時開始,倉儲層成了新的時尚名詞。目前瞭解到,許多人只要在項目中看見 DAL 就會以爲很 low,可是比較好笑的一點是,多數的倉儲層與 DAL 實質在作一樣的事情。github

本文正要介紹這種比較 low 的方式,來現實通用的倉儲層。sql

參考規範

與其餘規範標準同樣,倉儲層也有相應的規範定義。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);
    }
}

如何使用?

一、安裝數組

dotnet add package FreeSql.Repository異步

二、聲明 FreeSql,爲單例async

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。函數

三、建立實體性能

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

四、建立倉儲層ui

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

相關文章
相關標籤/搜索