From e5cbd407cbfc752b691221d5a194d940c829a5fd Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Thu, 2 Apr 2020 16:21:18 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20FreeSqlBuilder=20UseSe?= =?UTF-8?q?edData=20=E8=AE=BE=E5=AE=9A=20CodeFirst=20=E7=A7=8D=E5=AD=90?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/base_entity/Program.cs | 19 +- .../BaseEntity.cs | 3 +- .../BaseEntityAsync.cs | 3 +- .../BaseEntityReadOnly.cs | 29 ++- FreeSql.DbContext/FreeSql.DbContext.xml | 9 - FreeSql/FreeSql.xml | 195 +++--------------- FreeSql/FreeSqlBuilder.cs | 127 ++++++------ FreeSql/FreeSqlBuilder_Obsolete.cs | 80 +++++++ 8 files changed, 222 insertions(+), 243 deletions(-) create mode 100644 FreeSql/FreeSqlBuilder_Obsolete.cs diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index 97aad3ee..9d762f82 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -65,7 +65,24 @@ namespace base_entity //.UseConnectionString(FreeSql.DataType.OdbcOracle, "Driver={Oracle in XE};Server=//127.0.0.1:1521/XE;Persist Security Info=False;Trusted_Connection=Yes;UID=odbc1;PWD=123456") //.UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) - .UseConnectionString(FreeSql.DataType.OdbcDameng, "Driver={DM8 ODBC DRIVER};Server=127.0.0.1:5236;Persist Security Info=False;Trusted_Connection=Yes;UID=USER1;PWD=123456789") + //.UseConnectionString(FreeSql.DataType.OdbcDameng, "Driver={DM8 ODBC DRIVER};Server=127.0.0.1:5236;Persist Security Info=False;Trusted_Connection=Yes;UID=USER1;PWD=123456789") + + .UseMonitorCommand(cmd => Console.Write(cmd.CommandText)) + .UseSeedData(sd => sd + .Apply(new[] + { + new Products { Id = 1, title = "product-1" }, + new Products { Id = 2, title = "product-2" }, + new Products { Id = 3, title = "product-3" }, + new Products { Id = 4, title = "product-4" } + }) + .Apply(new[] + { + new S_SysConfig { Name = "testkey11", Config = new TestConfig { clicks = 11, title = "testtitle11" } }, + new S_SysConfig { Name = "testkey22", Config = new TestConfig { clicks = 22, title = "testtitle22" } }, + new S_SysConfig { Name = "testkey33", Config = new TestConfig { clicks = 33, title = "testtitle33" } } + }) + ) .UseLazyLoading(true) .Build(); diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs index 516fdbd9..829e33c5 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntity.cs @@ -25,8 +25,7 @@ namespace FreeSql { var tkeyType = typeof(TKey)?.NullableTypeOrThis(); if (tkeyType == typeof(int) || tkeyType == typeof(long)) - Orm.CodeFirst.ConfigEntity(typeof(TEntity), - t => t.Property("Id").IsIdentity(true)); + BaseEntity.ConfigEntity(typeof(TEntity), t => t.Property("Id").IsIdentity(true)); } /// diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs index 0d412cdb..fb43fcb9 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityAsync.cs @@ -21,8 +21,7 @@ namespace FreeSql { var tkeyType = typeof(TKey)?.NullableTypeOrThis(); if (tkeyType == typeof(int) || tkeyType == typeof(long)) - Orm.CodeFirst.ConfigEntity(typeof(TEntity), - t => t.Property("Id").IsIdentity(true)); + BaseEntity.ConfigEntity(typeof(TEntity), t => t.Property("Id").IsIdentity(true)); } /// diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs index e50030ab..68174990 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs @@ -4,6 +4,7 @@ using FreeSql.DataAnnotations; using System; using System.Collections; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Data; using System.Diagnostics; using System.Linq; @@ -18,7 +19,7 @@ namespace FreeSql [Table(DisableSyncStructure = true)] public abstract class BaseEntity { - static IFreeSql _ormPriv; + internal static IFreeSql _ormPriv; /// /// 全局 IFreeSql orm 对象 /// @@ -42,6 +43,32 @@ namespace FreeSql { _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); + } + } + } + + class ConfigEntityInfo + { + public Type EntityType; + public Action Fluent; + } + static ConcurrentQueue _configEntityQueues = new ConcurrentQueue(); + static object _configEntityLock = new object(); + internal static void ConfigEntity(Type entityType, Action fluent) + { + lock (_configEntityLock) + { + if (_ormPriv == null) + _configEntityQueues.Enqueue(new ConfigEntityInfo { EntityType = entityType, Fluent = fluent }); + else + _ormPriv.CodeFirst.ConfigEntity(entityType, fluent); + } } /// diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 2fa6c448..bd335d0e 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -217,15 +217,6 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - 注意:IFreeSql 属于顶级对象,事务无法自动传递。 diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index d9c8421f..e9379bd3 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -690,20 +690,6 @@ true:运行时检查自动同步结构, false:不同步结构 - - - 转小写同步结构 - - true:转小写, false:不转 - - - - - 转大写同步结构 - - true:转大写, false:不转 - - 将数据库的主键、自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。 @@ -746,6 +732,36 @@ 执行后,可监视执行性能 + + + 实体类名 -> 数据库表名,命名转换(类名、属性名都生效) + 优先级小于 [Table(Name = "xxx")]、[Column(Name = "xxx")] + + + + + + + CodeFirst 初始化种子数据 + 表数据为空时,创建设定的种子数据 + + + + + + + 转小写同步结构 + + true:转小写, false:不转 + + + + + 转大写同步结构 + + true:转大写, false:不转 + + 自动转换实体属性名称 Entity Property -> Db Filed @@ -755,14 +771,6 @@ - - - 实体类名 -> 数据库表名,命名转换(类名、属性名都生效) - 优先级小于 [Table(Name = "xxx")]、[Column(Name = "xxx")] - - - - 指定事务对象 @@ -2309,137 +2317,6 @@ - - - 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】 - - - - - - - - - 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > ?age", new { age = 25 }) - - - - - - - 查询 - - - - - - - 查询,ExecuteArrayAsync("select * from user where age > ?age", new { age = 25 }) - - - - - - - - 查询 - - - - - - - 查询,ExecuteDataSetAsync("select * from user where age > ?age; select 2", new { age = 25 }) - - - - - - - - 查询 - - - - - - - 查询,ExecuteDataTableAsync("select * from user where age > ?age", new { age = 25 }) - - - - - - - - 在【主库】执行 - - - - - - - - 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > ?age", new { age = 25 }) - - - - - - - - 在【主库】执行 - - - - - - - - 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > ?age", new { age = 25 }) - - - - - - - - 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > ?age", new SqlParameter { ParameterName = "age", Value = 25 }) - - - - - - - - - - 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > ?age", new { age = 25 }) - - - - - - - - - 执行SQL返回对象集合,Query<User>("select * from user where age > ?age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 }) - - - - - - - - - - 执行SQL返回对象集合,Query<User>("select * from user where age > ?age; select * from address", new { age = 25 }) - - - - - - 可自定义解析表达式 @@ -2963,12 +2840,6 @@ 超时 - - - 获取资源 - - - 使用完毕后,归还资源 @@ -3039,12 +2910,6 @@ 资源对象 - - - 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象 - - 资源对象 - 归还对象给对象池的时候触发 diff --git a/FreeSql/FreeSqlBuilder.cs b/FreeSql/FreeSqlBuilder.cs index 800b3900..11e881a7 100644 --- a/FreeSql/FreeSqlBuilder.cs +++ b/FreeSql/FreeSqlBuilder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Reflection; @@ -7,7 +8,7 @@ using FreeSql.Internal; namespace FreeSql { - public class FreeSqlBuilder + public partial class FreeSqlBuilder { DataType _dataType; string _masterConnectionString; @@ -79,28 +80,6 @@ namespace FreeSql return this; } /// - /// 转小写同步结构 - /// - /// true:转小写, false:不转 - /// - [Obsolete("请使用 UseNameConvert(NameConvertType.ToLower),或者 fsql.CodeFirst.IsSyncStructureToLower = value")] - public FreeSqlBuilder UseSyncStructureToLower(bool value) - { - _isSyncStructureToLower = value; - return this; - } - /// - /// 转大写同步结构 - /// - /// true:转大写, false:不转 - /// - [Obsolete("请使用 UseNameConvert(NameConvertType.ToUpper),或者 fsql.CodeFirst.IsSyncStructureToUpper = value")] - public FreeSqlBuilder UseSyncStructureToUpper(bool value) - { - _isSyncStructureToUpper = value; - return this; - } - /// /// 将数据库的主键、自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。 /// 本功能会影响 IFreeSql 首次访问的速度。 /// 若使用 CodeFirst 创建索引后,又直接在数据库上建了索引,若无本功能下一次 CodeFirst 迁移时数据库上创建的索引将被删除 @@ -159,20 +138,6 @@ namespace FreeSql return this; } - /// - /// 自动转换实体属性名称 Entity Property -> Db Filed - /// - /// *不会覆盖 [Column] 特性设置的Name - /// - /// - /// - [Obsolete("请使用 UseNameConvert 功能")] - public FreeSqlBuilder UseEntityPropertyNameConvert(StringConvertType convertType) - { - _entityPropertyConvertType = convertType; - return this; - } - /// /// 实体类名 -> 数据库表名,命名转换(类名、属性名都生效) /// 优先级小于 [Table(Name = "xxx")]、[Column(Name = "xxx")] @@ -276,32 +241,7 @@ namespace FreeSql _aopCommandExecuted?.Invoke(e.Command, e.Log); }); - //添加实体属性名全局AOP转换处理 - if (_entityPropertyConvertType != StringConvertType.None) - { - string PascalCaseToUnderScore(string str) => string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())); - - switch (_entityPropertyConvertType) - { - case StringConvertType.Lower: - ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = e.Property.Name.ToLower(); - break; - case StringConvertType.Upper: - ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = e.Property.Name.ToUpper(); - break; - case StringConvertType.PascalCaseToUnderscore: - ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.Property.Name); - break; - case StringConvertType.PascalCaseToUnderscoreWithLower: - ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.Property.Name).ToLower(); - break; - case StringConvertType.PascalCaseToUnderscoreWithUpper: - ret.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.Property.Name).ToUpper(); - break; - default: - break; - } - } + this.EntityPropertyNameConvert(ret); //添加实体属性名全局AOP转换处理 if (_nameConvertType != NameConvertType.None) { @@ -362,9 +302,70 @@ namespace FreeSql } } }); + + //SeedData + if (_seedData != null && _seedData._data.Any()) + { + ret.Aop.SyncStructureAfter += new EventHandler((s, e) => + { + if (string.IsNullOrEmpty(e.Sql)) return; + foreach (var et in e.EntityTypes) + { + if (_seedData._data.TryGetValue(et, out var sd) == false) continue; + if (sd.Any() == false) continue; + if (ret.Select().AsType(et).Any()) continue; + ret.Insert() + .AsType(et) + .NoneParameter() + .InsertIdentity() + .AppendData(sd.ToArray()) + .ExecuteAffrows(); + } + }); + + foreach (var sd in _seedData._data) + { + ret.CodeFirst.SyncStructure(sd.Key); + } + } } return ret; } + + public class SeedDataBuilder + { + internal Dictionary> _data = new Dictionary>(); + public SeedDataBuilder Apply(T data) where T : class + { + if (_data.TryGetValue(typeof(T), out var ds) == false) + _data.Add(typeof(T), ds = new List()); + ds.Add(data); + return this; + } + public SeedDataBuilder Apply(T[] data) where T : class + { + return this.Apply(data as IEnumerable); + } + public SeedDataBuilder Apply(IEnumerable data) where T : class + { + foreach (var d in data) this.Apply(d); + return this; + } + } + SeedDataBuilder _seedData; + + /// + /// CodeFirst 初始化种子数据 + /// 表数据为空时,创建设定的种子数据 + /// + /// + /// + public FreeSqlBuilder UseSeedData(Action sd) + { + _seedData = new SeedDataBuilder(); + sd?.Invoke(_seedData); + return this; + } } } diff --git a/FreeSql/FreeSqlBuilder_Obsolete.cs b/FreeSql/FreeSqlBuilder_Obsolete.cs new file mode 100644 index 00000000..41563807 --- /dev/null +++ b/FreeSql/FreeSqlBuilder_Obsolete.cs @@ -0,0 +1,80 @@ +using System; +using System.Data.Common; +using System.Linq; +using System.Reflection; +using FreeSql.DataAnnotations; +using FreeSql.Internal; + +namespace FreeSql +{ + partial class FreeSqlBuilder + { + + /// + /// 转小写同步结构 + /// + /// true:转小写, false:不转 + /// + [Obsolete("请使用 UseNameConvert(NameConvertType.ToLower),或者 fsql.CodeFirst.IsSyncStructureToLower = value")] + public FreeSqlBuilder UseSyncStructureToLower(bool value) + { + _isSyncStructureToLower = value; + return this; + } + /// + /// 转大写同步结构 + /// + /// true:转大写, false:不转 + /// + [Obsolete("请使用 UseNameConvert(NameConvertType.ToUpper),或者 fsql.CodeFirst.IsSyncStructureToUpper = value")] + public FreeSqlBuilder UseSyncStructureToUpper(bool value) + { + _isSyncStructureToUpper = value; + return this; + } + + /// + /// 自动转换实体属性名称 Entity Property -> Db Filed + /// + /// *不会覆盖 [Column] 特性设置的Name + /// + /// + /// + [Obsolete("请使用 UseNameConvert 功能")] + public FreeSqlBuilder UseEntityPropertyNameConvert(StringConvertType convertType) + { + _entityPropertyConvertType = convertType; + return this; + } + + void EntityPropertyNameConvert(IFreeSql fsql) + { + //添加实体属性名全局AOP转换处理 + if (_entityPropertyConvertType != StringConvertType.None) + { + string PascalCaseToUnderScore(string str) => string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())); + + switch (_entityPropertyConvertType) + { + case StringConvertType.Lower: + fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = e.Property.Name.ToLower(); + break; + case StringConvertType.Upper: + fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = e.Property.Name.ToUpper(); + break; + case StringConvertType.PascalCaseToUnderscore: + fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.Property.Name); + break; + case StringConvertType.PascalCaseToUnderscoreWithLower: + fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.Property.Name).ToLower(); + break; + case StringConvertType.PascalCaseToUnderscoreWithUpper: + fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.Property.Name).ToUpper(); + break; + default: + break; + } + } + } + } +}