mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 10:42:52 +08:00
FreeSql.DbContext 融合 Repository + UnitOfWork
This commit is contained in:
parent
496750da94
commit
a7e06843a9
@ -13,8 +13,9 @@ namespace FreeSql {
|
||||
internal IFreeSql _orm;
|
||||
internal IFreeSql _fsql => _orm ?? throw new ArgumentNullException("请在 OnConfiguring 或 AddFreeDbContext 中配置 UseFreeSql");
|
||||
|
||||
UnitOfWork _uowPriv;
|
||||
internal UnitOfWork _uow => _uowPriv ?? (_uowPriv = new UnitOfWork(_fsql));
|
||||
IUnitOfWork _uowPriv;
|
||||
internal IUnitOfWork _uow => _isUseUnitOfWork ? (_uowPriv ?? (_uowPriv = new UnitOfWork(_fsql))) : null;
|
||||
internal bool _isUseUnitOfWork = true; //不使用工作单元事务
|
||||
|
||||
static ConcurrentDictionary<Type, PropertyInfo[]> _dicGetDbSetProps = new ConcurrentDictionary<Type, PropertyInfo[]>();
|
||||
protected DbContext() {
|
||||
@ -41,15 +42,14 @@ namespace FreeSql {
|
||||
}
|
||||
|
||||
|
||||
Dictionary<Type, object> _dicSet = new Dictionary<Type, object>();
|
||||
protected Dictionary<Type, object> _dicSet = new Dictionary<Type, object>();
|
||||
public DbSet<TEntity> Set<TEntity>() where TEntity : class => this.Set(typeof(TEntity)) as DbSet<TEntity>;
|
||||
public object Set(Type entityType) {
|
||||
public virtual object Set(Type entityType) {
|
||||
if (_dicSet.ContainsKey(entityType)) return _dicSet[entityType];
|
||||
var sd = Activator.CreateInstance(typeof(BaseDbSet<>).MakeGenericType(entityType), this);
|
||||
var sd = Activator.CreateInstance(typeof(DbContextDbSet<>).MakeGenericType(entityType), this);
|
||||
_dicSet.Add(entityType, sd);
|
||||
return sd;
|
||||
}
|
||||
|
||||
protected Dictionary<string, object> AllSets { get; } = new Dictionary<string, object>();
|
||||
|
||||
internal class ExecCommandInfo {
|
||||
@ -60,7 +60,7 @@ namespace FreeSql {
|
||||
}
|
||||
internal enum ExecCommandInfoType { Insert, Update, Delete }
|
||||
Queue<ExecCommandInfo> _actions = new Queue<ExecCommandInfo>();
|
||||
internal long _affrows = 0;
|
||||
internal int _affrows = 0;
|
||||
|
||||
internal void EnqueueAction(ExecCommandInfoType actionType, object dbSet, Type stateType, object state) {
|
||||
_actions.Enqueue(new ExecCommandInfo { actionType = actionType, dbSet = dbSet, stateType = stateType, state = state });
|
||||
@ -73,7 +73,11 @@ namespace FreeSql {
|
||||
public void Dispose() {
|
||||
if (_isdisposed) return;
|
||||
try {
|
||||
_uow.Rollback();
|
||||
_actions.Clear();
|
||||
_dicSet.Clear();
|
||||
AllSets.Clear();
|
||||
|
||||
_uow?.Rollback();
|
||||
} finally {
|
||||
_isdisposed = true;
|
||||
GC.SuppressFinalize(this);
|
||||
|
@ -11,14 +11,17 @@ using System.Threading.Tasks;
|
||||
namespace FreeSql {
|
||||
partial class DbContext {
|
||||
|
||||
async public Task<long> SaveChangesAsync() {
|
||||
async public Task<int> SaveChangesAsync() {
|
||||
await ExecCommandAsync();
|
||||
_uow.Commit();
|
||||
return _affrows;
|
||||
_uow?.Commit();
|
||||
var ret = _affrows;
|
||||
_affrows = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Dictionary<Type, Dictionary<string, Func<object, object[], Task<int>>>> _dicExecCommandDbContextBetchAsync = new Dictionary<Type, Dictionary<string, Func<object, object[], Task<int>>>>();
|
||||
async internal Task ExecCommandAsync() {
|
||||
if (_actions.Any() == false) return;
|
||||
ExecCommandInfo oldinfo = null;
|
||||
var states = new List<object>();
|
||||
|
||||
|
@ -10,14 +10,17 @@ using System.Linq.Expressions;
|
||||
namespace FreeSql {
|
||||
partial class DbContext {
|
||||
|
||||
public long SaveChanges() {
|
||||
public int SaveChanges() {
|
||||
ExecCommand();
|
||||
_uow.Commit();
|
||||
return _affrows;
|
||||
_uow?.Commit();
|
||||
var ret = _affrows;
|
||||
_affrows = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Dictionary<Type, Dictionary<string, Func<object, object[], int>>> _dicExecCommandDbContextBetch = new Dictionary<Type, Dictionary<string, Func<object, object[], int>>>();
|
||||
internal void ExecCommand() {
|
||||
if (_actions.Any() == false) return;
|
||||
ExecCommandInfo oldinfo = null;
|
||||
var states = new List<object>();
|
||||
|
||||
|
@ -7,29 +7,41 @@ using System.Linq.Expressions;
|
||||
|
||||
namespace FreeSql {
|
||||
|
||||
internal class BaseDbSet<TEntity> : DbSet<TEntity> where TEntity : class {
|
||||
internal class DbContextDbSet<TEntity> : DbSet<TEntity> where TEntity : class {
|
||||
|
||||
public BaseDbSet(DbContext ctx) {
|
||||
if (ctx != null) {
|
||||
public DbContextDbSet(DbContext ctx) {
|
||||
_ctx = ctx;
|
||||
_uow = ctx._uow;
|
||||
_fsql = ctx._fsql;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract partial class DbSet<TEntity> where TEntity : class {
|
||||
public abstract partial class DbSet<TEntity> : IDisposable where TEntity : class {
|
||||
|
||||
internal DbContext _ctx;
|
||||
internal UnitOfWork _uow;
|
||||
internal IUnitOfWork _uow;
|
||||
internal IFreeSql _fsql;
|
||||
bool IsNoneDbContext => _ctx == null;
|
||||
|
||||
protected virtual ISelect<TEntity> OrmSelect(object dywhere) {
|
||||
DbContextExecCommand(); //查询前先提交,否则会出脏读
|
||||
return _fsql.Select<TEntity>(dywhere).WithTransaction(_uow?.GetOrBeginTransaction(false)).TrackToList(TrackToList);
|
||||
}
|
||||
|
||||
~DbSet() {
|
||||
this.Dispose();
|
||||
}
|
||||
bool _isdisposed = false;
|
||||
public void Dispose() {
|
||||
if (_isdisposed) return;
|
||||
try {
|
||||
this._dicUpdateTimes.Clear();
|
||||
this._states.Clear();
|
||||
} finally {
|
||||
_isdisposed = true;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IInsert<TEntity> OrmInsert() => _fsql.Insert<TEntity>().WithTransaction(_uow?.GetOrBeginTransaction());
|
||||
protected virtual IInsert<TEntity> OrmInsert(TEntity data) => _fsql.Insert<TEntity>(data).WithTransaction(_uow?.GetOrBeginTransaction());
|
||||
protected virtual IInsert<TEntity> OrmInsert(IEnumerable<TEntity> data) => _fsql.Insert<TEntity>(data).WithTransaction(_uow?.GetOrBeginTransaction());
|
||||
@ -38,11 +50,9 @@ namespace FreeSql {
|
||||
protected virtual IDelete<TEntity> OrmDelete(object dywhere) => _fsql.Delete<TEntity>(dywhere).WithTransaction(_uow?.GetOrBeginTransaction());
|
||||
|
||||
internal void EnqueueToDbContext(DbContext.ExecCommandInfoType actionType, EntityState state) {
|
||||
if (IsNoneDbContext == false)
|
||||
_ctx.EnqueueAction(actionType, this, typeof(EntityState), state);
|
||||
}
|
||||
internal void IncrAffrows(long affrows) {
|
||||
if (IsNoneDbContext == false)
|
||||
internal void IncrAffrows(int affrows) {
|
||||
_ctx._affrows += affrows;
|
||||
}
|
||||
internal void TrackToList(object list) {
|
||||
|
@ -8,12 +8,9 @@ namespace FreeSql {
|
||||
partial class DbSet<TEntity> {
|
||||
|
||||
Task DbContextExecCommandAsync() {
|
||||
if (IsNoneDbContext == false) {
|
||||
_dicUpdateTimes.Clear();
|
||||
return _ctx.ExecCommandAsync();
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
async Task<int> DbContextBetchAddAsync(EntityState[] adds) {
|
||||
if (adds.Any() == false) return 0;
|
||||
@ -59,9 +56,6 @@ namespace FreeSql {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (IsNoneDbContext)
|
||||
IncrAffrows(await OrmInsert(data).ExecuteAffrowsAsync());
|
||||
else
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(data));
|
||||
}
|
||||
}
|
||||
@ -94,9 +88,6 @@ namespace FreeSql {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (IsNoneDbContext)
|
||||
IncrAffrows(await OrmInsert(data).ExecuteAffrowsAsync());
|
||||
else
|
||||
//进入队列,等待 SaveChanges 时执行
|
||||
foreach (var s in data)
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(s));
|
||||
@ -154,56 +145,6 @@ namespace FreeSql {
|
||||
//等待下次对比再保存
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal Task<int> UpdateAffrowsAsync(TEntity data) => UpdateRangeAffrowsAsync(new[] { data });
|
||||
async internal Task<int> UpdateRangeAffrowsAsync(IEnumerable<TEntity> data) {
|
||||
if (CanUpdate(data, true) == false) return 0;
|
||||
if (IsNoneDbContext) {
|
||||
var dataarray = data.ToArray();
|
||||
var ups = new List<EntityState>();
|
||||
var totalAffrows = 0;
|
||||
for (var a = 0; a < dataarray.Length + 1; a++) {
|
||||
var item = a < dataarray.Length ? dataarray[a] : null;
|
||||
if (item != null) {
|
||||
var state = CreateEntityState(item);
|
||||
state.Value = item;
|
||||
ups.Add(state);
|
||||
}
|
||||
|
||||
var affrows = await DbContextBetchUpdatePrivAsync(ups.ToArray(), item == null);
|
||||
if (affrows == -999) { //最后一个元素已被删除
|
||||
ups.RemoveAt(ups.Count - 1);
|
||||
continue;
|
||||
}
|
||||
if (affrows == -998 || affrows == -997) { //没有执行更新
|
||||
var laststate = ups[ups.Count - 1];
|
||||
ups.Clear();
|
||||
if (affrows == -997) ups.Add(laststate); //保留最后一个
|
||||
}
|
||||
if (affrows > 0) {
|
||||
totalAffrows += affrows;
|
||||
var islastNotUpdated = ups.Count != affrows;
|
||||
var laststate = ups[ups.Count - 1];
|
||||
ups.Clear();
|
||||
if (islastNotUpdated) ups.Add(laststate); //保留最后一个
|
||||
}
|
||||
}
|
||||
IncrAffrows(totalAffrows);
|
||||
return totalAffrows;
|
||||
}
|
||||
foreach (var item in data) {
|
||||
if (_dicUpdateTimes.ContainsKey(item))
|
||||
await DbContextExecCommandAsync();
|
||||
_dicUpdateTimes.Add(item, 1);
|
||||
|
||||
var state = CreateEntityState(item);
|
||||
state.OldValue = item;
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Update, state);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
internal Task UpdateAsync(TEntity data) => UpdateAffrowsAsync(data);
|
||||
internal Task UpdateRangeAsync(IEnumerable<TEntity> data) => UpdateRangeAffrowsAsync(data);
|
||||
#endregion
|
||||
|
||||
#region RemoveAsync
|
||||
@ -212,28 +153,6 @@ namespace FreeSql {
|
||||
var affrows = await this.OrmDelete(dels.Select(a => a.Value)).ExecuteAffrowsAsync();
|
||||
return Math.Max(dels.Length, affrows);
|
||||
}
|
||||
|
||||
internal Task<int> RemoveAffrowsAsync(TEntity data) => RemoveRangeAffrowsAsync(new[] { data });
|
||||
async internal Task<int> RemoveRangeAffrowsAsync(IEnumerable<TEntity> data) {
|
||||
if (CanRemove(data, true) == false) return 0;
|
||||
var dels = new List<EntityState>();
|
||||
foreach (var item in data) {
|
||||
var state = CreateEntityState(item);
|
||||
if (_states.ContainsKey(state.Key)) _states.Remove(state.Key);
|
||||
_fsql.ClearEntityPrimaryValueWithIdentityAndGuid(item);
|
||||
|
||||
if (IsNoneDbContext) dels.Add(state);
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Delete, state);
|
||||
}
|
||||
if (IsNoneDbContext) {
|
||||
var affrows = await DbContextBetchRemoveAsync(dels.ToArray());
|
||||
IncrAffrows(affrows);
|
||||
return affrows;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
internal Task RemoveAsync(TEntity data) => RemoveAffrowsAsync(data);
|
||||
internal Task RemoveRangeAsync(IEnumerable<TEntity> data) => RemoveRangeAffrowsAsync(data);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,9 @@ namespace FreeSql {
|
||||
partial class DbSet<TEntity> {
|
||||
|
||||
void DbContextExecCommand() {
|
||||
if (IsNoneDbContext == false) {
|
||||
_dicUpdateTimes.Clear();
|
||||
_ctx.ExecCommand();
|
||||
}
|
||||
}
|
||||
|
||||
int DbContextBetchAdd(EntityState[] adds) {
|
||||
if (adds.Any() == false) return 0;
|
||||
@ -56,13 +54,9 @@ namespace FreeSql {
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (IsNoneDbContext)
|
||||
IncrAffrows(OrmInsert(data).ExecuteAffrows());
|
||||
else
|
||||
} else
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(data));
|
||||
}
|
||||
}
|
||||
public void Add(TEntity data) => AddPriv(data, true);
|
||||
public void AddRange(IEnumerable<TEntity> data) {
|
||||
if (CanAdd(data, true) == false) return;
|
||||
@ -92,9 +86,6 @@ namespace FreeSql {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (IsNoneDbContext)
|
||||
IncrAffrows(OrmInsert(data).ExecuteAffrows());
|
||||
else
|
||||
//进入队列,等待 SaveChanges 时执行
|
||||
foreach (var s in data)
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(s));
|
||||
@ -154,42 +145,9 @@ namespace FreeSql {
|
||||
}
|
||||
|
||||
Dictionary<TEntity, byte> _dicUpdateTimes = new Dictionary<TEntity, byte>();
|
||||
internal int UpdateAffrows(TEntity data) => UpdateRangeAffrows(new[] { data });
|
||||
internal int UpdateRangeAffrows(IEnumerable<TEntity> data) {
|
||||
if (CanUpdate(data, true) == false) return 0;
|
||||
if (IsNoneDbContext) {
|
||||
var dataarray = data.ToArray();
|
||||
var ups = new List<EntityState>();
|
||||
var totalAffrows = 0;
|
||||
for (var a = 0; a < dataarray.Length + 1; a++) {
|
||||
var item = a < dataarray.Length ? dataarray[a] : null;
|
||||
if (item != null) {
|
||||
var state = CreateEntityState(item);
|
||||
state.Value = item;
|
||||
ups.Add(state);
|
||||
}
|
||||
|
||||
var affrows = DbContextBetchUpdatePriv(ups.ToArray(), item == null);
|
||||
if (affrows == -999) { //最后一个元素已被删除
|
||||
ups.RemoveAt(ups.Count - 1);
|
||||
continue;
|
||||
}
|
||||
if (affrows == -998 || affrows == -997) { //没有执行更新
|
||||
var laststate = ups[ups.Count - 1];
|
||||
ups.Clear();
|
||||
if (affrows == -997) ups.Add(laststate); //保留最后一个
|
||||
}
|
||||
if (affrows > 0) {
|
||||
totalAffrows += affrows;
|
||||
var islastNotUpdated = ups.Count != affrows;
|
||||
var laststate = ups[ups.Count - 1];
|
||||
ups.Clear();
|
||||
if (islastNotUpdated) ups.Add(laststate); //保留最后一个
|
||||
}
|
||||
}
|
||||
IncrAffrows(totalAffrows);
|
||||
return totalAffrows;
|
||||
}
|
||||
public void Update(TEntity data) => UpdateRange(new[] { data });
|
||||
public void UpdateRange(IEnumerable<TEntity> data) {
|
||||
if (CanUpdate(data, true) == false) return;
|
||||
foreach (var item in data) {
|
||||
if (_dicUpdateTimes.ContainsKey(item))
|
||||
DbContextExecCommand();
|
||||
@ -199,10 +157,7 @@ namespace FreeSql {
|
||||
state.OldValue = item;
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Update, state);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public void Update(TEntity data) => UpdateAffrows(data);
|
||||
public void UpdateRange(IEnumerable<TEntity> data) => UpdateRangeAffrows(data);
|
||||
#endregion
|
||||
|
||||
#region Remove
|
||||
@ -212,27 +167,17 @@ namespace FreeSql {
|
||||
return Math.Max(dels.Length, affrows);
|
||||
}
|
||||
|
||||
internal int RemoveAffrows(TEntity data) => RemoveRangeAffrows(new[] { data });
|
||||
internal int RemoveRangeAffrows(IEnumerable<TEntity> data) {
|
||||
if (CanRemove(data, true) == false) return 0;
|
||||
var dels = new List<EntityState>();
|
||||
public void Remove(TEntity data) => RemoveRange(new[] { data });
|
||||
public void RemoveRange(IEnumerable<TEntity> data) {
|
||||
if (CanRemove(data, true) == false) return;
|
||||
foreach (var item in data) {
|
||||
var state = CreateEntityState(item);
|
||||
if (_states.ContainsKey(state.Key)) _states.Remove(state.Key);
|
||||
_fsql.ClearEntityPrimaryValueWithIdentityAndGuid(item);
|
||||
|
||||
if (IsNoneDbContext) dels.Add(state);
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Delete, state);
|
||||
}
|
||||
if (IsNoneDbContext) {
|
||||
var affrows = DbContextBetchRemove(dels.ToArray());
|
||||
IncrAffrows(affrows);
|
||||
return affrows;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public void Remove(TEntity data) => RemoveAffrows(data);
|
||||
public void RemoveRange(IEnumerable<TEntity> data) => RemoveRangeAffrows(data);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql {
|
||||
internal class RepositoryDbContext<TEntity> : DbContext where TEntity : class {
|
||||
|
||||
protected BaseRepository<TEntity> _repos;
|
||||
public RepositoryDbContext(IFreeSql orm, BaseRepository<TEntity> repos) : base() {
|
||||
_orm = orm;
|
||||
_repos = repos;
|
||||
_isUseUnitOfWork = false;
|
||||
}
|
||||
|
||||
public override object Set(Type entityType) {
|
||||
if (_dicSet.ContainsKey(entityType)) return _dicSet[entityType];
|
||||
var sd = Activator.CreateInstance(typeof(RepositoryDbSet<>).MakeGenericType(entityType), _repos);
|
||||
_dicSet.Add(entityType, sd);
|
||||
return sd;
|
||||
}
|
||||
|
||||
RepositoryDbSet<TEntity> _dbSet;
|
||||
public RepositoryDbSet<TEntity> DbSet => _dbSet ?? (_dbSet = Set<TEntity>() as RepositoryDbSet<TEntity>);
|
||||
}
|
||||
}
|
@ -9,8 +9,9 @@ namespace FreeSql {
|
||||
|
||||
protected BaseRepository<TEntity> _repos;
|
||||
public RepositoryDbSet(BaseRepository<TEntity> repos) {
|
||||
_ctx = repos._db;
|
||||
_fsql = repos._fsql;
|
||||
_uow = repos._uow;
|
||||
_uow = repos.UnitOfWork;
|
||||
_repos = repos;
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql {
|
||||
|
||||
public interface IRepositoryUnitOfWork : IUnitOfWork {
|
||||
/// <summary>
|
||||
/// 在工作单元内创建默认仓库类,工作单元下的仓储操作具有事务特点
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <param name="filter">数据过滤 + 验证</param>
|
||||
/// <returns></returns>
|
||||
DefaultRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class;
|
||||
|
||||
/// <summary>
|
||||
/// 在工作单元内创建仓库类,工作单元下的仓储操作具有事务特点
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <param name="filter">数据过滤 + 验证</param>
|
||||
/// <param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
|
||||
/// <returns></returns>
|
||||
GuidRepository<TEntity> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class;
|
||||
}
|
||||
|
||||
class RepositoryUnitOfWork : UnitOfWork, IRepositoryUnitOfWork {
|
||||
|
||||
public RepositoryUnitOfWork(IFreeSql fsql) : base(fsql) {
|
||||
}
|
||||
|
||||
public GuidRepository<TEntity> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class {
|
||||
var repos = new GuidRepository<TEntity>(_fsql, filter, asTable);
|
||||
repos.UnitOfWork = this;
|
||||
return repos;
|
||||
}
|
||||
|
||||
public DefaultRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class {
|
||||
var repos = new DefaultRepository<TEntity, TKey>(_fsql, filter);
|
||||
repos.UnitOfWork = this;
|
||||
return repos;
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ public static class FreeSqlRepositoryExtenssions {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回仓库类,适用 Insert 方法无须返回插入的数据
|
||||
/// 返回仓库类
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <param name="that"></param>
|
||||
|
@ -11,9 +11,7 @@ namespace FreeSql {
|
||||
where TEntity : class {
|
||||
|
||||
internal IFreeSql _fsql;
|
||||
internal UnitOfWork _uow;
|
||||
RepositoryDbSet<TEntity> _setPriv;
|
||||
internal RepositoryDbSet<TEntity> _set => _setPriv ?? (_setPriv = new RepositoryDbSet<TEntity>(this));
|
||||
internal RepositoryDbContext<TEntity> _db;
|
||||
public IDataFilter<TEntity> DataFilter { get; } = new DataFilter<TEntity>();
|
||||
Func<string, string> _asTableVal;
|
||||
protected Func<string, string> AsTable {
|
||||
@ -32,45 +30,89 @@ namespace FreeSql {
|
||||
DataFilterUtil.SetRepositoryDataFilter(this, null);
|
||||
DataFilter.Apply("", filter);
|
||||
AsTable = asTable;
|
||||
_db = new RepositoryDbContext<TEntity>(_fsql, this);
|
||||
}
|
||||
|
||||
public Type EntityType => _set._entityTypeInternal;
|
||||
public IUpdate<TEntity> UpdateDiy => _set.OrmUpdateInternal(null);
|
||||
~BaseRepository() {
|
||||
this.Dispose();
|
||||
}
|
||||
bool _isdisposed = false;
|
||||
public void Dispose() {
|
||||
if (_isdisposed) return;
|
||||
try {
|
||||
_db.Dispose();
|
||||
this.DataFilter.Dispose();
|
||||
} finally {
|
||||
_isdisposed = true;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public IUnitOfWork UnitOfWork { get; set; }
|
||||
public Type EntityType => _db.DbSet._entityTypeInternal;
|
||||
public IUpdate<TEntity> UpdateDiy => _db.DbSet.OrmUpdateInternal(null);
|
||||
|
||||
public ISelect<TEntity> Select => _set.OrmSelectInternal(null);
|
||||
public ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => _set.OrmSelectInternal(null).Where(exp);
|
||||
public ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => _set.OrmSelectInternal(null).WhereIf(condition, exp);
|
||||
public ISelect<TEntity> Select => _db.DbSet.OrmSelectInternal(null);
|
||||
public ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => _db.DbSet.OrmSelectInternal(null).Where(exp);
|
||||
public ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => _db.DbSet.OrmSelectInternal(null).WhereIf(condition, exp);
|
||||
|
||||
public int Delete(Expression<Func<TEntity, bool>> predicate) => _set.OrmDeleteInternal(null).Where(predicate).ExecuteAffrows();
|
||||
public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate) => _set.OrmDeleteInternal(null).Where(predicate).ExecuteAffrowsAsync();
|
||||
public int Delete(Expression<Func<TEntity, bool>> predicate) => _db.DbSet.OrmDeleteInternal(null).Where(predicate).ExecuteAffrows();
|
||||
public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate) => _db.DbSet.OrmDeleteInternal(null).Where(predicate).ExecuteAffrowsAsync();
|
||||
|
||||
public int Delete(TEntity entity) => _set.RemoveAffrows(entity);
|
||||
public Task<int> DeleteAsync(TEntity entity) => _set.RemoveAffrowsAsync(entity);
|
||||
public int Delete(IEnumerable<TEntity> entitys) => _set.RemoveRangeAffrows(entitys);
|
||||
public Task<int> DeleteAsync(IEnumerable<TEntity> entitys) => _set.RemoveRangeAffrowsAsync(entitys);
|
||||
public int Delete(TEntity entity) {
|
||||
_db.DbSet.Remove(entity);
|
||||
return _db.SaveChanges();
|
||||
}
|
||||
public Task<int> DeleteAsync(TEntity entity) {
|
||||
_db.DbSet.Remove(entity);
|
||||
return _db.SaveChangesAsync();
|
||||
}
|
||||
public int Delete(IEnumerable<TEntity> entitys) {
|
||||
_db.DbSet.RemoveRange(entitys);
|
||||
return _db.SaveChanges();
|
||||
}
|
||||
public Task<int> DeleteAsync(IEnumerable<TEntity> entitys) {
|
||||
_db.DbSet.RemoveRange(entitys);
|
||||
return _db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public virtual TEntity Insert(TEntity entity) {
|
||||
_set.Add(entity);
|
||||
_db.DbSet.Add(entity);
|
||||
_db.SaveChanges();
|
||||
return entity;
|
||||
}
|
||||
async public virtual Task<TEntity> InsertAsync(TEntity entity) {
|
||||
await _db.DbSet.AddAsync(entity);
|
||||
_db.SaveChanges();
|
||||
return entity;
|
||||
}
|
||||
public virtual List<TEntity> Insert(IEnumerable<TEntity> entitys) {
|
||||
_set.AddRange(entitys);
|
||||
_db.DbSet.AddRange(entitys);
|
||||
_db.SaveChanges();
|
||||
return entitys.ToList();
|
||||
}
|
||||
async public virtual Task<TEntity> InsertAsync(TEntity entity) {
|
||||
await _set.AddAsync(entity);
|
||||
return entity;
|
||||
}
|
||||
async public virtual Task<List<TEntity>> InsertAsync(IEnumerable<TEntity> entitys) {
|
||||
await _set.AddRangeAsync(entitys);
|
||||
await _db.DbSet.AddRangeAsync(entitys);
|
||||
await _db.SaveChangesAsync();
|
||||
return entitys.ToList();
|
||||
}
|
||||
|
||||
public int Update(TEntity entity) => _set.UpdateAffrows(entity);
|
||||
public Task<int> UpdateAsync(TEntity entity) => _set.UpdateAffrowsAsync(entity);
|
||||
public int Update(IEnumerable<TEntity> entitys) => _set.UpdateRangeAffrows(entitys);
|
||||
public Task<int> UpdateAsync(IEnumerable<TEntity> entitys) => _set.UpdateRangeAffrowsAsync(entitys);
|
||||
public int Update(TEntity entity) {
|
||||
_db.DbSet.Update(entity);
|
||||
return _db.SaveChanges();
|
||||
}
|
||||
public Task<int> UpdateAsync(TEntity entity) {
|
||||
_db.DbSet.Update(entity);
|
||||
return _db.SaveChangesAsync();
|
||||
}
|
||||
public int Update(IEnumerable<TEntity> entitys) {
|
||||
_db.DbSet.UpdateRange(entitys);
|
||||
return _db.SaveChanges();
|
||||
}
|
||||
public Task<int> UpdateAsync(IEnumerable<TEntity> entitys) {
|
||||
_db.DbSet.UpdateRange(entitys);
|
||||
return _db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class BaseRepository<TEntity, TKey> : BaseRepository<TEntity>, IRepository<TEntity, TKey>
|
||||
@ -81,17 +123,19 @@ namespace FreeSql {
|
||||
|
||||
public int Delete(TKey id) {
|
||||
var stateKey = string.Concat(id);
|
||||
if (_set._statesInternal.ContainsKey(stateKey)) _set._statesInternal.Remove(stateKey);
|
||||
return _set.OrmDeleteInternal(id).ExecuteAffrows();
|
||||
if (_db.DbSet._statesInternal.ContainsKey(stateKey))
|
||||
_db.DbSet._statesInternal.Remove(stateKey);
|
||||
return _db.DbSet.OrmDeleteInternal(id).ExecuteAffrows();
|
||||
}
|
||||
public Task<int> DeleteAsync(TKey id) {
|
||||
var stateKey = string.Concat(id);
|
||||
if (_set._statesInternal.ContainsKey(stateKey)) _set._statesInternal.Remove(stateKey);
|
||||
return _set.OrmDeleteInternal(id).ExecuteAffrowsAsync();
|
||||
if (_db.DbSet._statesInternal.ContainsKey(stateKey))
|
||||
_db.DbSet._statesInternal.Remove(stateKey);
|
||||
return _db.DbSet.OrmDeleteInternal(id).ExecuteAffrowsAsync();
|
||||
}
|
||||
|
||||
public TEntity Find(TKey id) => _set.OrmSelectInternal(id).ToOne();
|
||||
public Task<TEntity> FindAsync(TKey id) => _set.OrmSelectInternal(id).ToOneAsync();
|
||||
public TEntity Find(TKey id) => _db.DbSet.OrmSelectInternal(id).ToOne();
|
||||
public Task<TEntity> FindAsync(TKey id) => _db.DbSet.OrmSelectInternal(id).ToOneAsync();
|
||||
|
||||
public TEntity Get(TKey id) => Find(id);
|
||||
public Task<TEntity> GetAsync(TKey id) => FindAsync(id);
|
||||
|
@ -4,8 +4,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace FreeSql {
|
||||
|
||||
public interface IRepository {
|
||||
public interface IRepository : IDisposable {
|
||||
Type EntityType { get; }
|
||||
IUnitOfWork UnitOfWork { get; set; }
|
||||
}
|
||||
|
||||
public interface IRepository<TEntity> : IReadOnlyRepository<TEntity>, IBasicRepository<TEntity>
|
||||
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql {
|
||||
class RepositoryUnitOfWork : UnitOfWork, IRepositoryUnitOfWork {
|
||||
|
||||
public RepositoryUnitOfWork(IFreeSql fsql) : base(fsql) {
|
||||
}
|
||||
|
||||
public GuidRepository<TEntity> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class {
|
||||
var repos = new GuidRepository<TEntity>(_fsql, filter, asTable);
|
||||
repos._uow = this;
|
||||
return repos;
|
||||
}
|
||||
|
||||
public DefaultRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class {
|
||||
var repos = new DefaultRepository<TEntity, TKey>(_fsql, filter);
|
||||
repos._uow = this;
|
||||
return repos;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql {
|
||||
public interface IUnitOfWork : IDisposable {
|
||||
|
||||
DbTransaction GetOrBeginTransaction(bool isCreate = true);
|
||||
|
||||
void Commit();
|
||||
|
||||
void Rollback();
|
||||
}
|
||||
|
||||
public interface IRepositoryUnitOfWork : IUnitOfWork {
|
||||
|
||||
/// <summary>
|
||||
/// 在工作单元内创建默认仓库类,工作单元下的仓储操作具有事务特点
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <param name="filter">数据过滤 + 验证</param>
|
||||
/// <returns></returns>
|
||||
DefaultRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class;
|
||||
|
||||
/// <summary>
|
||||
/// 在工作单元内创建仓库类,适用 Insert 方法无须返回插入的数据,工作单元下的仓储操作具有事务特点
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <param name="filter">数据过滤 + 验证</param>
|
||||
/// <param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
|
||||
/// <returns></returns>
|
||||
GuidRepository<TEntity> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class;
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace FreeSql {
|
||||
_tran = null;
|
||||
_conn = null;
|
||||
}
|
||||
internal DbTransaction GetOrBeginTransaction(bool isCreate = true) {
|
||||
public DbTransaction GetOrBeginTransaction(bool isCreate = true) {
|
||||
|
||||
if (_tran != null) return _tran;
|
||||
if (isCreate == false) return null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user