diff --git a/Directory.Build.props b/Directory.Build.props index 635682e8..37a6ecf5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,7 +11,7 @@ diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index 2b8be9af..ba879bbc 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -4,6 +4,7 @@ using FreeSql.Extensions; using FreeSql.Internal; using FreeSql.Internal.CommonProvider; using FreeSql.Internal.Model; +using FreeSql.Odbc.Default; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; @@ -351,6 +352,15 @@ namespace base_entity public int aa { get; set; } } + [Table(Name = "db2.sql_AAA_attr")] + [Index("{tablename}_xxx1", nameof(aa))] + [Index("{tablename}_xxx2", nameof(aa))] + public class SqliteAAA + { + [Column(Name = "aa_attr")] + public int aa { get; set; } + } + public class JoinConditionAttribute : Attribute { public string Condition { get; set; } @@ -372,8 +382,55 @@ namespace base_entity } public enum JoinTest01Enum { f1, f2, f3 } + public class AccessOdbcAdapter : OdbcAdapter + { + public override string UnicodeStringRawSql(object value, ColumnInfo mapColumn) => value == null ? "NULL" : string.Concat("'", value.ToString().Replace("'", "''"), "'"); + } + private static IFreeSql CreateInstance(string connectString, DataType type) + { + IFreeSql client = new FreeSqlBuilder() + .UseConnectionString(type, connectString) + .Build(); + if (DataType.Odbc.Equals(type)) + { + client.SetOdbcAdapter(new AccessOdbcAdapter()); + } + return client; + } + static void Main(string[] args) { + var pams = new Dictionary(); + var sql2rscs = Utils.ReplaceSqlConstString("'', 'SARTEN ACERO VITR.18CM''''GRAFIT''''', 'a", + pams, "@lantin1"); + + //using (IFreeSql client = CreateInstance(@"Driver={Microsoft Access Driver (*.mdb)};DBQ=d:/accdb/2007.accdb", DataType.Odbc)) + //{ + // client.Aop.AuditValue += (_, e) => + // { + // if (e.Object is Dictionary dict) + // { + // foreach(var key in dict.Keys) + // { + // var val = dict[key]; + // if (val == DBNull.Value) dict[key] = null; + // } + // e.ObjectAuditBreak = true; + // } + // }; + // Dictionary data = new Dictionary(); + // data.Add("ExpNo", "RSP0950008"); + // data.Add("SPoint", "RSP0950004"); + // data.Add("EPoint", "RSP095000440"); + // data.Add("PType", "RS"); + // data.Add("GType", "窨井轮廓线"); + // data.Add("LineStyle", 2); + // data.Add("Memo", DBNull.Value); + // data.Add("ClassID", DBNull.Value); + // var kdkdksqlxx = client.InsertDict(data).AsTable("FZLINE").ToSql(); + //} + + BaseModel.fsql = 1; BaseModel.fsql = 2; Console.WriteLine(BaseModel.fsql); @@ -389,6 +446,7 @@ namespace base_entity .UseConnectionString(FreeSql.DataType.Sqlite, "data source=:memory:") + //.UseConnectionString(DataType.Sqlite, "data source=db1.db;attachs=db2.db") //.UseSlave("data source=test1.db", "data source=test2.db", "data source=test3.db", "data source=test4.db") //.UseSlaveWeight(10, 1, 1, 5) @@ -429,6 +487,62 @@ namespace base_entity BaseEntity.Initialization(fsql, () => _asyncUow.Value); #endregion + var dkdksql = fsql.Select().WithLock().From() + .InnerJoin((user, usergroup) => user.GroupId == usergroup.Id && usergroup.GroupName == "xxx") + .ToSql(); + + //Func getName1 = () => "xxx"; + //fsql.GlobalFilter.Apply("fil1", a => a.Nickname == getName1()); + //var gnsql2 = fsql.Select().ToSql(); + + using (var ctx9 = fsql.CreateDbContext()) + { + //var uset = ctx9.Set(); + //var item = new UserGroup + //{ + // GroupName = "group1" + //}; + //uset.Add(item); + //item.GroupName = "group1_2"; + //uset.Update(item); + var uset = ctx9.Set(); + var item = new User1 + { + Nickname = "nick1", + Username = "user1" + }; + uset.Add(item); + item.Nickname = "nick1_2"; + item.Username = "user1_2"; + uset.Update(item); + + ctx9.SaveChanges(); + } + + var strs = new string[] { "a", "b", "c" }; + var strssql1 = fsql.Select().Where(a => strs.Any(b => b == a.Nickname)).ToSql(); + var strssql2 = fsql.Select().Where(a => strs.Any(b => a.Nickname.Contains(b))).ToSql(); + var objs = new UserGroup[] { new UserGroup { GroupName = "a", Id = 1 }, new UserGroup { GroupName = "b", Id = 2 }, new UserGroup { GroupName = "c", Id = 3 } }; + var objssql1 = fsql.Select().Where(a => objs.Any(b => b.GroupName == a.Nickname && b.Id == a.GroupId)).ToSql(); + + + var tttsqlext01 = fsql.Select().ToSql(a => new + { + cou = SqlExt.Count(1).Over().PartitionBy(a.Id).ToValue(), + avg = SqlExt.Avg(1).Over().PartitionBy(a.Id).ToValue() + + }); + + + + //fsql.CodeFirst.SyncStructure(); + + fsql.CodeFirst.Entity(a => a.Property(p => p.code).IsRequired()); + var repo1010 = fsql.GetRepository(); + var jtitem = new JoinTest01 { id = 100 }; + repo1010.Attach(jtitem); + jtitem.name = "name01"; + repo1010.Update(jtitem); var sqlt0a1 = fsql.InsertOrUpdate<抖店实时销售金额表>() .SetSource(new 抖店实时销售金额表 diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs index d041fc58..6e3029fb 100644 --- a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs +++ b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs @@ -168,11 +168,8 @@ namespace FreeSql return entity; } if (table.Primarys.Where(a => a.Attribute.IsIdentity).Count() == table.Primarys.Length) - { Orm.ClearEntityPrimaryValueWithIdentity(EntityType, entity); - return await InsertAsync(entity, cancellationToken); - } - throw new Exception(DbContextStrings.CannotAdd_PrimaryKey_NotSet(Orm.GetEntityString(EntityType, entity))); + return await InsertAsync(entity, cancellationToken); } public virtual Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default) => UpdateAsync(new[] { entity }, cancellationToken); @@ -271,7 +268,8 @@ namespace FreeSql UpdateColumns = b.Item4, UpdateColumnsString = string.Join(",", b.Item4.OrderBy(c => c)) }).ToArray()); - var updateLogDict2 = updateLogDict.ToDictionary(a => a.Key, a => a.Value.ToDictionary(b => b.UpdateColumnsString, b => a.Value.Where(c => c.UpdateColumnsString == b.UpdateColumnsString).ToArray())); + var updateLogDict2 = updateLogDict.ToDictionary(a => a.Key, a => + a.Value.GroupBy(b => b.UpdateColumnsString).ToDictionary(b => b.Key, b => a.Value.Where(c => c.UpdateColumnsString == b.Key).ToArray())); foreach (var dl in updateLogDict2) { foreach (var dl2 in dl.Value) diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs index a29d24cf..4a9ac4e4 100644 --- a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs +++ b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs @@ -221,11 +221,8 @@ namespace FreeSql return entity; } if (table.Primarys.Where(a => a.Attribute.IsIdentity).Count() == table.Primarys.Length) - { Orm.ClearEntityPrimaryValueWithIdentity(EntityType, entity); - return Insert(entity); - } - throw new Exception(DbContextStrings.CannotAdd_PrimaryKey_NotSet(Orm.GetEntityString(EntityType, entity))); + return Insert(entity); } public virtual int Update(TEntity entity) => Update(new[] { entity }); @@ -322,7 +319,8 @@ namespace FreeSql UpdateColumns = b.Item4, UpdateColumnsString = string.Join(",", b.Item4.OrderBy(c => c)) }).ToArray()); - var updateLogDict2 = updateLogDict.ToDictionary(a => a.Key, a => a.Value.ToDictionary(b => b.UpdateColumnsString, b => a.Value.Where(c => c.UpdateColumnsString == b.UpdateColumnsString).ToArray())); + var updateLogDict2 = updateLogDict.ToDictionary(a => a.Key, a => + a.Value.GroupBy(b => b.UpdateColumnsString).ToDictionary(b => b.Key, b => a.Value.Where(c => c.UpdateColumnsString == b.Key).ToArray())); foreach (var dl in updateLogDict2) { foreach (var dl2 in dl.Value) diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/FreeSql.Extensions.AggregateRoot.csproj b/Extensions/FreeSql.Extensions.AggregateRoot/FreeSql.Extensions.AggregateRoot.csproj index 5cf8fedd..f374a87b 100644 --- a/Extensions/FreeSql.Extensions.AggregateRoot/FreeSql.Extensions.AggregateRoot.csproj +++ b/Extensions/FreeSql.Extensions.AggregateRoot/FreeSql.Extensions.AggregateRoot.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net60;net50;netcoreapp31;netcoreapp21;net45;net40 + netstandard2.0;net45;net40 true FreeSql;ncc;YeXiangQin FreeSql 扩展包,聚合根(实现室). @@ -18,7 +18,7 @@ true key.snk false - 1.0.3 + 1.0.6 @@ -26,7 +26,7 @@ - + diff --git a/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.csproj b/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.csproj index 642837cf..e5d57e87 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.csproj +++ b/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.csproj @@ -19,7 +19,7 @@ key.snk false latest - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Extensions/FreeSql.Extensions.JsonMap/FreeSql.Extensions.JsonMap.csproj b/Extensions/FreeSql.Extensions.JsonMap/FreeSql.Extensions.JsonMap.csproj index c6e9709e..07afeafb 100644 --- a/Extensions/FreeSql.Extensions.JsonMap/FreeSql.Extensions.JsonMap.csproj +++ b/Extensions/FreeSql.Extensions.JsonMap/FreeSql.Extensions.JsonMap.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj b/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj index b785b46d..fdad0bc7 100644 --- a/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj +++ b/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj @@ -15,7 +15,7 @@ $(AssemblyName) true true - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj b/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj index e5669971..c277521f 100644 --- a/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj +++ b/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Extensions/FreeSql.Generator/FreeSql.Generator.csproj b/Extensions/FreeSql.Generator/FreeSql.Generator.csproj index e0612441..4290b3f7 100644 --- a/Extensions/FreeSql.Generator/FreeSql.Generator.csproj +++ b/Extensions/FreeSql.Generator/FreeSql.Generator.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1;net60 + net60 true true true @@ -13,7 +13,7 @@ https://github.com/2881099/FreeSql https://github.com/2881099/FreeSql FreeSql DbFirst 实体生成器 - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/FreeSql.All/FreeSql.All.csproj b/FreeSql.All/FreeSql.All.csproj index cdff6623..e125f524 100644 --- a/FreeSql.All/FreeSql.All.csproj +++ b/FreeSql.All/FreeSql.All.csproj @@ -17,7 +17,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/FreeSql.DbContext/DbContext/DbContext.cs b/FreeSql.DbContext/DbContext/DbContext.cs index d76dc6fc..03323796 100644 --- a/FreeSql.DbContext/DbContext/DbContext.cs +++ b/FreeSql.DbContext/DbContext/DbContext.cs @@ -83,20 +83,29 @@ namespace FreeSql #region Set static ConcurrentDictionary> _dicGetDbSetProps = new ConcurrentDictionary>(); + static object _lockOnModelCreating = new object(); internal void InitPropSets() { var thisType = this.GetType(); - var dicval = _dicGetDbSetProps.GetOrAdd(thisType, tp => - NativeTuple.Create( - tp.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) - .Where(a => a.PropertyType.IsGenericType && - a.PropertyType == typeof(DbSet<>).MakeGenericType(a.PropertyType.GetGenericArguments()[0])).ToArray(), - false)); - if (dicval.Item2 == false) + var isOnModelCreating = false; + if (_dicGetDbSetProps.TryGetValue(thisType, out var dicval) == false) { - if (_dicGetDbSetProps.TryUpdate(thisType, NativeTuple.Create(dicval.Item1, true), dicval)) - OnModelCreating(OrmOriginal.CodeFirst); + lock (_lockOnModelCreating) + { + if (_dicGetDbSetProps.TryGetValue(thisType, out dicval) == false) + { + dicval = NativeTuple.Create( + thisType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) + .Where(a => a.PropertyType.IsGenericType && + a.PropertyType == typeof(DbSet<>).MakeGenericType(a.PropertyType.GetGenericArguments()[0])).ToArray(), + false); + _dicGetDbSetProps.TryAdd(thisType, dicval); + isOnModelCreating = true; + } + } } + if (isOnModelCreating) + OnModelCreating(OrmOriginal.CodeFirst); foreach (var prop in dicval.Item1) { diff --git a/FreeSql.DbContext/DbContext/DbContextAsync.cs b/FreeSql.DbContext/DbContext/DbContextAsync.cs index af4717b7..811ecfe7 100644 --- a/FreeSql.DbContext/DbContext/DbContextAsync.cs +++ b/FreeSql.DbContext/DbContext/DbContextAsync.cs @@ -98,58 +98,64 @@ namespace FreeSql } }; - while (_prevCommands.Any() || states.Any()) + try { - var info = _prevCommands.Any() ? _prevCommands.Dequeue() : null; - if (oldinfo == null) oldinfo = info; - var isLiveUpdate = false; - flagFuncUpdateLaststate = false; - - if (_prevCommands.Any() == false && states.Any() || - info != null && oldinfo.changeType != info.changeType || - info != null && oldinfo.stateType != info.stateType || - info != null && oldinfo.entityType != info.entityType) + while (_prevCommands.Any() || states.Any()) { + var info = _prevCommands.Any() ? _prevCommands.Dequeue() : null; + if (oldinfo == null) oldinfo = info; + var isLiveUpdate = false; + flagFuncUpdateLaststate = false; - if (info != null && oldinfo.changeType == info.changeType && oldinfo.stateType == info.stateType && oldinfo.entityType == info.entityType) + if (_prevCommands.Any() == false && states.Any() || + info != null && oldinfo.changeType != info.changeType || + info != null && oldinfo.stateType != info.stateType || + info != null && oldinfo.entityType != info.entityType) + { + + if (info != null && oldinfo.changeType == info.changeType && oldinfo.stateType == info.stateType && oldinfo.entityType == info.entityType) + { + //最后一个,合起来发送 + states.Add(info.state); + info = null; + } + + switch (oldinfo.changeType) + { + case EntityChangeType.Insert: + await funcInsert(); + break; + case EntityChangeType.Delete: + await funcDelete(); + break; + } + isLiveUpdate = true; + } + + if (isLiveUpdate || oldinfo.changeType == EntityChangeType.Update) + { + if (states.Any()) + { + await funcUpdate(isLiveUpdate); + if (info?.changeType == EntityChangeType.Update) + flagFuncUpdateLaststate = true; + } + } + + if (info != null) { - //最后一个,合起来发送 states.Add(info.state); - info = null; + oldinfo = info; + + if (flagFuncUpdateLaststate && oldinfo.changeType == EntityChangeType.Update) //马上与上个元素比较 + await funcUpdate(isLiveUpdate); } - - switch (oldinfo.changeType) - { - case EntityChangeType.Insert: - await funcInsert(); - break; - case EntityChangeType.Delete: - await funcDelete(); - break; - } - isLiveUpdate = true; - } - - if (isLiveUpdate || oldinfo.changeType == EntityChangeType.Update) - { - if (states.Any()) - { - await funcUpdate(isLiveUpdate); - if (info?.changeType == EntityChangeType.Update) - flagFuncUpdateLaststate = true; - } - } - - if (info != null) - { - states.Add(info.state); - oldinfo = info; - - if (flagFuncUpdateLaststate && oldinfo.changeType == EntityChangeType.Update) //马上与上个元素比较 - await funcUpdate(isLiveUpdate); } } - isFlushCommanding = false; + finally + { + isFlushCommanding = false; + } } } } diff --git a/FreeSql.DbContext/DbContext/DbContextSync.cs b/FreeSql.DbContext/DbContext/DbContextSync.cs index e5aad882..7b4fde35 100644 --- a/FreeSql.DbContext/DbContext/DbContextSync.cs +++ b/FreeSql.DbContext/DbContext/DbContextSync.cs @@ -113,58 +113,64 @@ namespace FreeSql } }; - while (_prevCommands.Any() || states.Any()) + try { - var info = _prevCommands.Any() ? _prevCommands.Dequeue() : null; - if (oldinfo == null) oldinfo = info; - var isLiveUpdate = false; - flagFuncUpdateLaststate = false; - - if (_prevCommands.Any() == false && states.Any() || - info != null && oldinfo.changeType != info.changeType || - info != null && oldinfo.stateType != info.stateType || - info != null && oldinfo.entityType != info.entityType) + while (_prevCommands.Any() || states.Any()) { + var info = _prevCommands.Any() ? _prevCommands.Dequeue() : null; + if (oldinfo == null) oldinfo = info; + var isLiveUpdate = false; + flagFuncUpdateLaststate = false; - if (info != null && oldinfo.changeType == info.changeType && oldinfo.stateType == info.stateType && oldinfo.entityType == info.entityType) + if (_prevCommands.Any() == false && states.Any() || + info != null && oldinfo.changeType != info.changeType || + info != null && oldinfo.stateType != info.stateType || + info != null && oldinfo.entityType != info.entityType) + { + + if (info != null && oldinfo.changeType == info.changeType && oldinfo.stateType == info.stateType && oldinfo.entityType == info.entityType) + { + //最后一个,合起来发送 + states.Add(info.state); + info = null; + } + + switch (oldinfo.changeType) + { + case EntityChangeType.Insert: + funcInsert(); + break; + case EntityChangeType.Delete: + funcDelete(); + break; + } + isLiveUpdate = true; + } + + if (isLiveUpdate || oldinfo.changeType == EntityChangeType.Update) + { + if (states.Any()) + { + funcUpdate(isLiveUpdate); + if (info?.changeType == EntityChangeType.Update) + flagFuncUpdateLaststate = true; + } + } + + if (info != null) { - //最后一个,合起来发送 states.Add(info.state); - info = null; + oldinfo = info; + + if (flagFuncUpdateLaststate && oldinfo.changeType == EntityChangeType.Update) //马上与上个元素比较 + funcUpdate(isLiveUpdate); } - - switch (oldinfo.changeType) - { - case EntityChangeType.Insert: - funcInsert(); - break; - case EntityChangeType.Delete: - funcDelete(); - break; - } - isLiveUpdate = true; - } - - if (isLiveUpdate || oldinfo.changeType == EntityChangeType.Update) - { - if (states.Any()) - { - funcUpdate(isLiveUpdate); - if (info?.changeType == EntityChangeType.Update) - flagFuncUpdateLaststate = true; - } - } - - if (info != null) - { - states.Add(info.state); - oldinfo = info; - - if (flagFuncUpdateLaststate && oldinfo.changeType == EntityChangeType.Update) //马上与上个元素比较 - funcUpdate(isLiveUpdate); } } - isFlushCommanding = false; + finally + { + isFlushCommanding = false; + } } } } diff --git a/FreeSql.DbContext/DbSet/DbSet.cs b/FreeSql.DbContext/DbSet/DbSet.cs index 6b6f617d..59f5a5cc 100644 --- a/FreeSql.DbContext/DbSet/DbSet.cs +++ b/FreeSql.DbContext/DbSet/DbSet.cs @@ -29,7 +29,7 @@ namespace FreeSql public abstract partial class DbSet : IDbSet where TEntity : class { internal DbContext _db { get; set; } - internal IUnitOfWork _uow { get; set; } + internal virtual IUnitOfWork _uow { get; set; } protected virtual ISelect OrmSelect(object dywhere) { @@ -163,7 +163,7 @@ namespace FreeSql return this; } - Dictionary> _dicDbSetObjects = new Dictionary>(); + internal Dictionary> _dicDbSetObjects = new Dictionary>(); DbSet GetDbSetObject(Type et) { if (_dicDbSetObjects.TryGetValue(et, out var tryds)) return tryds; diff --git a/FreeSql.DbContext/FreeSql.DbContext.csproj b/FreeSql.DbContext/FreeSql.DbContext.csproj index 0ef01f73..c5d9402a 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.csproj +++ b/FreeSql.DbContext/FreeSql.DbContext.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net60;net50;netcoreapp31;netcoreapp21;net45;net40 + netstandard2.0;net70;net60;net50;netcoreapp31;netcoreapp21;net45;net40 true FreeSql;ncc;YeXiangQin FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Odbc, 达梦, 人大金仓, 神舟通用, 南大通用, 翰高, And Access @@ -17,7 +17,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 @@ -33,7 +33,7 @@ net40 - + netcoreapp @@ -41,6 +41,9 @@ + + + diff --git a/FreeSql.DbContext/Repository/ContextSet/RepositoryDbSet.cs b/FreeSql.DbContext/Repository/ContextSet/RepositoryDbSet.cs index ad55f84f..1a71db07 100644 --- a/FreeSql.DbContext/Repository/ContextSet/RepositoryDbSet.cs +++ b/FreeSql.DbContext/Repository/ContextSet/RepositoryDbSet.cs @@ -16,6 +16,18 @@ namespace FreeSql _repo = repo; } + IUnitOfWork _uowPriv; + internal override IUnitOfWork _uow + { + get => _uowPriv; + set + { + _uowPriv = value; + foreach (var dbset in _dicDbSetObjects.Values) //配合 UnitOfWorkManager + dbset._uow = _uowPriv; + } + } + protected override ISelect OrmSelect(object dywhere) { var select = base.OrmSelect(dywhere).AsTable(_repo.AsTableSelectValueInternal); diff --git a/FreeSql.DbContext/Repository/Repository/BaseRepository.cs b/FreeSql.DbContext/Repository/Repository/BaseRepository.cs index 81bf8e2a..76857637 100644 --- a/FreeSql.DbContext/Repository/Repository/BaseRepository.cs +++ b/FreeSql.DbContext/Repository/Repository/BaseRepository.cs @@ -181,10 +181,11 @@ namespace FreeSql UnitOfWork.Dispose(); UnitOfWork = olduow; } - return affrows + _db.SaveChanges(); + _db.SaveChanges(); + return affrows; } - var affrows2 = _dbset.EndEdit(data); - return affrows2 + _db.SaveChanges(); + _db.SaveChanges(); + return _dbset.EndEdit(data); } } diff --git a/FreeSql.Repository/FreeSql.Repository.csproj b/FreeSql.Repository/FreeSql.Repository.csproj index 11150948..70ea8d90 100644 --- a/FreeSql.Repository/FreeSql.Repository.csproj +++ b/FreeSql.Repository/FreeSql.Repository.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net60;net50;netcoreapp31;netcoreapp21;net45;net40 + netstandard2.0;net70;net60;net50;netcoreapp31;netcoreapp21;net45;net40 FreeSql;ncc;YeXiangQin FreeSql Implementation of General Repository, Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/Access, and read/write separation、and split table. https://github.com/2881099/FreeSql/wiki/Repository @@ -17,7 +17,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Custom/FreeSql.Tests.Provider.Custom.csproj b/FreeSql.Tests/FreeSql.Tests.Provider.Custom/FreeSql.Tests.Provider.Custom.csproj index a78f9598..da2fecbc 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Custom/FreeSql.Tests.Provider.Custom.csproj +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Custom/FreeSql.Tests.Provider.Custom.csproj @@ -16,7 +16,7 @@ - + all diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index f6ea7ea0..558be915 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -2028,6 +2028,11 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT TOP 10 b.[Title] Assert.Equal("SELECT TOP 1 a.[id], a.[name] FROM [ToUpd1Pk] a With(NoLock)", sql); orm.Select().WithLock().Limit(1).ToList(); + sql = orm.Select().WithLock().WithIndex("idx_01").Limit(1).ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT TOP 1 a.[id], a.[name] FROM [ToUpd1Pk] a With(index=idx_01, NoLock)", sql); + sql = orm.Select().WithIndex("idx_01").WithLock().Limit(1).ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT TOP 1 a.[id], a.[name] FROM [ToUpd1Pk] a With(NoLock, index=idx_01)", sql); + sql = orm.Select().WithLock(SqlServerLock.NoLock).Limit(1).ToSql().Replace("\r\n", ""); Assert.Equal("SELECT TOP 1 a.[id], a.[name] FROM [ToUpd1Pk] a With(NoLock)", sql); orm.Select().WithLock(SqlServerLock.NoLock).Limit(1).ToList(); @@ -2039,6 +2044,11 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT TOP 10 b.[Title] sql = orm.Select().WithLock(SqlServerLock.UpdLock | SqlServerLock.RowLock | SqlServerLock.NoWait).Limit(1).ToSql().Replace("\r\n", ""); Assert.Equal("SELECT TOP 1 a.[id], a.[name] FROM [ToUpd1Pk] a With(UpdLock, RowLock, NoWait)", sql); orm.Select().WithLock(SqlServerLock.UpdLock | SqlServerLock.RowLock | SqlServerLock.NoWait).Limit(1).ToList(); + + sql = orm.Select().WithLock(SqlServerLock.UpdLock | SqlServerLock.RowLock | SqlServerLock.NoWait).WithIndex("idx_01").Limit(1).ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT TOP 1 a.[id], a.[name] FROM [ToUpd1Pk] a With(index=idx_01, UpdLock, RowLock, NoWait)", sql); + sql = orm.Select().WithIndex("idx_01").WithLock(SqlServerLock.UpdLock | SqlServerLock.RowLock | SqlServerLock.NoWait).Limit(1).ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT TOP 1 a.[id], a.[name] FROM [ToUpd1Pk] a With(UpdLock, RowLock, NoWait, index=idx_01)", sql); }); var sql2 = orm.Select() @@ -2049,6 +2059,46 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT TOP 10 b.[Title] FROM [tb_topic22] a With(NoLock) INNER JOIN [TestTypeInfo] a__Type With(NoLock) ON a__Type.[Guid] = a.[Id]", sql2); + + sql2 = orm.Select() + .WithSql("select * from topic with (nolock)") + .InnerJoin(a => a.Type.Guid == a.Id) + .WithLock() + .ToSql(); + Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a__Type.[Guid], a__Type.[ParentId], a__Type.[Name], a.[Title], a.[CreateTime] +FROM ( select * from topic with (nolock) ) a +INNER JOIN [TestTypeInfo] a__Type With(NoLock) ON a__Type.[Guid] = a.[Id]", sql2); + + + sql2 = orm.Select() + .InnerJoin(a => a.Type.Guid == a.Id) + .WithLock() + .ToSql(); + Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a__Type.[Guid], a__Type.[ParentId], a__Type.[Name], a.[Title], a.[CreateTime] +FROM [tb_topic22] a With(NoLock) +INNER JOIN [TestTypeInfo] a__Type With(NoLock) ON a__Type.[Guid] = a.[Id]", sql2); + + sql2 = orm.Select() + .InnerJoin(a => a.Type.Guid == a.Id) + .WithLock() + .WithIndex("idx_02") + .ToSql(); + Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a__Type.[Guid], a__Type.[ParentId], a__Type.[Name], a.[Title], a.[CreateTime] +FROM [tb_topic22] a With(index=idx_02, NoLock) +INNER JOIN [TestTypeInfo] a__Type With(NoLock) ON a__Type.[Guid] = a.[Id]", sql2); + sql2 = orm.Select() + .InnerJoin(a => a.Type.Guid == a.Id) + .WithLock() + .WithIndex("idx_02", new Dictionary + { + [typeof(TestTypeInfo)] = "idx_03" + }) + .ToSql(); + Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a__Type.[Guid], a__Type.[ParentId], a__Type.[Name], a.[Title], a.[CreateTime] +FROM [tb_topic22] a With(index=idx_02, NoLock) +INNER JOIN [TestTypeInfo] a__Type With(index=idx_03, NoLock) ON a__Type.[Guid] = a.[Id]", sql2); + + sql2 = orm.Select() .InnerJoin(a => a.Type.Guid == a.Id) .WithLock(SqlServerLock.NoLock, new Dictionary diff --git a/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs index c6cad284..e9b1a489 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs @@ -82,7 +82,7 @@ namespace FreeSql /// count() over(order by ...) /// /// - public static ISqlOver Count() => Over("count()"); + public static ISqlOver Count(object column) => Over($"count({expContext.Value.ParsedContent["column"]})"); /// /// sum(..) over(order by ...) /// @@ -93,7 +93,7 @@ namespace FreeSql /// avg(..) over(order by ...) /// /// - public static ISqlOver Avg() => Over($"avg({expContext.Value.ParsedContent["column"]})"); + public static ISqlOver Avg(object column) => Over($"avg({expContext.Value.ParsedContent["column"]})"); /// /// max(..) over(order by ...) /// diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index ff7286c1..cbb5208c 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -876,6 +876,7 @@ SELECT "); /// public static InsertDictImpl InsertDict(this IFreeSql freesql, Dictionary source) { + LocalReplaceDictDBNullValue(source); var insertDict = new InsertDictImpl(freesql); insertDict._insertProvider.AppendData(source); return insertDict; @@ -887,10 +888,21 @@ SELECT "); /// public static InsertDictImpl InsertDict(this IFreeSql freesql, IEnumerable> source) { + if (source?.Any() == true) foreach (var dict in source) LocalReplaceDictDBNullValue(dict); var insertDict = new InsertDictImpl(freesql); insertDict._insertProvider.AppendData(source); return insertDict; } + static void LocalReplaceDictDBNullValue(Dictionary dict) + { + if (dict == null) return; + var keys = dict.Keys; + foreach (var key in keys) + { + var val = dict[key]; + if (val == DBNull.Value) dict[key] = null; + } + } /// /// 更新数据字典 Dictionary<string, object> /// @@ -898,6 +910,7 @@ SELECT "); /// public static UpdateDictImpl UpdateDict(this IFreeSql freesql, Dictionary source) { + LocalReplaceDictDBNullValue(source); var updateDict = new UpdateDictImpl(freesql); updateDict._updateProvider.SetSource(source); return updateDict; @@ -909,6 +922,7 @@ SELECT "); /// public static UpdateDictImpl UpdateDict(this IFreeSql freesql, IEnumerable> source) { + if (source?.Any() == true) foreach (var dict in source) LocalReplaceDictDBNullValue(dict); var updateDict = new UpdateDictImpl(freesql); updateDict._updateProvider.SetSource(source); return updateDict; @@ -929,12 +943,14 @@ SELECT "); /// public static InsertOrUpdateDictImpl InsertOrUpdateDict(this IFreeSql freesql, Dictionary source) { + LocalReplaceDictDBNullValue(source); var insertOrUpdateDict = new InsertOrUpdateDictImpl(freesql); insertOrUpdateDict._insertOrUpdateProvider.SetSource(source); return insertOrUpdateDict; } public static InsertOrUpdateDictImpl InsertOrUpdateDict(this IFreeSql freesql, IEnumerable> source) { + if (source?.Any() == true) foreach (var dict in source) LocalReplaceDictDBNullValue(dict); var insertOrUpdateDict = new InsertOrUpdateDictImpl(freesql); insertOrUpdateDict._insertOrUpdateProvider.SetSource(source); return insertOrUpdateDict; @@ -946,6 +962,7 @@ SELECT "); /// public static DeleteDictImpl DeleteDict(this IFreeSql freesql, Dictionary source) { + LocalReplaceDictDBNullValue(source); var deleteDict = new DeleteDictImpl(freesql); UpdateProvider>.GetDictionaryTableInfo(source, deleteDict._deleteProvider._orm, ref deleteDict._deleteProvider._table); var primarys = UpdateDictImpl.GetPrimarys(deleteDict._deleteProvider._table, source.Keys.ToArray()); @@ -959,6 +976,7 @@ SELECT "); /// public static DeleteDictImpl DeleteDict(this IFreeSql freesql, IEnumerable> source) { + if (source?.Any() == true) foreach (var dict in source) LocalReplaceDictDBNullValue(dict); DeleteDictImpl deleteDict = null; if (source.Select(a => string.Join(",", a.Keys)).Distinct().Count() == 1) { diff --git a/FreeSql/FreeSql.csproj b/FreeSql/FreeSql.csproj index e855436a..a1d89c2a 100644 --- a/FreeSql/FreeSql.csproj +++ b/FreeSql/FreeSql.csproj @@ -17,7 +17,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 74b1a582..302c8ee7 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1201,7 +1201,7 @@ - + count() over(order by ...) @@ -1214,7 +1214,7 @@ - + avg(..) over(order by ...) diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 1dd8ff87..671a7e7c 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -1019,6 +1019,9 @@ namespace FreeSql.Internal } else if (exp3.Arguments[a].IsParameter()) exp3InvokeParams[a] = exp3.Arguments[a].Type.CreateInstanceGetDefaultValue(); + + else if (Utils.dicExecuteArrayRowReadClassOrTuple.ContainsKey(exp3.Arguments[a].Type.NullableTypeOrThis()) == false) + exp3InvokeParams[a] = exp3.Arguments[a].Type.CreateInstanceGetDefaultValue(); else { var exp3CsValue = eccContent.StartsWith("N'") ? @@ -1045,8 +1048,8 @@ namespace FreeSql.Internal typeof(ThreadLocal).GetProperty("Value").SetValue(eccField.GetValue(null), ecc, null); try { - var sqlRet = exp3.Method.Invoke(null, exp3InvokeParams); - if (string.IsNullOrEmpty(ecc.Result) && sqlRet is string) ecc.Result = string.Concat(sqlRet); + var invokeReturn = exp3.Method.Invoke(null, exp3InvokeParams); + if (string.IsNullOrEmpty(ecc.Result) && invokeReturn is string) ecc.Result = string.Concat(invokeReturn); if (string.IsNullOrEmpty(ecc.Result) && exp3MethodParams.Any()) ecc.Result = ecc.ParsedContent[exp3MethodParams[0].Name]; if (ecc.UserParameters?.Any() == true) tsc.dbParams?.AddRange(ecc.UserParameters); return ecc.Result; @@ -1695,7 +1698,7 @@ namespace FreeSql.Internal if (oper2.NodeType == ExpressionType.Parameter) { var oper2Parm = oper2 as ParameterExpression; - expStack.Push(exp2.Type.IsAbstract || exp2.Type.IsInterface ? oper2Parm : Expression.Parameter(exp2.Type, oper2Parm.Name)); + expStack.Push(exp2.Type.IsAbstract || exp2.Type.IsInterface || exp2.Type.IsAssignableFrom(oper2Parm.Type) ? oper2Parm : Expression.Parameter(exp2.Type, oper2Parm.Name)); } else expStack.Push(oper2); @@ -2283,6 +2286,12 @@ namespace FreeSql.Internal return Expression.Property(_replaceExp, node.Member.Name); return base.VisitMember(node); } + protected override Expression VisitParameter(ParameterExpression node) + { + if (node == oldParameter) + return _replaceExp; + return base.VisitParameter(node); + } } public class ReplaceHzyTupleToMultiParam : ExpressionVisitor @@ -2502,7 +2511,7 @@ namespace FreeSql.Internal if (whereGlobalFilter.Any()) select._whereGlobalFilter.AddRange(whereGlobalFilter); } } - while (true) + while (exp3Stack.Any()) { var exp4 = exp3Stack.Pop(); if (exp4.NodeType == ExpressionType.MemberAccess) @@ -2546,8 +2555,15 @@ namespace FreeSql.Internal var callExp = exp4 as MethodCallExpression; switch (callExp.Method.Name) { + case "Exists": case "Any": - if (callExp.Arguments.Count == 2) + if (callExp.Method.Name == "Exists" && callExp.Arguments.Count == 1 && callExp.Type.IsGenericType && callExp.Type.GetGenericTypeDefinition().IsAssignableFrom(typeof(IList<>))) + { + select._tables[0].Parameter = (callExp.Arguments[0] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select.InternalWhere(callExp.Arguments[0]); + } + if (callExp.Method.Name == "Any" && callExp.Arguments.Count == 2) { select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 40fa38a9..a59076bf 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -615,18 +615,21 @@ namespace FreeSql.Internal.CommonProvider { if (exp == null) return this as TSelect; _tables[0].Parameter = exp.Parameters[0]; + if (_tables.Count > 1 && _tables[1].Table.Type == typeof(T2)) _tables[1].Parameter = exp.Parameters[1]; return this.InternalJoin(exp?.Body, SelectTableInfoType.LeftJoin); } public TSelect InnerJoin(Expression> exp) { if (exp == null) return this as TSelect; _tables[0].Parameter = exp.Parameters[0]; + if (_tables.Count > 1 && _tables[1].Table.Type == typeof(T2)) _tables[1].Parameter = exp.Parameters[1]; return this.InternalJoin(exp?.Body, SelectTableInfoType.InnerJoin); } public TSelect RightJoin(Expression> exp) { if (exp == null) return this as TSelect; _tables[0].Parameter = exp.Parameters[0]; + if (_tables.Count > 1 && _tables[1].Table.Type == typeof(T2)) _tables[1].Parameter = exp.Parameters[1]; return this.InternalJoin(exp?.Body, SelectTableInfoType.RightJoin); } diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs index 0f4e3147..55ea7502 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs @@ -483,7 +483,11 @@ namespace FreeSql.Internal.CommonProvider var curPropName = parentNameSplits[k]; if (curTb.Table.Properties.TryGetValue(parentNameSplits[k], out var tryprop) == false) { - k++; + if (++k >= parentNameSplits.Length) + { + iscontinue = true; + break; + } curPropName = $"{curPropName}__{parentNameSplits[k]}"; if (curTb.Table.Properties.TryGetValue(parentNameSplits[k], out tryprop) == false) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index 87e67899..8f8d1400 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -1336,25 +1336,28 @@ namespace FreeSql.Internal.CommonProvider }).ToArray(); var arrExp = Expression.NewArrayInit(tbref.RefColumns[0].CsType, listKeys.Where(a => a != null).SelectMany(a => a).Distinct() .Select(a => Expression.Constant(Utils.GetDataReaderValue(tbref.RefColumns[0].CsType, a), tbref.RefColumns[0].CsType)).ToArray()); - var otmExpParm1 = Expression.Parameter(typeof(TNavigate), "a"); - var containsMethod = _dicTypeMethod.GetOrAdd(tbref.RefColumns[0].CsType, et => new ConcurrentDictionary()).GetOrAdd("Contains", mn => - typeof(Enumerable).GetMethods().Where(a => a.Name == mn).First()).MakeGenericMethod(tbref.RefColumns[0].CsType); - var refCol = Expression.MakeMemberAccess(otmExpParm1, tbref2.Properties[tbref.RefColumns[0].CsName]); - subSelect.Where(Expression.Lambda>( - Expression.Call(null, containsMethod, arrExp, refCol), otmExpParm1)); - - if (isAsync) + if (arrExp.Expressions.Any()) { + var otmExpParm1 = Expression.Parameter(typeof(TNavigate), "a"); + var containsMethod = _dicTypeMethod.GetOrAdd(tbref.RefColumns[0].CsType, et => new ConcurrentDictionary()).GetOrAdd("Contains", mn => + typeof(Enumerable).GetMethods().Where(a => a.Name == mn).First()).MakeGenericMethod(tbref.RefColumns[0].CsType); + var refCol = Expression.MakeMemberAccess(otmExpParm1, tbref2.Properties[tbref.RefColumns[0].CsName]); + subSelect.Where(Expression.Lambda>( + Expression.Call(null, containsMethod, arrExp, refCol), otmExpParm1)); + + if (isAsync) + { #if net40 #else - if (selectExp == null) subList = await subSelect.ToListAsync(true, cancellationToken); - else subList = await subSelect.ToListAsync(selectExp, cancellationToken); + if (selectExp == null) subList = await subSelect.ToListAsync(true, cancellationToken); + else subList = await subSelect.ToListAsync(selectExp, cancellationToken); #endif - } - else - { - if (selectExp == null) subList = subSelect.ToList(true); - else subList = subSelect.ToList(selectExp); + } + else + { + if (selectExp == null) subList = subSelect.ToList(true); + else subList = subSelect.ToList(selectExp); + } } if (subList.Any() == false) @@ -1536,6 +1539,17 @@ namespace FreeSql.Internal.CommonProvider var bindings = new List(); if (imni.IsOutputPrimary) bindings.AddRange(imni.Table.Primarys.Select(a => Expression.Bind(imni.Table.Properties[a.CsName], Expression.MakeMemberAccess(imni.CurrentExpression, imni.Table.Properties[a.CsName])))); if (imni.Childs.Any()) bindings.AddRange(imni.Childs.Select(a => Expression.Bind(imni.Table.Properties[a.Key], GetIncludeManyNewInitExpression(a.Value)))); + var pgarrayToManys = imni.Table.GetAllTableRef().Select(tr => + { + if (tr.Value.RefType != TableRefType.PgArrayToMany) return null; + var reftb = _orm.CodeFirst.GetTableByEntity(tr.Value.RefEntityType); + if (tr.Value.RefColumns[0] == reftb.Primarys[0]) + { + bindings.Add(Expression.Bind(imni.Table.Properties[tr.Value.Columns[0].CsName], Expression.MakeMemberAccess(imni.CurrentExpression, imni.Table.Properties[tr.Value.Columns[0].CsName]))); + return tr.Key; + } + return null; + }).ToList(); return Expression.MemberInit(imni.Table.Type.InternalNewExpression(), bindings); } diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 1edaf42c..023e8c31 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -2458,6 +2458,7 @@ namespace FreeSql.Internal } if (sidx < sql.Length && sql[sidx] == '\'') { + sidx++; startLength += 2; continue; } diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs index 816e2b0f..4a40da88 100644 --- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs +++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs @@ -51,7 +51,7 @@ namespace FreeSql.ClickHouse } public override DbParameter[] GetDbParamtersByObject(string sql, object obj) => - Utils.GetDbParamtersByObject(sql, obj, "?", (name, type, value) => + Utils.GetDbParamtersByObject(sql, obj, "@", (name, type, value) => { if (value is string str) value = str?.Replace("\t", "\\t") @@ -59,7 +59,7 @@ namespace FreeSql.ClickHouse .Replace("\n", "\\n") .Replace("\r", "\\r") .Replace("/", "\\/"); - DbParameter ret = new ClickHouseDbParameter { ParameterName = $"?{name}", Value = value }; + DbParameter ret = new ClickHouseDbParameter { ParameterName = $"@{name}", Value = value }; var tp = _orm.CodeFirst.GetDbInfo(type)?.type; if (tp != null) ret.DbType = (DbType)tp.Value; diff --git a/Providers/FreeSql.Provider.ClickHouse/FreeSql.Provider.ClickHouse.csproj b/Providers/FreeSql.Provider.ClickHouse/FreeSql.Provider.ClickHouse.csproj index 4f802a9c..bb102b91 100644 --- a/Providers/FreeSql.Provider.ClickHouse/FreeSql.Provider.ClickHouse.csproj +++ b/Providers/FreeSql.Provider.ClickHouse/FreeSql.Provider.ClickHouse.csproj @@ -19,7 +19,7 @@ False key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.Custom/FreeSql.Provider.Custom.csproj b/Providers/FreeSql.Provider.Custom/FreeSql.Provider.Custom.csproj index 0d9c4080..61f41945 100644 --- a/Providers/FreeSql.Provider.Custom/FreeSql.Provider.Custom.csproj +++ b/Providers/FreeSql.Provider.Custom/FreeSql.Provider.Custom.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlCodeFirst.cs b/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlCodeFirst.cs index 8cce49e2..bee6e372 100644 --- a/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlCodeFirst.cs +++ b/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlCodeFirst.cs @@ -200,7 +200,7 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); if (istmpatler == false) { - var existsPrimary = LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.key_column_usage where table_schema={0} and table_name={1} and constraint_name = 'PRIMARY' limit 1", tbname)); + var existsPrimary = LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.columns where table_schema={0} and table_name={1} and column_key = 'PRI' limit 1", tbname)); foreach (var tbcol in tb.ColumnsByPosition) { var isIdentityChanged = tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1; diff --git a/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerSelect.cs b/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerSelect.cs index bc4bf5ed..9d07dd2d 100644 --- a/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerSelect.cs +++ b/Providers/FreeSql.Provider.Custom/SqlServer/Curd/CustomSqlServerSelect.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.Custom.SqlServer { @@ -44,7 +45,7 @@ namespace FreeSql.Custom.SqlServer if (_limit > 0 || _skip > 0) { - if (string.IsNullOrEmpty(_orderby)) + if (string.IsNullOrEmpty(_orderby) && (_limit > 1 || _skip > 0)) //TOP 1 不自动 order by { if (string.IsNullOrEmpty(_groupby)) { @@ -63,13 +64,15 @@ namespace FreeSql.Custom.SqlServer var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); for (var a = 0; a < tbsfrom.Length; a++) { - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); + var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(alias); if (tbsjoin.Length > 0) { //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias); + alias = LocalGetTableAlias(tbsfrom[b].Table.Type, tbUnion[tbsfrom[b].Table.Type], tbsfrom[b].Alias, _aliasRule); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(alias); if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); else @@ -110,7 +113,8 @@ namespace FreeSql.Custom.SqlServer sb.Append(" \r\nRIGHT JOIN "); break; } - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tb.Table.Type, tb.Alias) ?? tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + var alias = LocalGetTableAlias(tb.Table.Type, tbUnion[tb.Table.Type], tb.Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND ").Append(tb.Cascade); if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } @@ -165,7 +169,7 @@ namespace FreeSql.Custom.SqlServer if (tbUnionsIdx > 0) sb.Append("\r\n \r\nUNION ALL\r\n \r\n"); if (tbUnionsGt0) sb.Append(_select).Append(" * from ("); var tbUnion = tbUnions[tbUnionsIdx]; - + var sbnav = new StringBuilder(); sb.Append(_select); if (_distinct) sb.Append("DISTINCT "); @@ -176,13 +180,15 @@ namespace FreeSql.Custom.SqlServer var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); for (var a = 0; a < tbsfrom.Length; a++) { - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); + var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(alias); if (tbsjoin.Length > 0) { //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias); + alias = LocalGetTableAlias(tbsfrom[b].Table.Type, tbUnion[tbsfrom[b].Table.Type], tbsfrom[b].Alias, _aliasRule); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(alias); if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); else @@ -223,7 +229,8 @@ namespace FreeSql.Custom.SqlServer sb.Append(" \r\nRIGHT JOIN "); break; } - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tb.Table.Type, tb.Alias) ?? tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + var alias = LocalGetTableAlias(tb.Table.Type, tbUnion[tb.Table.Type], tb.Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND ").Append(tb.Cascade); if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } @@ -271,6 +278,17 @@ namespace FreeSql.Custom.SqlServer } #endregion + static string LocalGetTableAlias(Type entityType, string tbname, string alias, Func aliasRule) + { + if (aliasRule != null) + { + alias = aliasRule(entityType, alias); + if (tbname.IndexOf(' ') != -1) //还可以这样:select.AsTable((a, b) => "(select * from tb_topic where clicks > 10)").Page(1, 10).ToList() + alias = Regex.Replace(alias, @" With\([^\)]+\)", ""); //替换 WithLock、WithIndex + } + return alias; + } + public CustomSqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override ISelect From(Expression, T2, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcSqlServerSelect(_orm, _commonUtils, _commonExpression, null); CustomSqlServerSelect.CopyData(this, ret, exp?.Parameters); return ret; } public override ISelect From(Expression, T2, T3, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcSqlServerSelect(_orm, _commonUtils, _commonExpression, null); CustomSqlServerSelect.CopyData(this, ret, exp?.Parameters); return ret; } diff --git a/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj b/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj index 0bb8ebf8..ecbef1e4 100644 --- a/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj +++ b/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj @@ -15,7 +15,7 @@ $(AssemblyName) true true - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.Firebird/FirebirdAdo/FirebirdConnectionPool.cs b/Providers/FreeSql.Provider.Firebird/FirebirdAdo/FirebirdConnectionPool.cs index 35ad5ed2..407b6175 100644 --- a/Providers/FreeSql.Provider.Firebird/FirebirdAdo/FirebirdConnectionPool.cs +++ b/Providers/FreeSql.Provider.Firebird/FirebirdAdo/FirebirdConnectionPool.cs @@ -64,7 +64,7 @@ namespace FreeSql.Firebird { _connectionString = value ?? ""; - var minPoolSize = 0; + var minPoolSize = 1; var pattern = @"Min\s*pool\s*size\s*=\s*(\d+)"; var m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase); if (m.Success) diff --git a/Providers/FreeSql.Provider.Firebird/FirebirdCodeFirst.cs b/Providers/FreeSql.Provider.Firebird/FirebirdCodeFirst.cs index 3c90965f..0fbf6dd2 100644 --- a/Providers/FreeSql.Provider.Firebird/FirebirdCodeFirst.cs +++ b/Providers/FreeSql.Provider.Firebird/FirebirdCodeFirst.cs @@ -33,7 +33,7 @@ namespace FreeSql.Firebird { typeof(double).FullName, CsToDb.New(FbDbType.Double, "double precision","double precision NOT NULL", false, false, 0) },{ typeof(double?).FullName, CsToDb.New(FbDbType.Double, "double precision", "double precision", false, true, null) }, { typeof(decimal).FullName, CsToDb.New(FbDbType.Decimal, "decimal", "decimal(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, CsToDb.New(FbDbType.Numeric, "decimal", "decimal(10,2)", false, true, null) }, - { typeof(string).FullName, CsToDb.New(FbDbType.VarChar, "varchar", "varchar(255)", false, null, "") }, + { typeof(string).FullName, CsToDb.New(FbDbType.VarChar, "varchar", "varchar(200)", false, null, "") }, { typeof(TimeSpan).FullName, CsToDb.New(FbDbType.Time, "time","time NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, CsToDb.New(FbDbType.Time, "time", "time",false, true, null) }, { typeof(DateTime).FullName, CsToDb.New(FbDbType.TimeStamp, "timestamp", "timestamp NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, CsToDb.New(FbDbType.TimeStamp, "timestamp", "timestamp", false, true, null) }, @@ -136,7 +136,7 @@ namespace FreeSql.Firebird { sb.Append("CREATE "); if (uk.IsUnique) sb.Append("UNIQUE "); - sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(uk.Name)).Append(" ON ").Append(createTableName).Append("("); + sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(ReplaceIndexName(uk.Name, tbname))).Append(" ON ").Append(createTableName).Append("("); foreach (var tbcol in uk.Columns) { sb.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name)); @@ -269,5 +269,18 @@ where d.rdb$index_type = 0 and trim(d.rdb$relation_name) = {0}", tboldname ?? tb } return sb.Length == 0 ? null : sb.ToString(); } + + public override int ExecuteDDLStatements(string ddl) + { + if (string.IsNullOrEmpty(ddl)) return 0; + var scripts = ddl.Split(new string[] { ";\r\n" }, StringSplitOptions.None).Where(a => string.IsNullOrEmpty(a.Trim()) == false).ToArray(); + + if (scripts.Any() == false) return 0; + + var affrows = 0; + foreach (var script in scripts) + affrows += base.ExecuteDDLStatements(script); + return affrows; + } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Firebird/FreeSql.Provider.Firebird.csproj b/Providers/FreeSql.Provider.Firebird/FreeSql.Provider.Firebird.csproj index 59ec327e..36e7bf47 100644 --- a/Providers/FreeSql.Provider.Firebird/FreeSql.Provider.Firebird.csproj +++ b/Providers/FreeSql.Provider.Firebird/FreeSql.Provider.Firebird.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.GBase/FreeSql.Provider.GBase.csproj b/Providers/FreeSql.Provider.GBase/FreeSql.Provider.GBase.csproj index 83f316e9..9ea9cdf0 100644 --- a/Providers/FreeSql.Provider.GBase/FreeSql.Provider.GBase.csproj +++ b/Providers/FreeSql.Provider.GBase/FreeSql.Provider.GBase.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.KingbaseES/FreeSql.Provider.KingbaseES.csproj b/Providers/FreeSql.Provider.KingbaseES/FreeSql.Provider.KingbaseES.csproj index dba947c8..925621c6 100644 --- a/Providers/FreeSql.Provider.KingbaseES/FreeSql.Provider.KingbaseES.csproj +++ b/Providers/FreeSql.Provider.KingbaseES/FreeSql.Provider.KingbaseES.csproj @@ -15,7 +15,7 @@ $(AssemblyName) true true - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.MsAccess/FreeSql.Provider.MsAccess.csproj b/Providers/FreeSql.Provider.MsAccess/FreeSql.Provider.MsAccess.csproj index 8d0c0a33..00b81f1c 100644 --- a/Providers/FreeSql.Provider.MsAccess/FreeSql.Provider.MsAccess.csproj +++ b/Providers/FreeSql.Provider.MsAccess/FreeSql.Provider.MsAccess.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.MsAccess/MsAccessAdo/MsAccessConnectionPool.cs b/Providers/FreeSql.Provider.MsAccess/MsAccessAdo/MsAccessConnectionPool.cs index 4bcc57a0..d0bf31bb 100644 --- a/Providers/FreeSql.Provider.MsAccess/MsAccessAdo/MsAccessConnectionPool.cs +++ b/Providers/FreeSql.Provider.MsAccess/MsAccessAdo/MsAccessConnectionPool.cs @@ -63,7 +63,7 @@ namespace FreeSql.MsAccess { _connectionString = value ?? ""; - var minPoolSize = 0; + var minPoolSize = 1; var pattern = @"Min\s*pool\s*size\s*=\s*(\d+)"; var m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase); if (m.Success) diff --git a/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj b/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj index 0e419478..f3b4a829 100644 --- a/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj +++ b/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs b/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs index 75a2e955..7aac0ed7 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs @@ -212,7 +212,7 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); if (istmpatler == false) { - var existsPrimary = LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.key_column_usage where table_schema={0} and table_name={1} and constraint_name = 'PRIMARY' limit 1", tbname)); + var existsPrimary = LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.columns where table_schema={0} and table_name={1} and column_key = 'PRI' limit 1", tbname)); foreach (var tbcol in tb.ColumnsByPosition) { if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || diff --git a/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj b/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj index 3e7de715..a6af21bc 100644 --- a/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj +++ b/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs index d2104316..328bfe2a 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs @@ -37,7 +37,8 @@ namespace FreeSql.Odbc.Default return ret; }); - public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbc(args); + static FreeSql.Odbc.Default.OdbcAdo _customAdo = new FreeSql.Odbc.Default.OdbcAdo(); + public override string FormatSql(string sql, params object[] args) => (_orm?.Ado as OdbcAdo)?.Addslashes(sql, args) ?? _customAdo.Addslashes(sql, args); public override string QuoteSqlName(params string[] name) { if (name.Length == 1) diff --git a/Providers/FreeSql.Provider.Odbc/FreeSql.Provider.Odbc.csproj b/Providers/FreeSql.Provider.Odbc/FreeSql.Provider.Odbc.csproj index c8834590..0541f0b5 100644 --- a/Providers/FreeSql.Provider.Odbc/FreeSql.Provider.Odbc.csproj +++ b/Providers/FreeSql.Provider.Odbc/FreeSql.Provider.Odbc.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.Odbc/FreeSqlOdbcGlobalExtensions.cs b/Providers/FreeSql.Provider.Odbc/FreeSqlOdbcGlobalExtensions.cs index 3f91fbbc..8459646c 100644 --- a/Providers/FreeSql.Provider.Odbc/FreeSqlOdbcGlobalExtensions.cs +++ b/Providers/FreeSql.Provider.Odbc/FreeSqlOdbcGlobalExtensions.cs @@ -37,15 +37,6 @@ internal static string FormatOdbcPostgreSQL(this string that, params object[] args) => _odbcPostgreSQLAdo.Addslashes(that, args); static FreeSql.Odbc.PostgreSQL.OdbcPostgreSQLAdo _odbcPostgreSQLAdo = new FreeSql.Odbc.PostgreSQL.OdbcPostgreSQLAdo(); - /// - /// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换 - /// - /// - /// - /// - internal static string FormatOdbc(this string that, params object[] args) => _odbcAdo.Addslashes(that, args); - static FreeSql.Odbc.Default.OdbcAdo _odbcAdo = new FreeSql.Odbc.Default.OdbcAdo(); - /// /// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换 /// diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs index d75e2737..547e3455 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs @@ -201,7 +201,7 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); if (istmpatler == false) { - var existsPrimary = LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.key_column_usage where table_schema={0} and table_name={1} and constraint_name = 'PRIMARY' limit 1", tbname)); + var existsPrimary = LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.columns where table_schema={0} and table_name={1} and column_key = 'PRI' limit 1", tbname)); foreach (var tbcol in tb.ColumnsByPosition) { var isIdentityChanged = tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1; diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerSelect.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerSelect.cs index 750bae37..1e3bfdce 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerSelect.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerSelect.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.Odbc.SqlServer { @@ -44,7 +45,7 @@ namespace FreeSql.Odbc.SqlServer if (_limit > 0 || _skip > 0) { - if (string.IsNullOrEmpty(_orderby)) + if (string.IsNullOrEmpty(_orderby) && (_limit > 1 || _skip > 0)) //TOP 1 不自动 order by { if (string.IsNullOrEmpty(_groupby)) { @@ -63,13 +64,15 @@ namespace FreeSql.Odbc.SqlServer var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); for (var a = 0; a < tbsfrom.Length; a++) { - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); + var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(alias); if (tbsjoin.Length > 0) { //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias); + alias = LocalGetTableAlias(tbsfrom[b].Table.Type, tbUnion[tbsfrom[b].Table.Type], tbsfrom[b].Alias, _aliasRule); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(alias); if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); else @@ -110,7 +113,8 @@ namespace FreeSql.Odbc.SqlServer sb.Append(" \r\nRIGHT JOIN "); break; } - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tb.Table.Type, tb.Alias) ?? tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + var alias = LocalGetTableAlias(tb.Table.Type, tbUnion[tb.Table.Type], tb.Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND ").Append(tb.Cascade); if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } @@ -165,7 +169,7 @@ namespace FreeSql.Odbc.SqlServer if (tbUnionsIdx > 0) sb.Append("\r\n \r\nUNION ALL\r\n \r\n"); if (tbUnionsGt0) sb.Append(_select).Append(" * from ("); var tbUnion = tbUnions[tbUnionsIdx]; - + var sbnav = new StringBuilder(); sb.Append(_select); if (_distinct) sb.Append("DISTINCT "); @@ -176,13 +180,15 @@ namespace FreeSql.Odbc.SqlServer var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); for (var a = 0; a < tbsfrom.Length; a++) { - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); + var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(alias); if (tbsjoin.Length > 0) { //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias); + alias = LocalGetTableAlias(tbsfrom[b].Table.Type, tbUnion[tbsfrom[b].Table.Type], tbsfrom[b].Alias, _aliasRule); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(alias); if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); else @@ -223,7 +229,8 @@ namespace FreeSql.Odbc.SqlServer sb.Append(" \r\nRIGHT JOIN "); break; } - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tb.Table.Type, tb.Alias) ?? tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + var alias = LocalGetTableAlias(tb.Table.Type, tbUnion[tb.Table.Type], tb.Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND ").Append(tb.Cascade); if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } @@ -271,6 +278,17 @@ namespace FreeSql.Odbc.SqlServer } #endregion + static string LocalGetTableAlias(Type entityType, string tbname, string alias, Func aliasRule) + { + if (aliasRule != null) + { + alias = aliasRule(entityType, alias); + if (tbname.IndexOf(' ') != -1) //还可以这样:select.AsTable((a, b) => "(select * from tb_topic where clicks > 10)").Page(1, 10).ToList() + alias = Regex.Replace(alias, @" With\([^\)]+\)", ""); //替换 WithLock、WithIndex + } + return alias; + } + public OdbcSqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override ISelect From(Expression, T2, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcSqlServerSelect(_orm, _commonUtils, _commonExpression, null); OdbcSqlServerSelect.CopyData(this, ret, exp?.Parameters); return ret; } public override ISelect From(Expression, T2, T3, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcSqlServerSelect(_orm, _commonUtils, _commonExpression, null); OdbcSqlServerSelect.CopyData(this, ret, exp?.Parameters); return ret; } diff --git a/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj b/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj index 2d3d9815..46952429 100644 --- a/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj +++ b/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.OracleOledb/FreeSql.Provider.OracleOledb.csproj b/Providers/FreeSql.Provider.OracleOledb/FreeSql.Provider.OracleOledb.csproj index 7c6b7cfb..2b5ca143 100644 --- a/Providers/FreeSql.Provider.OracleOledb/FreeSql.Provider.OracleOledb.csproj +++ b/Providers/FreeSql.Provider.OracleOledb/FreeSql.Provider.OracleOledb.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj b/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj index 22a9310e..5a1aed23 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj +++ b/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.ShenTong/FreeSql.Provider.ShenTong.csproj b/Providers/FreeSql.Provider.ShenTong/FreeSql.Provider.ShenTong.csproj index 079988d9..03a733b7 100644 --- a/Providers/FreeSql.Provider.ShenTong/FreeSql.Provider.ShenTong.csproj +++ b/Providers/FreeSql.Provider.ShenTong/FreeSql.Provider.ShenTong.csproj @@ -15,7 +15,7 @@ $(AssemblyName) true true - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs index 625187d6..ac66d414 100644 --- a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs +++ b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.SqlServer.Curd { @@ -44,7 +45,7 @@ namespace FreeSql.SqlServer.Curd if (_limit > 0 || _skip > 0) { - if (string.IsNullOrEmpty(_orderby)) + if (string.IsNullOrEmpty(_orderby) && (_limit > 1 || _skip > 0)) //TOP 1 不自动 order by { if (string.IsNullOrEmpty(_groupby)) { @@ -63,13 +64,15 @@ namespace FreeSql.SqlServer.Curd var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); for (var a = 0; a < tbsfrom.Length; a++) { - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); + var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(alias); if (tbsjoin.Length > 0) { //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias); + alias = LocalGetTableAlias(tbsfrom[b].Table.Type, tbUnion[tbsfrom[b].Table.Type], tbsfrom[b].Alias, _aliasRule); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(alias); if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); else @@ -110,7 +113,8 @@ namespace FreeSql.SqlServer.Curd sb.Append(" \r\nRIGHT JOIN "); break; } - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tb.Table.Type, tb.Alias) ?? tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + var alias = LocalGetTableAlias(tb.Table.Type, tbUnion[tb.Table.Type], tb.Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND ").Append(tb.Cascade); if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } @@ -176,13 +180,15 @@ namespace FreeSql.SqlServer.Curd var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); for (var a = 0; a < tbsfrom.Length; a++) { - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); + var alias = LocalGetTableAlias(tbsfrom[a].Table.Type, tbUnion[tbsfrom[a].Table.Type], tbsfrom[a].Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(alias); if (tbsjoin.Length > 0) { //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias); + alias = LocalGetTableAlias(tbsfrom[b].Table.Type, tbUnion[tbsfrom[b].Table.Type], tbsfrom[b].Alias, _aliasRule); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(alias); if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); else @@ -223,7 +229,8 @@ namespace FreeSql.SqlServer.Curd sb.Append(" \r\nRIGHT JOIN "); break; } - sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tb.Table.Type, tb.Alias) ?? tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + var alias = LocalGetTableAlias(tb.Table.Type, tbUnion[tb.Table.Type], tb.Alias, _aliasRule); + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND ").Append(tb.Cascade); if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } @@ -271,6 +278,17 @@ namespace FreeSql.SqlServer.Curd } #endregion + static string LocalGetTableAlias(Type entityType, string tbname, string alias, Func aliasRule) + { + if (aliasRule != null) + { + alias = aliasRule(entityType, alias); + if (tbname.IndexOf(' ') != -1) //还可以这样:select.AsTable((a, b) => "(select * from tb_topic where clicks > 10)").Page(1, 10).ToList() + alias = Regex.Replace(alias, @" With\([^\)]+\)", ""); //替换 WithLock、WithIndex + } + return alias; + } + public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { if (FreeSqlSqlServerGlobalExtensions._dicSetGlobalSelectWithLock.TryGetValue(orm.Ado.Identifier, out var tryval)) this.WithLock(tryval.Item1, tryval.Item2); diff --git a/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj b/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj index 2db88d1c..9c18f3c6 100644 --- a/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj +++ b/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj @@ -18,7 +18,7 @@ true false key.snk - 3.2.683-preview20221101 + 3.2.684-preview20221124 @@ -26,7 +26,7 @@ - + diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs index a2a6dfd7..315ae260 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; +using FreeSql.Internal.CommonProvider; #if microsoft using Microsoft.Data.SqlClient; #else @@ -31,10 +32,74 @@ public static partial class FreeSqlSqlServerGlobalExtensions /// /// 多表查询时的锁规则 /// - public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) - => rule == null ? - that.AsAlias((type, old) => $"{old} With({lockType.ToString()})") : - that.AsAlias((type, old) => rule.TryGetValue(type, out var trybool) && trybool ? $"{old} With({lockType.ToString()})" : old); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class => LocalWithLock(that, lockType, rule); + + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class where T13 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class where T13 : class where T14 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class where T13 : class where T14 : class where T15 : class => LocalWithLock(that, lockType, rule); + public static ISelect WithLock(this ISelect that, SqlServerLock lockType = SqlServerLock.NoLock, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class where T13 : class where T14 : class where T15 : class where T16 : class => LocalWithLock(that, lockType, rule); + static TReturn LocalWithLock(TReturn query, SqlServerLock lockType, Dictionary rule) + { + var selectProvider = query as Select0Provider; + var oldalias = selectProvider._aliasRule; + selectProvider._aliasRule = (type, old) => + { + if (oldalias != null) old = oldalias(type, old); + if (rule == null) return LocalAppendWithString(old, lockType.ToString()); + return rule.TryGetValue(type, out var trybool) && trybool ? LocalAppendWithString(old, lockType.ToString()) : old; + }; + return query; + } + /// + /// SqkServer with(index) 强制索引 + /// + /// + /// + /// + /// + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class => LocalWithIndex(that, indexName, rule); + + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class where T13 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class where T13 : class where T14 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class where T13 : class where T14 : class where T15 : class => LocalWithIndex(that, indexName, rule); + public static ISelect WithIndex(this ISelect that, string indexName, Dictionary rule = null) where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class where T11 : class where T12 : class where T13 : class where T14 : class where T15 : class where T16 : class => LocalWithIndex(that, indexName, rule); + static TReturn LocalWithIndex(TReturn query, string indexName, Dictionary rule) + { + if (string.IsNullOrWhiteSpace(indexName)) return query; + var selectProvider = query as Select0Provider; + var oldalias = selectProvider._aliasRule; + selectProvider._aliasRule = (type, old) => + { + if (oldalias != null) old = oldalias(type, old); + if (type == selectProvider._tables[0].Table.Type) return LocalAppendWithString(old, $"index={indexName}"); + if (rule == null) return old; + return rule.TryGetValue(type, out var tryidxName) && string.IsNullOrWhiteSpace(tryidxName) == false ? LocalAppendWithString(old, $"index={tryidxName}") : old; + }; + return query; + } + static string LocalAppendWithString(string old, string str) => old?.Contains(" With(") == true ? old.Replace(" With(", $" With({str}, ") : $"{old} With({str})"; /// /// 设置全局 SqlServer with(nolock) 查询 diff --git a/Providers/FreeSql.Provider.SqlServerForSystem/FreeSql.Provider.SqlServerForSystem.csproj b/Providers/FreeSql.Provider.SqlServerForSystem/FreeSql.Provider.SqlServerForSystem.csproj index a79a3e3c..e9e9aa29 100644 --- a/Providers/FreeSql.Provider.SqlServerForSystem/FreeSql.Provider.SqlServerForSystem.csproj +++ b/Providers/FreeSql.Provider.SqlServerForSystem/FreeSql.Provider.SqlServerForSystem.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 @@ -26,7 +26,7 @@ - + diff --git a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsert.cs b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsert.cs index 4a9dd070..dd555680 100644 --- a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsert.cs +++ b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsert.cs @@ -58,6 +58,22 @@ namespace FreeSql.Sqlite.Curd return ret; } + public override string ToSql() + { + if (_table.Columns.Count == 1 && _table.ColumnsByPosition[0].Attribute.IsIdentity) + { + var sb = new StringBuilder(); + var didx = 0; + foreach (var d in _source) + { + if (didx++ > 0) sb.Append(";\r\n"); + sb.Append("INSERT INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" DEFAULT VALUES"); + } + return sb.ToString(); + } + return base.ToSql(); + } + #if net40 #else public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); diff --git a/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj b/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj index 44708cbf..f7f13124 100644 --- a/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj +++ b/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteConnectionPool.cs b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteConnectionPool.cs index 71502e04..9c762632 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteConnectionPool.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteConnectionPool.cs @@ -76,7 +76,7 @@ namespace FreeSql.Sqlite { _connectionString = value ?? ""; - var minPoolSize = 0; + var minPoolSize = 1; var pattern = @"Min\s*pool\s*size\s*=\s*(\d+)"; var m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase); if (m.Success) diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs b/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs index be6f2f5a..f332db90 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs @@ -136,7 +136,7 @@ namespace FreeSql.Sqlite { sb.Append("CREATE "); if (uk.IsUnique) sb.Append("UNIQUE "); - sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(ReplaceIndexName(uk.Name, tbname[1]))).Append(" ON ").Append(tbname[1]).Append("("); + sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(tbname[0], ReplaceIndexName(uk.Name, tbname[1]))).Append(" ON ").Append(tbname[1]).Append("("); foreach (var tbcol in uk.Columns) { sb.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name)); @@ -213,7 +213,7 @@ namespace FreeSql.Sqlite { if (string.Concat(dbIndex[3]) == "pk") continue; var dbIndexesColumns = _orm.Ado.ExecuteArray(CommandType.Text, $"PRAGMA {_commonUtils.QuoteSqlName(tbtmp[0])}.INDEX_INFO({dbIndex[1]})"); - var dbIndexesSql = string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, $" SELECT sql FROM sqlite_master WHERE name = '{dbIndex[1]}'")); + var dbIndexesSql = string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, $" SELECT sql FROM {_commonUtils.QuoteSqlName(tbtmp[0])}.sqlite_master WHERE name = '{dbIndex[1]}'")); foreach (var dbcolumn in dbIndexesColumns) { var dbcolumnName = string.Concat(dbcolumn[2]); @@ -292,7 +292,7 @@ namespace FreeSql.Sqlite { sb.Append("CREATE "); if (uk.IsUnique) sb.Append("UNIQUE "); - sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(ReplaceIndexName(uk.Name, tbname[1]))).Append(" ON \"").Append(tablenameOnlyTb).Append("\"("); + sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(tbname[0], ReplaceIndexName(uk.Name, tbname[1]))).Append(" ON \"").Append(tablenameOnlyTb).Append("\"("); foreach (var tbcol in uk.Columns) { sb.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name)); diff --git a/Providers/FreeSql.Provider.SqliteCore/FreeSql.Provider.SqliteCore.csproj b/Providers/FreeSql.Provider.SqliteCore/FreeSql.Provider.SqliteCore.csproj index 8940e113..368ad0d9 100644 --- a/Providers/FreeSql.Provider.SqliteCore/FreeSql.Provider.SqliteCore.csproj +++ b/Providers/FreeSql.Provider.SqliteCore/FreeSql.Provider.SqliteCore.csproj @@ -18,7 +18,7 @@ true key.snk false - 3.2.683-preview20221101 + 3.2.684-preview20221124 diff --git a/README.md b/README.md index b89364d7..0b8f0bfd 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,8 @@ constantine, [JohnZhou2020](https://github.com/JohnZhou2020), [mafeng8](https://github.com/mafeng8), [VicBilibily](https://github.com/VicBilibily), -[Soar](https://github.com/sgf) etc. +[Soar](https://github.com/sgf), +[quzhen91](https://github.com/quzhen91) etc. ## 💕 Donation diff --git a/README.zh-CN.md b/README.zh-CN.md index 579110a8..072e4001 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -210,8 +210,8 @@ constantine, [JohnZhou2020](https://github.com/JohnZhou2020), [mafeng8](https://github.com/mafeng8), [VicBilibily](https://github.com/VicBilibily), -[Soar](https://github.com/sgf) 等。 - +[Soar](https://github.com/sgf), +[quzhen91](https://github.com/quzhen91) 等。 ## 💕 Donation (捐赠)