mirror of
https://github.com/nsnail/FreeSql.git
synced 2026-03-22 02:02:05 +08:00
## v0.3.27
- 增加 行级锁功能,适用修改实体; - 增加 FreeSql.Repository 默认依赖注入的方式,同时保留原有 Autofac; - 优化 FreeSql.Repository Insert 逻辑,参考了 FreeSql.DbContext; - 优化 FreeSql.IUpdate 参照 IInsert 对大批量更新,拆分执行; - 修复 FreeSql.IInsert ClearData 重复利用的 bug(使用 IgnoreColumns 进行大批量插入时会发生);
This commit is contained in:
@@ -8,7 +8,7 @@ using System.Text;
|
||||
|
||||
namespace FreeSql {
|
||||
|
||||
internal class Utils {
|
||||
internal class DataFilterUtil {
|
||||
|
||||
internal static Action<FluentDataFilter> _globalDataFilter;
|
||||
|
||||
@@ -20,7 +20,7 @@ public static class FreeSqlRepositoryAutofacExtenssions {
|
||||
|
||||
static void RegisterFreeRepositoryPrivate(ContainerBuilder builder, Action<FluentDataFilter> globalDataFilter, params Assembly[] assemblies) {
|
||||
|
||||
Utils._globalDataFilter = globalDataFilter;
|
||||
DataFilterUtil._globalDataFilter = globalDataFilter;
|
||||
|
||||
builder.RegisterGeneric(typeof(GuidRepository<>)).As(
|
||||
typeof(GuidRepository<>),
|
||||
39
FreeSql.Repository/Extenssions/DependencyInjection.cs
Normal file
39
FreeSql.Repository/Extenssions/DependencyInjection.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using FreeSql;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace FreeSql {
|
||||
public static class FreeSqlRepositoryDependencyInjection {
|
||||
|
||||
public static IServiceCollection AddFreeRepository(this IServiceCollection services, Action<FluentDataFilter> globalDataFilter = null, params Assembly[] assemblies) {
|
||||
|
||||
DataFilterUtil._globalDataFilter = globalDataFilter;
|
||||
|
||||
services.AddScoped(typeof(IReadOnlyRepository<>), typeof(GuidRepository<>));
|
||||
services.AddScoped(typeof(IBasicRepository<>), typeof(GuidRepository<>));
|
||||
services.AddScoped(typeof(BaseRepository<>), typeof(GuidRepository<>));
|
||||
services.AddScoped(typeof(GuidRepository<>));
|
||||
|
||||
services.AddScoped(typeof(IReadOnlyRepository<,>), typeof(DefaultRepository<,>));
|
||||
services.AddScoped(typeof(IBasicRepository<,>), typeof(DefaultRepository<,>));
|
||||
services.AddScoped(typeof(BaseRepository<,>), typeof(DefaultRepository<,>));
|
||||
services.AddScoped(typeof(DefaultRepository<,>));
|
||||
|
||||
if (assemblies?.Any() == true) {
|
||||
foreach(var asse in assemblies) {
|
||||
foreach (var repos in asse.GetTypes().Where(a => a.IsAbstract == false && typeof(IRepository).IsAssignableFrom(a))) {
|
||||
|
||||
services.AddScoped(repos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using System.Linq.Expressions;
|
||||
using System.Linq;
|
||||
using System.Data;
|
||||
|
||||
public static class FreeSqlRepositoryIFreeSqlExtenssions {
|
||||
public static class FreeSqlRepositoryExtenssions {
|
||||
|
||||
/// <summary>
|
||||
/// 返回默认仓库类
|
||||
@@ -15,7 +15,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FreeSql\FreeSql.csproj" />
|
||||
<ProjectReference Include="..\FreeSql\FreeSql.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using FreeSql.Extensions.EntityUtil;
|
||||
using FreeSql.Internal.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
@@ -28,7 +29,7 @@ namespace FreeSql {
|
||||
|
||||
protected BaseRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable = null) : base() {
|
||||
_fsql = fsql ?? throw new NullReferenceException(nameof(fsql));
|
||||
Utils.SetRepositoryDataFilter(this, null);
|
||||
DataFilterUtil.SetRepositoryDataFilter(this, null);
|
||||
DataFilter.Apply("", filter);
|
||||
AsTable = asTable;
|
||||
}
|
||||
@@ -42,52 +43,20 @@ namespace FreeSql {
|
||||
public Task<int> DeleteAsync(TEntity entity) => OrmDelete(entity).ExecuteAffrowsAsync();
|
||||
|
||||
public virtual TEntity Insert(TEntity entity) {
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
return OrmInsert(entity).ExecuteInserted().FirstOrDefault();
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
default:
|
||||
throw new NotImplementedException($"{_fsql.Ado.DataType}不支持类似returning或output类型的特性,请参考FreeSql插入数据的方法重新实现。");
|
||||
}
|
||||
Add(entity);
|
||||
return entity;
|
||||
}
|
||||
public virtual List<TEntity> Insert(IEnumerable<TEntity> entitys) {
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
return OrmInsert(entitys).ExecuteInserted();
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
default:
|
||||
throw new NotImplementedException($"{_fsql.Ado.DataType}不支持类似returning或output类型的特性,请参考FreeSql插入数据的方法重新实现。");
|
||||
}
|
||||
AddRange(entitys);
|
||||
return entitys.ToList();
|
||||
}
|
||||
async public virtual Task<TEntity> InsertAsync(TEntity entity) {
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
return (await OrmInsert(entity).ExecuteInsertedAsync()).FirstOrDefault();
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
default:
|
||||
throw new NotImplementedException($"{_fsql.Ado.DataType}不支持类似returning或output类型的特性,请参考FreeSql插入数据的方法重新实现。");
|
||||
}
|
||||
await AddAsync(entity);
|
||||
return entity;
|
||||
}
|
||||
public virtual Task<List<TEntity>> InsertAsync(IEnumerable<TEntity> entitys) {
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
return OrmInsert(entitys).ExecuteInsertedAsync();
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
default:
|
||||
throw new NotImplementedException($"{_fsql.Ado.DataType}不支持类似returning或output类型的特性,请参考FreeSql插入数据的方法重新实现。");
|
||||
}
|
||||
async public virtual Task<List<TEntity>> InsertAsync(IEnumerable<TEntity> entitys) {
|
||||
await AddRangeAsync(entitys);
|
||||
return entitys.ToList();
|
||||
}
|
||||
|
||||
public int Update(TEntity entity) => OrmUpdate(entity).ExecuteAffrows();
|
||||
@@ -129,6 +98,178 @@ namespace FreeSql {
|
||||
}
|
||||
|
||||
protected void ApplyDataFilter(string name, Expression<Func<TEntity, bool>> exp) => DataFilter.Apply(name, exp);
|
||||
|
||||
#region 参考 FreeSql.DbContext/dbset
|
||||
|
||||
TableInfo _tablePriv;
|
||||
TableInfo _table => _tablePriv ?? (_tablePriv = _fsql.CodeFirst.GetTableByEntity(EntityType));
|
||||
ColumnInfo[] _tableIdentitysPriv;
|
||||
ColumnInfo[] _tableIdentitys => _tableIdentitysPriv ?? (_tableIdentitysPriv = _table.Primarys.Where(a => a.Attribute.IsIdentity).ToArray());
|
||||
|
||||
bool CanAdd(TEntity[] data, bool isThrow) {
|
||||
if (data == null) {
|
||||
if (isThrow) throw new ArgumentNullException(nameof(data));
|
||||
return false;
|
||||
}
|
||||
foreach (var s in data) if (CanAdd(s, isThrow) == false) return false;
|
||||
return true;
|
||||
}
|
||||
bool CanAdd(IEnumerable<TEntity> data, bool isThrow) {
|
||||
if (data == null) {
|
||||
if (isThrow) throw new ArgumentNullException(nameof(data));
|
||||
return false;
|
||||
}
|
||||
foreach (var s in data) if (CanAdd(s, isThrow) == false) return false;
|
||||
return true;
|
||||
}
|
||||
bool CanAdd(TEntity data, bool isThrow) {
|
||||
if (data == null) {
|
||||
if (isThrow) throw new ArgumentNullException(nameof(data));
|
||||
return false;
|
||||
}
|
||||
var key = _fsql.GetEntityKeyString(data);
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
return true;
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1) {
|
||||
return true;
|
||||
}
|
||||
if (isThrow) throw new Exception($"不可添加,未设置主键的值:{_fsql.GetEntityString(data)}");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
var idval = _fsql.GetEntityIdentityValueWithPrimary(data);
|
||||
if (idval > 0) {
|
||||
if (isThrow) throw new Exception($"不可添加,自增属性有值:{_fsql.GetEntityString(data)}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddPriv(TEntity data, bool isCheck) {
|
||||
if (isCheck && CanAdd(data, true) == false) return;
|
||||
if (_tableIdentitys.Length > 0) {
|
||||
//有自增,马上执行
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1) {
|
||||
var idtval = this.OrmInsert(data).ExecuteIdentity();
|
||||
_fsql.SetEntityIdentityValueWithPrimary(data, idtval);
|
||||
} else {
|
||||
var newval = this.OrmInsert(data).ExecuteInserted().First();
|
||||
_fsql.MapEntityValue(newval, data);
|
||||
}
|
||||
return;
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1) {
|
||||
var idtval = this.OrmInsert(data).ExecuteIdentity();
|
||||
_fsql.SetEntityIdentityValueWithPrimary(data, idtval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.OrmInsert(data).ExecuteAffrows();
|
||||
}
|
||||
}
|
||||
public void Add(TEntity source) => AddPriv(source, true);
|
||||
public void AddRange(TEntity[] data) => AddRange(data.ToList());
|
||||
public void AddRange(IEnumerable<TEntity> data) {
|
||||
if (CanAdd(data, true) == false) return;
|
||||
if (data.ElementAtOrDefault(1) == default(TEntity)) {
|
||||
Add(data.First());
|
||||
return;
|
||||
}
|
||||
if (_tableIdentitys.Length > 0) {
|
||||
//有自增,马上执行
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
var rets = this.OrmInsert(data).ExecuteInserted();
|
||||
if (rets.Count != data.Count()) throw new Exception($"特别错误:批量添加失败,{_fsql.Ado.DataType} 的返回数据,与添加的数目不匹配");
|
||||
var idx = 0;
|
||||
foreach (var s in data)
|
||||
_fsql.MapEntityValue(rets[idx++], s);
|
||||
return;
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
foreach (var s in data)
|
||||
AddPriv(s, false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.OrmInsert(data).ExecuteAffrows();
|
||||
}
|
||||
}
|
||||
|
||||
async Task AddPrivAsync(TEntity data, bool isCheck) {
|
||||
if (isCheck && CanAdd(data, true) == false) return;
|
||||
if (_tableIdentitys.Length > 0) {
|
||||
//有自增,马上执行
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1) {
|
||||
var idtval = await this.OrmInsert(data).ExecuteIdentityAsync();
|
||||
_fsql.SetEntityIdentityValueWithPrimary(data, idtval);
|
||||
} else {
|
||||
var newval = (await this.OrmInsert(data).ExecuteInsertedAsync()).First();
|
||||
_fsql.MapEntityValue(newval, data);
|
||||
}
|
||||
return;
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1) {
|
||||
var idtval = await this.OrmInsert(data).ExecuteIdentityAsync();
|
||||
_fsql.SetEntityIdentityValueWithPrimary(data, idtval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
await this.OrmInsert(data).ExecuteAffrowsAsync();
|
||||
}
|
||||
}
|
||||
public Task AddAsync(TEntity source) => AddPrivAsync(source, true);
|
||||
public Task AddRangeAsync(TEntity[] data) => AddRangeAsync(data.ToList());
|
||||
async public Task AddRangeAsync(IEnumerable<TEntity> data) {
|
||||
if (CanAdd(data, true) == false) return;
|
||||
if (data.ElementAtOrDefault(1) == default(TEntity)) {
|
||||
Add(data.First());
|
||||
return;
|
||||
}
|
||||
if (_tableIdentitys.Length > 0) {
|
||||
//有自增,马上执行
|
||||
switch (_fsql.Ado.DataType) {
|
||||
case DataType.SqlServer:
|
||||
case DataType.PostgreSQL:
|
||||
var rets = await this.OrmInsert(data).ExecuteInsertedAsync();
|
||||
if (rets.Count != data.Count()) throw new Exception($"特别错误:批量添加失败,{_fsql.Ado.DataType} 的返回数据,与添加的数目不匹配");
|
||||
var idx = 0;
|
||||
foreach (var s in data)
|
||||
_fsql.MapEntityValue(rets[idx++], s);
|
||||
return;
|
||||
case DataType.MySql:
|
||||
case DataType.Oracle:
|
||||
case DataType.Sqlite:
|
||||
foreach (var s in data)
|
||||
await AddPrivAsync(s, false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
await this.OrmInsert(data).ExecuteAffrowsAsync();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public abstract class BaseRepository<TEntity, TKey> : BaseRepository<TEntity>, IRepository<TEntity, TKey>
|
||||
|
||||
Reference in New Issue
Block a user