From c396a483dbcda162af2668e0dffb470038eabbae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E7=9F=B3=E5=A4=B4?= Date: Sun, 28 Jul 2024 21:53:07 +0800 Subject: [PATCH] =?UTF-8?q?FindByKey=E4=B8=8EFindByKeyForEdit=E6=94=AF?= =?UTF-8?q?=E6=8C=81key=E4=BC=A0=E5=85=A5IModel=EF=BC=8C=E5=85=B6=E4=B8=AD?= =?UTF-8?q?=E5=B8=A6=E6=9C=89=E4=B8=BB=E9=94=AE=E5=92=8C=E5=88=86=E8=A1=A8?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=8C=E4=B8=93=E7=94=A8=E4=BA=8E=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E5=88=86=E8=A1=A8=E5=AD=97=E6=AE=B5=E4=B8=8D=E6=98=AF?= =?UTF-8?q?=E4=B8=BB=E9=94=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- XCode/Entity/Entity.cs | 140 ++++++++------------------------ XCode/Entity/Entity_Meta.cs | 18 ++-- XCode/Entity/Entity_Operate.cs | 8 +- XCode/Entity/IEntityOperate.cs | 8 +- XCode/Shards/TimeShardPolicy.cs | 5 +- 5 files changed, 52 insertions(+), 127 deletions(-) diff --git a/XCode/Entity/Entity.cs b/XCode/Entity/Entity.cs index 3719321de..527a43647 100644 --- a/XCode/Entity/Entity.cs +++ b/XCode/Entity/Entity.cs @@ -573,51 +573,12 @@ public virtual Boolean Exist(Boolean isNew, params String[] names) /// public static TEntity? Find(String name, Object value, String selects) => Find([name], [value], selects); - /// 根据属性列表以及对应的值列表,查找单个实体 - /// 属性名称集合 - /// 属性值集合 - /// - public static TEntity? Find(String[] names, Object[] values) - { - if (names == null || names.Length == 0) throw new ArgumentNullException(nameof(names)); - if (values == null || values.Length == 0) throw new ArgumentNullException(nameof(values)); - - var exp = new WhereExpression(); - // 判断自增和主键 - if (names.Length == 1) - { - var field = Meta.Table.FindByName(names[0]); - if ((field as FieldItem) != null && (field.IsIdentity || field.PrimaryKey)) - { - // 唯一键为自增且参数小于等于0时,返回空 - if (Helper.IsNullKey(values[0], field.Type)) return null; - - exp &= field == values[0]; - return FindUnique(exp); - } - } - - for (var i = 0; i < names.Length; i++) - { - var fi = Meta.Table.FindByName(names[i]); - if (ReferenceEquals(fi, null)) throw new ArgumentOutOfRangeException(nameof(names), $"{names[i]} not found"); - - exp &= fi == values[i]; - } - - // 判断唯一索引,唯一索引也不需要分页 - var di = Meta.Table.DataTable.GetIndex(names); - if (di != null && di.Unique) return FindUnique(exp); - - return Find(exp); - } - /// 根据属性列表以及对应的值列表,查找单个实体 /// 属性名称集合 /// 属性值集合 /// 查询列,默认null表示所有字段 /// - public static TEntity? Find(String[] names, Object[] values, String selects) + public static TEntity? Find(String[] names, Object[] values, String? selects = null) { if (names == null || names.Length == 0) throw new ArgumentNullException(nameof(names)); if (values == null || values.Length == 0) throw new ArgumentNullException(nameof(values)); @@ -652,48 +613,6 @@ public virtual Boolean Exist(Boolean isNew, params String[] names) return Find(exp, selects); } - /// 根据条件查找唯一的单个实体 - /// 根据条件查找唯一的单个实体,因为是唯一的,所以不需要分页和排序。 - /// 如果不确定是否唯一,一定不要调用该方法,否则会返回大量的数据。 - /// - /// - /// 查询条件 - /// - private static TEntity? FindUnique(Expression where) - { - var session = Meta.Session; - var db = session.Dal.Db; - var ps = db.UseParameter ? new Dictionary() : null; - var wh = where?.GetString(db, ps); - - var builder = new SelectBuilder - { - Table = session.FormatedTableName, - // 谨记:某些项目中可能在where中使用了GroupBy,在分页时可能报错 - Where = wh - - }; - - // 使用默认选择列 - if (builder.Column.IsNullOrEmpty()) builder.Column = Meta.Factory.Selects; - - // 提取参数 - builder = FixParam(builder, ps); - - var list = LoadData(session.Query(builder, 0, 0)); - //var list = session.Query(builder, 0, 0, LoadData); - if (list == null || list.Count <= 0) return null; - - // 如果正在使用单对象缓存,则批量进入 - LoadSingleCache(list); - - if (list.Count > 1 && DAL.Debug) - { - DAL.WriteLog("调用FindUnique(\"{0}\")不合理,只有返回唯一记录的查询条件才允许调用!", wh); - } - return list[0]; - } - /// 根据条件查找唯一的单个实体 /// 根据条件查找唯一的单个实体,因为是唯一的,所以不需要分页和排序。 /// 如果不确定是否唯一,一定不要调用该方法,否则会返回大量的数据。 @@ -702,7 +621,7 @@ public virtual Boolean Exist(Boolean isNew, params String[] names) /// 查询条件 /// 查询列,默认null表示所有字段 /// - private static TEntity? FindUnique(Expression where, String selects) + private static TEntity? FindUnique(Expression where, String? selects = null) { var session = Meta.Session; var db = session.Dal.Db; @@ -750,22 +669,13 @@ public virtual Boolean Exist(Boolean isNew, params String[] names) /// 根据条件查找单个实体 /// 查询条件 /// - public static TEntity? Find(Expression where) - { - var max = 1; - - // 优待主键查询 - if (where is FieldExpression fe && fe.Field != null && fe.Field.PrimaryKey) max = 0; - - var list = FindAll(where, null, null, 0, max); - return list.Count <= 0 ? null : list[0]; - } + public static TEntity? Find(Expression where) => Find(where, null); /// 根据条件查找单个实体 /// 查询条件 /// 查询列,默认null表示所有字段 /// - public static TEntity? Find(Expression where, String selects) + public static TEntity? Find(Expression where, String? selects) { var max = 1; @@ -780,28 +690,35 @@ public virtual Boolean Exist(Boolean isNew, params String[] names) /// 唯一主键的值 /// 查询列,默认null表示所有字段 /// - public static TEntity? FindByKey(Object key, String selects) + public static TEntity? FindByKey(Object key, String? selects) { var field = Meta.Unique ?? throw new ArgumentNullException(nameof(Meta.Unique), "FindByKey方法要求" + typeof(TEntity).FullName + "有唯一主键!"); + // 查询时可能传入IModel,为了分表查询,主要解决分表字段不是主键的场景 + var model = key as IModel; + if (model != null) key = model[field.Name]!; + // 唯一键为自增且参数小于等于0时,返回空 if (Helper.IsNullKey(key, field.Type)) return null; - return Find(field.Name, key, selects); + if (Meta.InShard) return Find(field.Name, key); + + // 自动分库分表 + if (model == null) + { + model = new TEntity(); + model[field.Name] = key; + } + using var split = Meta.CreateShard(model); + + // 此外,一律返回 查找值,即使可能是空。而绝不能在找不到数据的情况下给它返回空,因为可能是找不到数据而已,而返回新实例会导致前端以为这里是新增数据 + return Find(field.Name, key); } /// 根据主键查找单个实体 /// 唯一主键的值 /// - public static TEntity? FindByKey(Object key) - { - var field = Meta.Unique ?? throw new ArgumentNullException(nameof(Meta.Unique), "FindByKey方法要求" + typeof(TEntity).FullName + "有唯一主键!"); - - // 唯一键为自增且参数小于等于0时,返回空 - if (Helper.IsNullKey(key, field.Type)) return null; - - return Find(field.Name, key); - } + public static TEntity? FindByKey(Object key) => FindByKey(key, null); /// 根据主键查询一个实体对象用于表单编辑 /// 唯一主键的值 @@ -810,6 +727,10 @@ public virtual Boolean Exist(Boolean isNew, params String[] names) { var field = Meta.Unique ?? throw new ArgumentNullException("Meta.Unique", "FindByKeyForEdit方法要求该表有唯一主键!"); + // 查询时可能传入IModel,为了分表查询,主要解决分表字段不是主键的场景 + var model = key as IModel; + if (model != null) key = model[field.Name]!; + // 参数为空时,返回新实例 if (key == null) return Meta.Factory.Create(true) as TEntity; @@ -831,9 +752,12 @@ public virtual Boolean Exist(Boolean isNew, params String[] names) else { // 自动分库分表 - var keyEntity = new TEntity(); - keyEntity[field.Name] = key; - using var split = Meta.CreateShard(keyEntity); + if (model == null) + { + model = new TEntity(); + model[field.Name] = key; + } + using var split = Meta.CreateShard(model); // 此外,一律返回 查找值,即使可能是空。而绝不能在找不到数据的情况下给它返回空,因为可能是找不到数据而已,而返回新实例会导致前端以为这里是新增数据 entity = Find(field.Name, key); diff --git a/XCode/Entity/Entity_Meta.cs b/XCode/Entity/Entity_Meta.cs index 57365180c..b302c8c97 100644 --- a/XCode/Entity/Entity_Meta.cs +++ b/XCode/Entity/Entity_Meta.cs @@ -197,15 +197,15 @@ void Reset() /// public static IDisposable CreateSplit(String connName, String tableName) => new SplitPackge(connName, tableName); - /// 针对实体对象自动分库分表 - /// - /// - public static IDisposable? CreateShard(TEntity entity) - { - // 使用自动分表分库策略 - var model = ShardPolicy?.Shard(entity); - return model != null ? new SplitPackge(model.ConnName, model.TableName) : null; - } + ///// 针对实体对象自动分库分表 + ///// + ///// + //public static IDisposable? CreateShard(TEntity entity) + //{ + // // 使用自动分表分库策略 + // var model = ShardPolicy?.Shard(entity); + // return model != null ? new SplitPackge(model.ConnName, model.TableName) : null; + //} /// 为实体对象、时间、雪花Id等计算分表分库 /// diff --git a/XCode/Entity/Entity_Operate.cs b/XCode/Entity/Entity_Operate.cs index 1ffba49df..a14de0e73 100644 --- a/XCode/Entity/Entity_Operate.cs +++ b/XCode/Entity/Entity_Operate.cs @@ -170,10 +170,10 @@ public DefaultEntityFactory() /// public virtual IDisposable CreateSplit(String connName, String tableName) => Meta.CreateSplit(connName, tableName); - /// 针对实体对象自动分库分表 - /// - /// - public virtual IDisposable? CreateShard(IEntity entity) => Meta.CreateShard((entity as TEntity)!); + ///// 针对实体对象自动分库分表 + ///// + ///// + //public virtual IDisposable? CreateShard(IEntity entity) => Meta.CreateShard((entity as TEntity)!); /// 为实体对象、时间、雪花Id等计算分表分库 /// diff --git a/XCode/Entity/IEntityOperate.cs b/XCode/Entity/IEntityOperate.cs index 4b9317cc0..d8c3f7f6d 100644 --- a/XCode/Entity/IEntityOperate.cs +++ b/XCode/Entity/IEntityOperate.cs @@ -171,10 +171,10 @@ public interface IEntityFactory /// IDisposable CreateSplit(String connName, String tableName); - /// 针对实体对象自动分库分表 - /// - /// - IDisposable? CreateShard(IEntity entity); + ///// 针对实体对象自动分库分表 + ///// + ///// + //IDisposable? CreateShard(IEntity entity); /// 为实体对象、时间、雪花Id等计算分表分库 /// diff --git a/XCode/Shards/TimeShardPolicy.cs b/XCode/Shards/TimeShardPolicy.cs index bba36ff09..5b523c442 100644 --- a/XCode/Shards/TimeShardPolicy.cs +++ b/XCode/Shards/TimeShardPolicy.cs @@ -1,4 +1,5 @@ using NewLife; +using NewLife.Data; using XCode.Configuration; using XCode.Statistics; @@ -62,7 +63,7 @@ public TimeShardPolicy(String fieldName, IEntityFactory factory) /// public virtual ShardModel? Shard(Object value) { - if (value is IEntity entity) return Shard(entity); + if (value is IModel entity) return Shard(entity); if (value is DateTime dt) return Shard(dt); if (value is Int64 id) { @@ -80,7 +81,7 @@ public TimeShardPolicy(String fieldName, IEntityFactory factory) /// 为实体对象计算分表分库 /// /// - public virtual ShardModel? Shard(IEntity entity) + public virtual ShardModel? Shard(IModel entity) { var fi = GetField(); if (fi == null) throw new XCodeException("分表策略要求指定时间字段!");