diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs index 1015bd55..213fb038 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs @@ -7,65 +7,129 @@ using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; -/// -/// 包括 CreateTime/UpdateTime/IsDeleted 的实体基类 -/// -[Table(DisableSyncStructure = true)] -public abstract class BaseEntity +namespace FreeSql { - static IFreeSql _ormPriv; /// - /// 全局 IFreeSql orm 对象 + /// 包括 CreateTime/UpdateTime/IsDeleted、CRUD 方法、以及 ID 主键定义 的实体基类 + /// + /// 当 TKey 为 int/long 时,Id 主键被设为自增值主键 /// - public static IFreeSql Orm => _ormPriv ?? throw new Exception(@"使用前请初始化 BaseEntity.Initialization(new FreeSqlBuilder() -.UseAutoSyncStructure(true) -.UseConnectionString(DataType.Sqlite, ""data source=test.db;max pool size=5"") -.Build());"); - - /// - /// 初始化BaseEntity - /// BaseEntity.Initialization(new FreeSqlBuilder() - /// - /// .UseAutoSyncStructure(true) - /// - /// .UseConnectionString(DataType.Sqlite, "data source=test.db;max pool size=5") - /// - /// .Build()); - /// - /// IFreeSql orm 对象 - public static void Initialization(IFreeSql fsql) + /// + /// + [Table(DisableSyncStructure = true)] + public abstract class BaseEntity : BaseEntity where TEntity : class { - _ormPriv = fsql; - _ormPriv.Aop.CurdBefore += (s, e) => Trace.WriteLine(e.Sql + "\r\n"); + static BaseEntity() + { + var tkeyType = typeof(TKey)?.NullableTypeOrThis(); + if (tkeyType == typeof(int) || tkeyType == typeof(long)) + Orm.CodeFirst.ConfigEntity(typeof(TEntity), + t => t.Property("Id").IsIdentity(true)); + } + + /// + /// 主键 + /// + public virtual TKey Id { get; set; } + + /// + /// 根据主键值获取数据 + /// + /// + /// + async public static Task FindAsync(TKey id) + { + var item = await Select.WhereDynamic(id).FirstAsync(); + (item as BaseEntity)?.Attach(); + return item; + } + + /// + /// 根据主键值获取数据 + /// + /// + /// + public static TEntity Find(TKey id) + { + var item = Select.WhereDynamic(id).First(); + (item as BaseEntity)?.Attach(); + return item; + } } /// - /// 创建时间 + /// 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步和同步方法的实体基类 /// - public DateTime CreateTime { get; set; } - /// - /// 更新时间 - /// - public DateTime UpdateTime { get; set; } - /// - /// 逻辑删除 - /// - public bool IsDeleted { get; set; } - - /// - /// 开启工作单元事务 - /// - /// - public static IUnitOfWork Begin() => Begin(null); - /// - /// 开启工作单元事务 - /// - /// 事务等级 - /// - public static IUnitOfWork Begin(IsolationLevel? level) + /// + [Table(DisableSyncStructure = true)] + public abstract class BaseEntity : BaseEntityAsync where TEntity : class { - var uow = Orm.CreateUnitOfWork(); - uow.IsolationLevel = level; - return uow; + bool UpdateIsDeleted(bool value) + { + if (this.Repository == null) + return Orm.Update(this as TEntity) + .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) + .Set(a => (a as BaseEntity).IsDeleted, this.IsDeleted = value).ExecuteAffrows() == 1; + + this.SetTenantId(); + this.IsDeleted = value; + this.Repository.UnitOfWork = UnitOfWork.Current.Value; + return this.Repository.Update(this as TEntity) == 1; + } + /// + /// 删除数据 + /// + /// + public virtual bool Delete() => this.UpdateIsDeleted(true); + /// + /// 恢复删除的数据 + /// + /// + public virtual bool Restore() => this.UpdateIsDeleted(false); + + /// + /// 更新数据 + /// + /// + public virtual bool Update() + { + this.UpdateTime = DateTime.Now; + if (this.Repository == null) + return Orm.Update() + .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) + .SetSource(this as TEntity).ExecuteAffrows() == 1; + + this.SetTenantId(); + this.Repository.UnitOfWork = UnitOfWork.Current.Value; + return this.Repository.Update(this as TEntity) == 1; + } + /// + /// 插入数据 + /// + public virtual TEntity Insert() + { + this.CreateTime = DateTime.Now; + if (this.Repository == null) + this.Repository = Orm.GetRepository(); + + this.SetTenantId(); + this.Repository.UnitOfWork = UnitOfWork.Current.Value; + return this.Repository.Insert(this as TEntity); + } + + /// + /// 更新或插入 + /// + /// + public virtual TEntity Save() + { + this.UpdateTime = DateTime.Now; + if (this.Repository == null) + this.Repository = Orm.GetRepository(); + + this.SetTenantId(); + this.Repository.UnitOfWork = UnitOfWork.Current.Value; + return this.Repository.InsertOrUpdate(this as TEntity); + } } -} +} \ No newline at end of file diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs index 8d5f2399..4b98dca2 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs @@ -1,121 +1,118 @@ using FreeSql; using FreeSql.DataAnnotations; using System; -using System.Data; -using System.Diagnostics; -using System.Linq.Expressions; -using System.Threading; using System.Threading.Tasks; -/// -/// 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步方法的实体基类 -/// -/// -[Table(DisableSyncStructure = true)] -public abstract class BaseEntityAsync : BaseEntity where TEntity : class +namespace FreeSql { /// - /// 查询数据 + /// 包括 CreateTime/UpdateTime/IsDeleted、CRUD 异步方法、以及 ID 主键定义 的实体基类 + /// + /// 当 TKey 为 int/long 时,Id 主键被设为自增值主键 /// - /// - public static ISelect Select => Orm.Select() - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction(false)) - .WhereCascade(a => (a as BaseEntity).IsDeleted == false); - /// - /// 查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com") - /// - /// lambda表达式 - /// - public static ISelect Where(Expression> exp) => Select.Where(exp); - /// - /// 查询条件,Where(true, a => a.Id > 10),支导航对象查询,Where(true, a => a.Author.Email == "2881099@qq.com") - /// - /// true 时生效 - /// lambda表达式 - /// - public static ISelect WhereIf(bool condition, Expression> exp) => Select.WhereIf(condition, exp); - - /// - /// 仓储对象 - /// - protected IBaseRepository Repository { get; set; } - - /// - /// 附加实体,在更新数据时,只更新变化的部分 - /// - public TEntity Attach() + /// + /// + [Table(DisableSyncStructure = true)] + public abstract class BaseEntityAsync : BaseEntityAsync where TEntity : class { - if (this.Repository == null) - this.Repository = Orm.GetRepository(); + static BaseEntityAsync() + { + var tkeyType = typeof(TKey)?.NullableTypeOrThis(); + if (tkeyType == typeof(int) || tkeyType == typeof(long)) + Orm.CodeFirst.ConfigEntity(typeof(TEntity), + t => t.Property("Id").IsIdentity(true)); + } - var item = this as TEntity; - this.Repository.Attach(item); - return item; - } + /// + /// 主键 + /// + public virtual TKey Id { get; set; } - /** async **/ - - async Task UpdateIsDeletedAsync(bool value) - { - if (this.Repository == null) - return await Orm.Update(this as TEntity) - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) - .Set(a => (a as BaseEntity).IsDeleted, this.IsDeleted = value).ExecuteAffrowsAsync() == 1; - - this.IsDeleted = value; - this.Repository.UnitOfWork = UnitOfWork.Current.Value; - return await this.Repository.UpdateAsync(this as TEntity) == 1; - } - /// - /// 删除数据 - /// - /// - public virtual Task DeleteAsync() => this.UpdateIsDeletedAsync(true); - /// - /// 恢复删除的数据 - /// - /// - public virtual Task RestoreAsync() => this.UpdateIsDeletedAsync(false); - - /// - /// 更新数据 - /// - /// - async public virtual Task UpdateAsync() - { - this.UpdateTime = DateTime.Now; - if (this.Repository == null) - return await Orm.Update() - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) - .SetSource(this as TEntity).ExecuteAffrowsAsync() == 1; - - this.Repository.UnitOfWork = UnitOfWork.Current.Value; - return await this.Repository.UpdateAsync(this as TEntity) == 1; - } - /// - /// 插入数据 - /// - public virtual Task InsertAsync() - { - this.CreateTime = DateTime.Now; - if (this.Repository == null) - this.Repository = Orm.GetRepository(); - - this.Repository.UnitOfWork = UnitOfWork.Current.Value; - return this.Repository.InsertAsync(this as TEntity); + /// + /// 根据主键值获取数据 + /// + /// + /// + async public static Task FindAsync(TKey id) + { + var item = await Select.WhereDynamic(id).FirstAsync(); + (item as BaseEntity)?.Attach(); + return item; + } } /// - /// 更新或插入 + /// 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步方法的实体基类 /// - /// - public virtual Task SaveAsync() + /// + [Table(DisableSyncStructure = true)] + public abstract class BaseEntityAsync : BaseEntityReadOnly where TEntity : class { - this.UpdateTime = DateTime.Now; - if (this.Repository == null) - this.Repository = Orm.GetRepository(); + async Task UpdateIsDeletedAsync(bool value) + { + if (this.Repository == null) + return await Orm.Update(this as TEntity) + .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) + .Set(a => (a as BaseEntity).IsDeleted, this.IsDeleted = value).ExecuteAffrowsAsync() == 1; - this.Repository.UnitOfWork = UnitOfWork.Current.Value; - return this.Repository.InsertOrUpdateAsync(this as TEntity); + this.IsDeleted = value; + this.Repository.UnitOfWork = UnitOfWork.Current.Value; + return await this.Repository.UpdateAsync(this as TEntity) == 1; + } + /// + /// 删除数据 + /// + /// + public virtual Task DeleteAsync() => this.UpdateIsDeletedAsync(true); + /// + /// 恢复删除的数据 + /// + /// + public virtual Task RestoreAsync() => this.UpdateIsDeletedAsync(false); + + /// + /// 更新数据 + /// + /// + async public virtual Task UpdateAsync() + { + this.UpdateTime = DateTime.Now; + if (this.Repository == null) + return await Orm.Update() + .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) + .SetSource(this as TEntity).ExecuteAffrowsAsync() == 1; + + this.SetTenantId(); + this.Repository.UnitOfWork = UnitOfWork.Current.Value; + return await this.Repository.UpdateAsync(this as TEntity) == 1; + } + /// + /// 插入数据 + /// + public virtual Task InsertAsync() + { + this.CreateTime = DateTime.Now; + if (this.Repository == null) + this.Repository = Orm.GetRepository(); + + this.SetTenantId(); + this.Repository.UnitOfWork = UnitOfWork.Current.Value; + return this.Repository.InsertAsync(this as TEntity); + } + + /// + /// 更新或插入 + /// + /// + public virtual Task SaveAsync() + { + this.UpdateTime = DateTime.Now; + if (this.Repository == null) + this.Repository = Orm.GetRepository(); + + this.SetTenantId(); + this.Repository.UnitOfWork = UnitOfWork.Current.Value; + return this.Repository.InsertOrUpdateAsync(this as TEntity); + } } -} +} \ No newline at end of file diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsyncTKey.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsyncTKey.cs deleted file mode 100644 index cb1b8b3e..00000000 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsyncTKey.cs +++ /dev/null @@ -1,44 +0,0 @@ -using FreeSql; -using FreeSql.DataAnnotations; -using System; -using System.Data; -using System.Diagnostics; -using System.Linq.Expressions; -using System.Threading; -using System.Threading.Tasks; - -/// -/// 包括 CreateTime/UpdateTime/IsDeleted、CRUD 异步方法、以及 ID 主键定义 的实体基类 -/// -/// 当 TKey 为 int/long 时,Id 主键被设为自增值主键 -/// -/// -/// -[Table(DisableSyncStructure = true)] -public abstract class BaseEntityAsync : BaseEntityAsync where TEntity : class -{ - static BaseEntityAsync() - { - var tkeyType = typeof(TKey)?.NullableTypeOrThis(); - if (tkeyType == typeof(int) || tkeyType == typeof(long)) - Orm.CodeFirst.ConfigEntity(typeof(TEntity), - t => t.Property("Id").IsIdentity(true)); - } - - /// - /// 主键 - /// - public virtual TKey Id { get; set; } - - /// - /// 根据主键值获取数据 - /// - /// - /// - async public static Task FindAsync(TKey id) - { - var item = await Select.WhereDynamic(id).FirstAsync(); - (item as BaseEntity)?.Attach(); - return item; - } -} diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs new file mode 100644 index 00000000..21d35c1f --- /dev/null +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs @@ -0,0 +1,160 @@ +using FreeSql.DataAnnotations; +using System; +using System.Data; +using System.Diagnostics; +using System.Linq.Expressions; +using System.Threading; + +namespace FreeSql +{ + /// + /// 包括 CreateTime/UpdateTime/IsDeleted 的实体基类 + /// + [Table(DisableSyncStructure = true)] + public abstract class BaseEntity + { + static IFreeSql _ormPriv; + /// + /// 全局 IFreeSql orm 对象 + /// + public static IFreeSql Orm => _ormPriv ?? throw new Exception(@"使用前请初始化 BaseEntity.Initialization(new FreeSqlBuilder() +.UseAutoSyncStructure(true) +.UseConnectionString(DataType.Sqlite, ""data source=test.db;max pool size=5"") +.Build());"); + + /// + /// 初始化BaseEntity + /// BaseEntity.Initialization(new FreeSqlBuilder() + /// + /// .UseAutoSyncStructure(true) + /// + /// .UseConnectionString(DataType.Sqlite, "data source=test.db;max pool size=5") + /// + /// .Build()); + /// + /// IFreeSql orm 对象 + public static void Initialization(IFreeSql fsql) + { + _ormPriv = fsql; + _ormPriv.Aop.CurdBefore += (s, e) => Trace.WriteLine(e.Sql + "\r\n"); + } + + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + /// + /// 更新时间 + /// + public DateTime UpdateTime { get; set; } + /// + /// 逻辑删除 + /// + public bool IsDeleted { get; set; } + /// + /// 排序 + /// + public int Sort { get; set; } + + /// + /// 开启工作单元事务 + /// + /// + public static IUnitOfWork Begin() => Begin(null); + /// + /// 开启工作单元事务 + /// + /// 事务等级 + /// + public static IUnitOfWork Begin(IsolationLevel? level) + { + var uow = Orm.CreateUnitOfWork(); + uow.IsolationLevel = level; + return uow; + } + + static readonly AsyncLocal _AsyncTenantId = new AsyncLocal(); + /// + /// 获取或设置当前租户id + /// + public static string CurrentTenantId + { + get => _AsyncTenantId.Value; + set => _AsyncTenantId.Value = value; + } + } + + /// + /// 租户 + /// + public interface ITenant + { + /// + /// 租户id + /// + string TenantId { get; set; } + } + + public abstract class BaseEntityReadOnly : BaseEntity where TEntity : class + { + /// + /// 查询数据 + /// + /// + public static ISelect Select + { + get + { + var select = Orm.Select().WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction(false)); + if (string.IsNullOrEmpty(CurrentTenantId) == false) + select.WhereCascade(a => (a as ITenant).TenantId == CurrentTenantId); + return select.WhereCascade(a => (a as BaseEntity).IsDeleted == false); + } + } + /// + /// 设置当前租户id + /// + protected void SetTenantId() + { + if (string.IsNullOrEmpty(CurrentTenantId) == false) + { + var ten = this as ITenant; + if (ten != null) + ten.TenantId = CurrentTenantId; + } + } + + /// + /// 查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com") + /// + /// lambda表达式 + /// + public static ISelect Where(Expression> exp) => Select.Where(exp); + /// + /// 查询条件,Where(true, a => a.Id > 10),支导航对象查询,Where(true, a => a.Author.Email == "2881099@qq.com") + /// + /// true 时生效 + /// lambda表达式 + /// + public static ISelect WhereIf(bool condition, Expression> exp) => Select.WhereIf(condition, exp); + + /// + /// 仓储对象 + /// + protected IBaseRepository Repository { get; set; } + + /// + /// 附加实体,在更新数据时,只更新变化的部分 + /// + public TEntity Attach() + { + if (this.Repository == null) + this.Repository = Orm.GetRepository(); + + var item = this as TEntity; + this.SetTenantId(); + this.Repository.Attach(item); + return item; + } + } +} \ No newline at end of file diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntitySync.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntitySync.cs deleted file mode 100644 index eab376b7..00000000 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntitySync.cs +++ /dev/null @@ -1,80 +0,0 @@ -using FreeSql; -using FreeSql.DataAnnotations; -using System; -using System.Data; -using System.Diagnostics; -using System.Linq.Expressions; -using System.Threading; -using System.Threading.Tasks; - -/// -/// 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步和同步方法的实体基类 -/// -/// -[Table(DisableSyncStructure = true)] -public abstract class BaseEntity : BaseEntityAsync where TEntity : class -{ - bool UpdateIsDeleted(bool value) - { - if (this.Repository == null) - return Orm.Update(this as TEntity) - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) - .Set(a => (a as BaseEntity).IsDeleted, this.IsDeleted = value).ExecuteAffrows() == 1; - - this.IsDeleted = value; - this.Repository.UnitOfWork = UnitOfWork.Current.Value; - return this.Repository.Update(this as TEntity) == 1; - } - /// - /// 删除数据 - /// - /// - public virtual bool Delete() => this.UpdateIsDeleted(true); - /// - /// 恢复删除的数据 - /// - /// - public virtual bool Restore() => this.UpdateIsDeleted(false); - - /// - /// 更新数据 - /// - /// - public virtual bool Update() - { - this.UpdateTime = DateTime.Now; - if (this.Repository == null) - return Orm.Update() - .WithTransaction(UnitOfWork.Current.Value?.GetOrBeginTransaction()) - .SetSource(this as TEntity).ExecuteAffrows() == 1; - - this.Repository.UnitOfWork = UnitOfWork.Current.Value; - return this.Repository.Update(this as TEntity) == 1; - } - /// - /// 插入数据 - /// - public virtual TEntity Insert() - { - this.CreateTime = DateTime.Now; - if (this.Repository == null) - this.Repository = Orm.GetRepository(); - - this.Repository.UnitOfWork = UnitOfWork.Current.Value; - return this.Repository.Insert(this as TEntity); - } - - /// - /// 更新或插入 - /// - /// - public virtual TEntity Save() - { - this.UpdateTime = DateTime.Now; - if (this.Repository == null) - this.Repository = Orm.GetRepository(); - - this.Repository.UnitOfWork = UnitOfWork.Current.Value; - return this.Repository.InsertOrUpdate(this as TEntity); - } -} diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntitySyncTKey.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntitySyncTKey.cs deleted file mode 100644 index 359e155a..00000000 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntitySyncTKey.cs +++ /dev/null @@ -1,56 +0,0 @@ -using FreeSql; -using FreeSql.DataAnnotations; -using System; -using System.Data; -using System.Diagnostics; -using System.Linq.Expressions; -using System.Threading; -using System.Threading.Tasks; - -/// -/// 包括 CreateTime/UpdateTime/IsDeleted、CRUD 方法、以及 ID 主键定义 的实体基类 -/// -/// 当 TKey 为 int/long 时,Id 主键被设为自增值主键 -/// -/// -/// -[Table(DisableSyncStructure = true)] -public abstract class BaseEntity : BaseEntity where TEntity : class -{ - static BaseEntity() - { - var tkeyType = typeof(TKey)?.NullableTypeOrThis(); - if (tkeyType == typeof(int) || tkeyType == typeof(long)) - Orm.CodeFirst.ConfigEntity(typeof(TEntity), - t => t.Property("Id").IsIdentity(true)); - } - - /// - /// 主键 - /// - public virtual TKey Id { get; set; } - - /// - /// 根据主键值获取数据 - /// - /// - /// - async public static Task FindAsync(TKey id) - { - var item = await Select.WhereDynamic(id).FirstAsync(); - (item as BaseEntity)?.Attach(); - return item; - } - - /// - /// 根据主键值获取数据 - /// - /// - /// - public static TEntity Find(TKey id) - { - var item = Select.WhereDynamic(id).First(); - (item as BaseEntity)?.Attach(); - return item; - } -} \ No newline at end of file diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityTree.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityTree.cs new file mode 100644 index 00000000..fa7bd5b1 --- /dev/null +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityTree.cs @@ -0,0 +1,164 @@ +using FreeSql; +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FreeSql +{ + /// + /// 树状基类 + /// + /// + /// + [Table(DisableSyncStructure = true)] + public abstract class BaseEntityTree : BaseEntity where TEntity : class + { + /// + /// 父级id + /// + public TKey ParentId + { + get => _ParentId; + set + { + if (Equals(value, default(TKey)) == false && Equals(value, Id)) + throw new ArgumentException("ParentId 值不能与 Id 相同"); + _ParentId = value; + } + } + public TEntity Parent { get; set; } + private TKey _ParentId; + + /// + /// 下级列表 + /// + [Navigate("ParentId")] + public List Childs { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 名称:技术部-前端 + /// + public string FullName { get; set; } + + public List GetAllChilds() => Select.WhereDynamic(this) + .IncludeMany(a => (a as BaseEntityTree).Childs, + t1 => t1.IncludeMany(a1 => (a1 as BaseEntityTree).Childs, + t2 => t2.IncludeMany(a2 => (a2 as BaseEntityTree).Childs, + t3 => t3.IncludeMany(a3 => (a3 as BaseEntityTree).Childs, + t4 => t4.IncludeMany(a4 => (a4 as BaseEntityTree).Childs, + t5 => t5.IncludeMany(a5 => (a5 as BaseEntityTree).Childs, + t6 => t6.IncludeMany(a6 => (a6 as BaseEntityTree).Childs, + t7 => t7.IncludeMany(a7 => (a7 as BaseEntityTree).Childs, + t8 => t8.IncludeMany(a8 => (a8 as BaseEntityTree).Childs, + t9 => t9.IncludeMany(a9 => (a9 as BaseEntityTree).Childs, + t10 => t10.IncludeMany(a10 => (a10 as BaseEntityTree).Childs))))))))))).ToList() + .SelectMany(a => (a as BaseEntityTree).Childs + .SelectMany(a1 => (a1 as BaseEntityTree)?.Childs + .SelectMany(a2 => (a2 as BaseEntityTree)?.Childs + .SelectMany(a3 => (a3 as BaseEntityTree)?.Childs + .SelectMany(a4 => (a4 as BaseEntityTree)?.Childs + .SelectMany(a5 => (a5 as BaseEntityTree)?.Childs + .SelectMany(a6 => (a6 as BaseEntityTree)?.Childs + .SelectMany(a7 => (a7 as BaseEntityTree)?.Childs + .SelectMany(a8 => (a8 as BaseEntityTree)?.Childs + .SelectMany(a9 => (a9 as BaseEntityTree)?.Childs + .SelectMany(a10 => (a10 as BaseEntityTree)?.Childs))))))))))).Where(a => a != null).ToList(); + + protected void RefershFullName() + { + var buf = new List(); + buf.Add(this as TEntity); + buf.AddRange(this.GetAllChilds()); + var repo = Orm.GetRepository(); + repo.UnitOfWork = UnitOfWork.Current.Value; + buf = repo.Select.WhereDynamic(buf) + .Include(a => ((((((((((a as BaseEntityTree).Parent + as BaseEntityTree).Parent + as BaseEntityTree).Parent + as BaseEntityTree).Parent + as BaseEntityTree).Parent + as BaseEntityTree).Parent + as BaseEntityTree).Parent + as BaseEntityTree).Parent + as BaseEntityTree).Parent + as BaseEntityTree).Parent).ToList(true); + foreach (var item in buf) + { + var up = item as BaseEntityTree; + up.Name = up.Name; + var cur = up.Parent as BaseEntityTree; + while (cur != null) + { + up.Name = $"{cur.Name}-{up.Name}"; + cur = cur.Parent as BaseEntityTree; + } + } + repo.Update(buf); + } + + T UpdateIsDelete(bool value, Func, List, T> func) + { + var childs = GetAllChilds(); + childs.Add(this as TEntity); + var repo = Orm.GetRepository(); + repo.UnitOfWork = UnitOfWork.Current.Value; + repo.Attach(childs); + foreach (var item in childs) + (item as BaseEntity).IsDeleted = false; + return func(repo, childs); + } + public override bool Delete() => UpdateIsDelete(true, (repo, chis) => repo.Update(chis)) > 0; + async public override Task DeleteAsync() => await UpdateIsDelete(true, (repo, chis) => repo.UpdateAsync(chis)) > 0; + + public override bool Restore() => UpdateIsDelete(false, (repo, chis) => repo.Update(chis)) > 0; + async public override Task RestoreAsync() => await UpdateIsDelete(false, (repo, chis) => repo.UpdateAsync(chis)) > 0; + + public override TEntity Insert() + { + var ret = base.Insert(); + RefershFullName(); + return ret; + } + async public override Task InsertAsync() + { + var ret = await base.InsertAsync(); + RefershFullName(); + return ret; + } + public override bool Update() + { + var old = Find(this.Id) as BaseEntityTree; + var ret = base.Update(); + if (old.Name != this.Name || Equals(old.ParentId, old.ParentId) == false) RefershFullName(); + return ret; + } + async public override Task UpdateAsync() + { + var old = Find(this.Id) as BaseEntityTree; + var ret = await base.UpdateAsync(); + if (old.Name != this.Name || Equals(old.ParentId, old.ParentId) == false) RefershFullName(); + return ret; + } + public override TEntity Save() + { + var old = Find(this.Id) as BaseEntityTree; + var ret = base.Save(); + if (old.Name != this.Name || Equals(old.ParentId, old.ParentId) == false) RefershFullName(); + return ret; + } + async public override Task SaveAsync() + { + var old = Find(this.Id) as BaseEntityTree; + var ret = await base.SaveAsync(); + if (old.Name != this.Name || Equals(old.ParentId, old.ParentId) == false) RefershFullName(); + return ret; + } + } +} \ No newline at end of file diff --git a/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.xml b/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.xml index 6a86cb7c..a03b9ba3 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.xml +++ b/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.xml @@ -4,17 +4,136 @@ FreeSql.Extensions.BaseEntity - + + + 包括 CreateTime/UpdateTime/IsDeleted、CRUD 方法、以及 ID 主键定义 的实体基类 + + 当 TKey 为 int/long 时,Id 主键被设为自增值主键 + + + + + + + 主键 + + + + + 根据主键值获取数据 + + + + + + + 根据主键值获取数据 + + + + + + + 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步和同步方法的实体基类 + + + + + + 删除数据 + + + + + + 恢复删除的数据 + + + + + + 更新数据 + + + + + + 插入数据 + + + + + 更新或插入 + + + + + + 包括 CreateTime/UpdateTime/IsDeleted、CRUD 异步方法、以及 ID 主键定义 的实体基类 + + 当 TKey 为 int/long 时,Id 主键被设为自增值主键 + + + + + + + 主键 + + + + + 根据主键值获取数据 + + + + + + + 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步方法的实体基类 + + + + + + 删除数据 + + + + + + 恢复删除的数据 + + + + + + 更新数据 + + + + + + 插入数据 + + + + + 更新或插入 + + + + 包括 CreateTime/UpdateTime/IsDeleted 的实体基类 - + 全局 IFreeSql orm 对象 - + 初始化BaseEntity BaseEntity.Initialization(new FreeSqlBuilder() @@ -27,54 +146,73 @@ IFreeSql orm 对象 - + 创建时间 - + 更新时间 - + 逻辑删除 - + + + 排序 + + + 开启工作单元事务 - + 开启工作单元事务 事务等级 - + - 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步方法的实体基类 + 获取或设置当前租户id - - + + + 租户 + + + + + 租户id + + + 查询数据 - + + + 设置当前租户id + + + 查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com") lambda表达式 - + 查询条件,Where(true, a => a.Id > 10),支导航对象查询,Where(true, a => a.Author.Email == "2881099@qq.com") @@ -82,131 +220,42 @@ lambda表达式 - + 仓储对象 - + 附加实体,在更新数据时,只更新变化的部分 - - async * - - + - 删除数据 - - - - - - 恢复删除的数据 - - - - - - 更新数据 - - - - - - 插入数据 - - - - - 更新或插入 - - - - - - 包括 CreateTime/UpdateTime/IsDeleted、CRUD 异步方法、以及 ID 主键定义 的实体基类 - - 当 TKey 为 int/long 时,Id 主键被设为自增值主键 + 树状基类 - + - 主键 + 父级id - + - 根据主键值获取数据 - - - - - - - 包括 CreateTime/UpdateTime/IsDeleted、以及 CRUD 异步和同步方法的实体基类 - - - - - - 删除数据 - - - - - - 恢复删除的数据 - - - - - - 更新数据 - - - - - - 插入数据 + 下级列表 - + - 更新或插入 - - - - - - 包括 CreateTime/UpdateTime/IsDeleted、CRUD 方法、以及 ID 主键定义 的实体基类 - - 当 TKey 为 int/long 时,Id 主键被设为自增值主键 - - - - - - - 主键 + 名称 - + - 根据主键值获取数据 + 名称:技术部-前端 - - - - - - 根据主键值获取数据 - - -