using FreeSql.DataAnnotations; using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Threading; // ReSharper disable CheckNamespace // ReSharper disable InconsistentNaming // ReSharper disable InconsistentlySynchronizedField namespace FreeSql { /// /// Entity base class, including CreateTime/UpdateTime/IsDeleted. /// /// 包括 CreateTime/UpdateTime/IsDeleted 的实体基类 /// [Table(DisableSyncStructure = true)] public abstract class BaseEntity { internal static IFreeSql _ormPriv; private const string ErrorMessageTemplate = @"使用前请初始化: BaseEntity.Initialization(new FreeSqlBuilder() .UseAutoSyncStructure(true) .UseConnectionString(DataType.Sqlite, ""data source=test.db;max pool size=5"") .Build());"; /// /// Global IFreeSql ORM Object
/// 全局 IFreeSql ORM 对象 ///
public static IFreeSql Orm => _ormPriv ?? throw new Exception(ErrorMessageTemplate); internal static Func _resolveUow; /// /// To initialize the BaseEntity
/// 初始化 BaseEntity /// /// BaseEntity.Initialization(
/// new FreeSqlBuilder()
/// .UseAutoSyncStructure(true)
/// .UseConnectionString(DataType.Sqlite, "data source=test.db;max pool size=5")
/// .Build()); ///
/// IFreeSql ORM Object /// 工作单元(事务)委托,如果不使用事务请传 null解释:由于AsyncLocal平台兼容不好,所以交给外部管理 public static void Initialization(IFreeSql fsql, Func resolveUow) { _ormPriv = fsql; _ormPriv.Aop.CurdBefore += (s, e) => Trace.WriteLine($"\r\n线程{Thread.CurrentThread.ManagedThreadId}: {e.Sql}\r\n"); if (_configEntityQueues.Any()) { lock (_configEntityLock) { while (_configEntityQueues.TryDequeue(out var cei)) _ormPriv.CodeFirst.ConfigEntity(cei.EntityType, cei.Fluent); } } _resolveUow = resolveUow; } class ConfigEntityInfo { public Type EntityType; public Action Fluent; } static readonly ConcurrentQueue _configEntityQueues = new(); static readonly object _configEntityLock = new(); internal static void ConfigEntity(Type entityType, Action fluent) { lock (_configEntityLock) { if (_ormPriv is null) _configEntityQueues.Enqueue(new ConfigEntityInfo { EntityType = entityType, Fluent = fluent }); else _ormPriv.CodeFirst.ConfigEntity(entityType, fluent); } } /// /// Created time
/// 创建时间 ///
[Column(Position = -4)] public virtual DateTime CreateTime { get; set; } = DateTime.Now; /// /// Updated time
/// 更新时间 ///
[Column(Position = -3)] public virtual DateTime UpdateTime { get; set; } /// /// Logical Delete
/// 逻辑删除 ///
[Column(Position = -2)] public virtual bool IsDeleted { get; set; } /// /// Sort
/// 排序 ///
[Column(Position = -1)] public virtual int Sort { get; set; } } /// /// A readonly entity base class, including CreateTime/UpdateTime/IsDeleted. /// /// 包括 CreateTime/UpdateTime/IsDeleted 的只读实体基类 /// /// [Table(DisableSyncStructure = true)] public abstract class BaseEntityReadOnly : BaseEntity where TEntity : class { /// /// To query data
/// 查询数据 ///
/// public static ISelect Select { get { var select = Orm.Select() .TrackToList(TrackToList) //自动为每个元素 Attach .WithTransaction(_resolveUow?.Invoke()?.GetOrBeginTransaction(false)); return select.WhereCascade(a => (a as BaseEntity).IsDeleted == false); } } static void TrackToList(object list) { if (list is null) return; if (list is not IList ls) { if (list is not IEnumerable ie) return; var isFirst = true; IBaseRepository baseRepo = null; foreach (var item in ie) { if (item is null) { return; } if (isFirst) { isFirst = false; var itemType = item.GetType(); if (itemType == typeof(object)) return; if (itemType.FullName!.Contains("FreeSqlLazyEntity__")) itemType = itemType.BaseType; if (Orm.CodeFirst.GetTableByEntity(itemType)?.Primarys.Any() != true) return; if (item is not BaseEntity) return; } if (item is BaseEntity entity) { baseRepo ??= Orm.GetRepository(); entity.Repository = baseRepo; entity.Attach(); } } return; } if (ls.Any() == false) return; if (ls.FirstOrDefault() is not BaseEntity) return; if (Orm.CodeFirst.GetTableByEntity(typeof(TEntity))?.Primarys.Any() != true) return; IBaseRepository repo = null; foreach (var item in ls) { if (item is BaseEntity entity) { repo ??= Orm.GetRepository(); entity.Repository = repo; entity.Attach(); } } } /// /// Query conditions
/// 查询条件,Where(a => a.Id> 10) /// /// Support navigation object query
/// 支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com") ///
/// lambda表达式 /// public static ISelect Where(Expression> exp) => Select.Where(exp); /// /// Query conditions
/// 查询条件,Where(true, a => a.Id > 10) /// /// Support navigation object query
/// 支导航对象查询,Where(true, a => a.Author.Email == "2881099@qq.com") ///
/// true 时生效 /// lambda表达式 /// public static ISelect WhereIf(bool condition, Expression> exp) => Select.WhereIf(condition, exp); /// /// Repository object.
/// 仓储对象 ///
protected IBaseRepository Repository { get; set; } /// /// To Attach entities. When updating data, only the changed part is updated.
/// 附加实体。在更新数据时,只更新变化的部分 ///
public TEntity Attach() { Repository ??= Orm.GetRepository(); var item = this as TEntity; Repository.Attach(item); return item; } } }