diff --git a/Src/Asp.Net/SqlSugar/Abstract/CodeFirstProvider/CodeFirstProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/CodeFirstProvider/CodeFirstProvider.cs index 8e077c042..876b3d1cd 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/CodeFirstProvider/CodeFirstProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/CodeFirstProvider/CodeFirstProvider.cs @@ -207,6 +207,7 @@ namespace SqlSugar #region Core Logic private void GetDifferenceTables(TableDifferenceProvider result, Type type) { + var isCreate = false; var tempTableName = "TempDiff" + DateTime.Now.ToString("yyMMssHHmmssfff"); var oldTableName = this.Context.EntityMaintenance.GetEntityInfo(type).DbTableName; var db = new SqlSugarProvider(UtilMethods.CopyConfig(this.Context.CurrentConnectionConfig)); @@ -224,6 +225,7 @@ namespace SqlSugar var codeFirst=db.CodeFirst; codeFirst.SetStringDefaultLength(this.DefultLength); codeFirst.InitTables(type); + isCreate = true; var tables = db.DbMaintenance.GetTableInfoList(false); var oldTableInfo = tables.FirstOrDefault(it=>it.Name.EqualCase(oldTableName)); var newTableInfo = tables.FirstOrDefault(it => it.Name.EqualCase(oldTableName)); @@ -248,7 +250,10 @@ namespace SqlSugar } finally { - db.DbMaintenance.DropTable(tempTableName); + if (isCreate) + { + db.DbMaintenance.DropTable(tempTableName); + } } } protected virtual void Execute(Type entityType,EntityInfo entityInfo) diff --git a/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/DynamicProperyBuilder.cs b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/DynamicProperyBuilder.cs index bb71bdb7f..c0986f435 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/DynamicProperyBuilder.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/DynamicProperyBuilder.cs @@ -106,28 +106,29 @@ namespace SqlSugar Type mappingTableType = navigate.MappingType; string typeAiD = navigate.MappingAId; string typeBId = navigate.MappingBId; + var queryPropertyNames = navigate.QueryPropertyNames; ConstructorInfo constructor; object[] constructorArgs; if (mappingTableType != null && typeAiD != null && typeBId != null) { - constructor = typeof(Navigate).GetConstructor(new Type[] { typeof(Type), typeof(string), typeof(string), typeof(string) }); - constructorArgs = new object[] { mappingTableType, typeAiD, typeBId, whereSql }; + constructor = typeof(Navigate).GetConstructor(new Type[] { typeof(Type), typeof(string), typeof(string), typeof(string), typeof(string[]) }); + constructorArgs = new object[] { mappingTableType, typeAiD, typeBId, whereSql , queryPropertyNames }; } else if (!string.IsNullOrEmpty(whereSql)) { - constructor = typeof(Navigate).GetConstructor(new Type[] { typeof(NavigateType), typeof(string), typeof(string), typeof(string) }); - constructorArgs = new object[] { navigatType, name, name2, whereSql }; + constructor = typeof(Navigate).GetConstructor(new Type[] { typeof(NavigateType), typeof(string), typeof(string), typeof(string), typeof(string[]) }); + constructorArgs = new object[] { navigatType, name, name2, whereSql, queryPropertyNames }; } else if (!string.IsNullOrEmpty(name2)) { - constructor = typeof(Navigate).GetConstructor(new Type[] { typeof(NavigateType), typeof(string), typeof(string) }); - constructorArgs = new object[] { navigatType, name, name2 }; + constructor = typeof(Navigate).GetConstructor(new Type[] { typeof(NavigateType), typeof(string), typeof(string), typeof(string[]) }); + constructorArgs = new object[] { navigatType, name, name2, queryPropertyNames }; } else { - constructor = typeof(Navigate).GetConstructor(new Type[] { typeof(NavigateType), typeof(string) }); - constructorArgs = new object[] { navigatType, name }; + constructor = typeof(Navigate).GetConstructor(new Type[] { typeof(NavigateType), typeof(string), typeof(string[]) }); + constructorArgs = new object[] { navigatType, name, queryPropertyNames }; } return new CustomAttributeBuilder(constructor, constructorArgs); diff --git a/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/FastestProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/FastestProvider.cs index ad729716f..8dce2dd0d 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/FastestProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/FastestProvider.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Reflection; using System.Runtime.CompilerServices; +using System.Linq.Expressions; namespace SqlSugar { public partial class FastestProvider:IFastest where T:class,new() @@ -244,6 +245,21 @@ namespace SqlSugar return BulkMergeAsync(datas, whereColumns, updateColumns).GetAwaiter().GetResult(); } + public async Task BulkMergeAsync(List datas, Expression> whereColumnsExp, Expression> updateColumnsExp) + { + // 1. 获取 whereColumns + var whereColumns =ExpressionTool.GetNewExpressionItemListNew((whereColumnsExp as LambdaExpression).Body).Select(it=>it.Key).ToArray(); + // 2. 获取 updateColumns + var updateColumns = ExpressionTool.GetNewExpressionItemListNew((updateColumnsExp as LambdaExpression).Body).Select(it => it.Key).ToArray(); + + // 3. 调用 BulkMergeAsync + return await BulkMergeAsync(datas, whereColumns, updateColumns); + } + public int BulkMerge(List datas, Expression> whereColumnsExp, Expression> updateColumnsExp) + { + return BulkMergeAsync(datas, whereColumnsExp, updateColumnsExp).GetAwaiter().GetResult(); + } + private async Task _BulkMerge(List datas, string[] updateColumns, string[] whereColumns) { try diff --git a/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/Private.cs b/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/Private.cs index a0e4f705f..0b6dc0dca 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/Private.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/Private.cs @@ -4,6 +4,7 @@ using System.Data; using System.Linq; using System.Linq.Expressions; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace SqlSugar @@ -85,7 +86,7 @@ namespace SqlSugar List uInt64TypeName = new List(); foreach (DataColumn item in tempDataTable.Columns) { - if (item.DataType == typeof(UInt64)) + if (item.DataType == typeof(UInt64)) { uInt64TypeName.Add(item.ColumnName); } @@ -98,13 +99,43 @@ namespace SqlSugar dt.Columns.Add(item.ColumnName, item.DataType); } } + + bool supportIdentity = true; + if (this.context.CurrentConnectionConfig.DbType == DbType.PostgreSQL || this.context.CurrentConnectionConfig.DbType == DbType.Vastbase) + { + supportIdentity = false; + } + + if (!supportIdentity) + { + // PostgreSQL/Vastbase不支持自增主键导入 + foreach (var identityColumnInfo in this.entityInfo.Columns.Where(it => it.IsIdentity)) + { + if (dt.Columns.Contains(identityColumnInfo.DbColumnName)) + { + dt.Columns.Remove(identityColumnInfo.DbColumnName); + } + } + } + dt.TableName = GetTableName(); - var columns = entityInfo.Columns; + var columns = supportIdentity ? entityInfo.Columns : entityInfo.Columns.Where(it => !it.IsIdentity).ToList(); if (columns.Where(it=>!it.IsIgnore).Count() > tempDataTable.Columns.Count) { var tempColumns = tempDataTable.Columns.Cast().Select(it=>it.ColumnName); columns = columns.Where(it => tempColumns.Any(s => s.EqualCase(it.DbColumnName))).ToList(); } + MyTuple myTuple = GetDiscrimator(); + + if (myTuple.isDiscrimator && myTuple.discrimatorDict?.Count > 0) + { + foreach (var dict in myTuple.discrimatorDict) + { + if (!dt.Columns.Contains(dict.Key)) + dt.Columns.Add(dict.Key); + } + } + var isMySql = this.context.CurrentConnectionConfig.DbType.IsIn(DbType.MySql, DbType.MySqlConnector); var isSqliteCore = SugarCompatible.IsFramework==false&& this.context.CurrentConnectionConfig.DbType.IsIn(DbType.Sqlite); foreach (var item in datas) @@ -168,6 +199,15 @@ namespace SqlSugar } dr[name] = value; } + if (myTuple.isDiscrimator && myTuple.discrimatorDict?.Count > 0) + { + foreach (var dict in myTuple.discrimatorDict) + { + var key = dict.Key; var val = dict.Value; + if (!string.IsNullOrWhiteSpace(val) && string.IsNullOrWhiteSpace(dr[key] + "")) + dr[key] = val; + } + } dt.Rows.Add(dr); } @@ -353,5 +393,36 @@ namespace SqlSugar } } + private MyTuple GetDiscrimator() + { + var isDiscrimator = entityInfo.Discrimator.HasValue(); + var dict = new Dictionary(); + if (isDiscrimator) + { + Check.ExceptionEasy(!Regex.IsMatch(entityInfo.Discrimator, @"^(?:\w+:\w+)(?:,\w+:\w+)*$"), "The format should be type:cat for this type, and if there are multiple, it can be FieldName:cat,FieldName2:dog ", "格式错误应该是type:cat这种格式,如果是多个可以FieldName:cat,FieldName2:dog,不要有空格"); + var array = entityInfo.Discrimator.Split(','); + foreach (var disItem in array) + { + var name = disItem.Split(':').First(); + var value = disItem.Split(':').Last(); + if(!dict.ContainsKey(name)) + dict.Add(name, value); + } + } + return new MyTuple(isDiscrimator, dict); + } + + } + + internal class MyTuple + { + public bool isDiscrimator; + public Dictionary discrimatorDict; + + public MyTuple(bool isDiscrimator, Dictionary dict) + { + this.isDiscrimator = isDiscrimator; + this.discrimatorDict = dict; + } } } diff --git a/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/InsertableHelper.cs b/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/InsertableHelper.cs index 9aee1c191..36b97b937 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/InsertableHelper.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/InsertableHelper.cs @@ -375,7 +375,7 @@ namespace SqlSugar { var name = disItem.Split(':').First(); var value = disItem.Split(':').Last(); - insertItem.Add(new DbColumnInfo() { DbColumnName = name, PropertyName = name, PropertyType = typeof(string), Value = value }); + insertItem.Add(new DbColumnInfo() { TableId=i, DbColumnName = name, PropertyName = name, PropertyType = typeof(string), Value = value }); } } } diff --git a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs index 30f965836..be9124ca5 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs @@ -271,7 +271,11 @@ namespace SqlSugar var sql = GetWhereSql(GetCrossDatabase(abDb, bEntity)); if (sql.SelectString == null) { + //加载指定列 + var manualPropertyNames = GetQueryPropertyNames(navObjectNameColumnInfo); + var columns = bEntityInfo.Columns.Where(it => !it.IsIgnore) + .WhereIF(manualPropertyNames != null && manualPropertyNames.Length > 0, it => manualPropertyNames.Contains(it.PropertyName)) .Select(it => GetOneToManySelectByColumnInfo(it, abDb)).ToList(); sql.SelectString = String.Join(",", columns); } @@ -433,7 +437,11 @@ namespace SqlSugar var sqlObj = GetWhereSql(db, navObjectNameColumnInfo.Navigat.Name); if (sqlObj.SelectString == null) { + // 加载指定列 + var queryPropertyNames = GetQueryPropertyNames(navObjectNameColumnInfo); + var columns = navEntityInfo.Columns.Where(it => !it.IsIgnore) + .WhereIF(queryPropertyNames != null && queryPropertyNames.Length > 0, it => queryPropertyNames.Contains(it.PropertyName)) .Select(it => GetOneToOneSelectByColumnInfo(it, db)).ToList(); sqlObj.SelectString = String.Join(",", columns); } @@ -581,7 +589,10 @@ namespace SqlSugar { if (sqlObj.SelectString == null) { + //加载指定列 + var manualPropertyNames = GetQueryPropertyNames(navObjectNameColumnInfo); var columns = navEntityInfo.Columns.Where(it => !it.IsIgnore) + .WhereIF(manualPropertyNames != null && manualPropertyNames.Length > 0, it => manualPropertyNames.Contains(it.PropertyName)) .Select(it => GetOneToManySelectByColumnInfo(it, childDb)).ToList(); sqlObj.SelectString = String.Join(",", columns); } @@ -699,7 +710,11 @@ namespace SqlSugar { if (sqlObj.SelectString == null) { + //加载指定列 + var manualPropertyNames = GetQueryPropertyNames(navObjectNameColumnInfo); + var columns = navEntityInfo.Columns.Where(it => !it.IsIgnore) + .WhereIF(manualPropertyNames != null && manualPropertyNames.Length > 0, it => manualPropertyNames.Contains(it.PropertyName)) .Select(it => GetOneToManySelectByColumnInfo(it,childDb)).ToList(); sqlObj.SelectString = String.Join(",", columns); } @@ -1252,5 +1267,38 @@ namespace SqlSugar return QueryBuilder.Builder.GetTranslationColumnName(it.DbColumnName) + " AS " + QueryBuilder.Builder.GetTranslationColumnName(it.PropertyName); } + /// + /// 获取查询的属性名称列表 + /// + /// + /// + private string[] GetQueryPropertyNames(EntityColumnInfo navObjectNameColumnInfo) + { + string[] queryPropertyNames = null; + if (navObjectNameColumnInfo?.Navigat?.QueryPropertyNames?.Any()==true) + { + var navInfo = navObjectNameColumnInfo?.Navigat; + queryPropertyNames = navObjectNameColumnInfo.Navigat.QueryPropertyNames; + var list = queryPropertyNames.ToList(); + if (navInfo.AClassId != null) + { + list.Add(navInfo.AClassId); + } + if (navInfo.BClassId != null) + { + list.Add(navInfo.BClassId); + } + if (navInfo.Name != null) + { + list.Add(navInfo.Name); + } + if (navInfo.Name2 != null) + { + list.Add(navInfo.Name2); + } + queryPropertyNames = list.ToArray(); + } + return queryPropertyNames; + } } } diff --git a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableExecuteSqlAsync.cs b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableExecuteSqlAsync.cs index e4f0ef79a..8e7ccae71 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableExecuteSqlAsync.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableExecuteSqlAsync.cs @@ -164,6 +164,7 @@ namespace SqlSugar { var copyDb = this.Clone(); copyDb.QueryBuilder.OrderByValue = null; + copyDb.QueryBuilder.Includes = null; var list = await copyDb.Select(" COUNT(1) ").ToListAsync(); return list.FirstOrDefault(); } diff --git a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableHelper.cs b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableHelper.cs index e40fa7bea..559b3b6db 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableHelper.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableHelper.cs @@ -13,7 +13,7 @@ using System.Collections.ObjectModel; using NetTaste; using Newtonsoft.Json.Linq; using System.Xml.Linq; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; namespace SqlSugar @@ -866,6 +866,15 @@ namespace SqlSugar { propertyInfo.SetValue(addItem,UtilMethods.To( kv.Value, propertyInfo.PropertyType)); } + else if (kv.Value is string s&& + s!=null&& + s?.StartsWith("[")==true&& + s?.EndsWith("]") == true&& + UtilMethods.IsArrayOrList(propertyInfo.PropertyType) + ) + { + propertyInfo.SetValue(addItem, UtilMethods.ConvertToArray(kv.Value?.ToString(), propertyInfo.PropertyType)); + } else { propertyInfo.SetValue(addItem, kv.Value); diff --git a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs index 59875a415..1054ab6b2 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs @@ -216,7 +216,14 @@ namespace SqlSugar if (isLeftJoin == false) { result.QueryBuilder.JoinQueryInfos.Remove(result.QueryBuilder.JoinQueryInfos.Last()); - result.QueryBuilder.AsTables = oldAsName; + if (oldAsName?.Any() == false && result.QueryBuilder.AsTables?.Any() == true) + { + //no things + } + else + { + result.QueryBuilder.AsTables = oldAsName; + } } return result; } @@ -227,7 +234,14 @@ namespace SqlSugar if (isJoin == false) { result.QueryBuilder.JoinQueryInfos.Remove(result.QueryBuilder.JoinQueryInfos.Last()); - result.QueryBuilder.AsTables = oldAsName; + if (oldAsName?.Any() == false && result.QueryBuilder.AsTables?.Any() == true) + { + //no things + } + else + { + result.QueryBuilder.AsTables = oldAsName; + } } return result; } diff --git a/Src/Asp.Net/SqlSugar/Abstract/Reportable/ReportableProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/Reportable/ReportableProvider.cs index 88b19296b..097290998 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/Reportable/ReportableProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/Reportable/ReportableProvider.cs @@ -215,6 +215,10 @@ namespace SqlSugar { return $" CAST( NULL AS timestamp) "; } + else if (entityColumnInfo != null && entityColumnInfo.IsJson && value!=null) + { + return $"'{this.Context.Utilities.SerializeObject(value).ToSqlFilter()}'"; + } if (value == null) return "null"; var type =UtilMethods.GetUnderType(value.GetType()); diff --git a/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarAccessory.cs b/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarAccessory.cs index f3a3e8e3d..a456224e5 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarAccessory.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarAccessory.cs @@ -527,6 +527,9 @@ namespace SqlSugar break; case DbType.PolarDB: config.DbType = DbType.MySql; + if (this.CurrentConnectionConfig.MoreSettings == null) + this.CurrentConnectionConfig.MoreSettings = new ConnMoreSettings(); + this.CurrentConnectionConfig.MoreSettings.DatabaseModel = DbType.PolarDB; break; case DbType.TDSQL: config.DbType = DbType.MySql; diff --git a/Src/Asp.Net/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs index 6c9bb6b44..096eecc29 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs @@ -275,7 +275,18 @@ namespace SqlSugar public IUpdateable InnerJoin(ISugarQueryable queryable, Expression> joinExpress) { var tableName = $" ({queryable.Clone().ToSqlString()}) "; ; - return this.InnerJoin(joinExpress, tableName); + return this.InnerJoin(tableName, joinExpress,this.UpdateBuilder.TableName); + } + public IUpdateable InnerJoin(string joinTable, Expression> joinExpress, string tableName) + { + UpdateableProvider result = new UpdateableProvider(); + result.updateableObj = this; + var querybale = this.Context.Queryable().LeftJoin(joinExpress); + result.updateableObj.UpdateBuilder.JoinInfos = querybale.QueryBuilder.JoinQueryInfos; + result.updateableObj.UpdateBuilder.JoinInfos.Last().TableName = joinTable; + result.updateableObj.UpdateBuilder.ShortName = joinExpress.Parameters.FirstOrDefault()?.Name; + result.updateableObj.UpdateBuilder.TableName = tableName; + return result; } public IUpdateable InnerJoin(Expression> joinExpress,string TableName) { diff --git a/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs b/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs index bf6657e5f..1e7dce3f1 100644 --- a/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs +++ b/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs @@ -243,6 +243,15 @@ namespace SqlSugar internal string BClassId { get; set; } + /// + /// 用于查询指定列 + /// + internal string[] QueryPropertyNames { get; set; } + public string[] GetQueryPropertyNames() + { + return QueryPropertyNames; + } + public string GetName() { return Name; @@ -272,36 +281,40 @@ namespace SqlSugar { return WhereSql; } - public Navigate(NavigateType navigatType,string ifSingleMasterTableColumn_IfListChildTableColumn) + public Navigate(NavigateType navigatType,string ifSingleMasterTableColumn_IfListChildTableColumn, string[] queryPropertyNames = null) { this.Name = ifSingleMasterTableColumn_IfListChildTableColumn; this.NavigatType = navigatType; + this.QueryPropertyNames = queryPropertyNames; } - public Navigate(NavigateType navigatType, string ifSingleMasterTableColumn_IfListChildTableColumn, string ifSingleChildTableColumn_IfListMasterTableColumn) + public Navigate(NavigateType navigatType, string ifSingleMasterTableColumn_IfListChildTableColumn, string ifSingleChildTableColumn_IfListMasterTableColumn, string[] queryPropertyNames = null) { Check.ExceptionEasy(navigatType == NavigateType.ManyToMany, "Correct usage [Navigate(typeof(ABMapping), nameof(abmapping.aid), nameof(abmapp.bid))], incorrect usage: [Navigate(Navigate.ManyToMany, nameof(ABMapping.Aid), nameof(ABMapping.BId))]", "多对多第一个参数是Type不是NavigateType,正确用法[Navigate(typeof(ABMapping), nameof(ABMapping.Aid), nameof(ABMapping.BId))],错误用法:[Navigate(Navigate.ManyToMany, nameof(ABMapping.Aid), nameof(ABMapping.BId))]"); this.Name = ifSingleMasterTableColumn_IfListChildTableColumn; this.Name2 = ifSingleChildTableColumn_IfListMasterTableColumn; this.NavigatType = navigatType; + this.QueryPropertyNames = queryPropertyNames; } - public Navigate(NavigateType navigatType, string ifSingleMasterTableColumn_IfListChildTableColumn, string ifSingleChildTableColumn_IfListMasterTableColumn, string whereSql) + public Navigate(NavigateType navigatType, string ifSingleMasterTableColumn_IfListChildTableColumn, string ifSingleChildTableColumn_IfListMasterTableColumn, string whereSql, string[] queryPropertyNames = null) { this.Name = ifSingleMasterTableColumn_IfListChildTableColumn; this.Name2 = ifSingleChildTableColumn_IfListMasterTableColumn; this.NavigatType = navigatType; this.WhereSql = whereSql; + this.QueryPropertyNames = queryPropertyNames; //Check.ExceptionEasy(navigatType != NavigateType.OneToOne, "Currently, only one-to-one navigation configuration Sql conditions are supported", "目前导航配置Sql条件只支持一对一"); } - public Navigate(Type MappingTableType,string typeAId,string typeBId) + public Navigate(Type MappingTableType,string typeAId,string typeBId, string[] queryPropertyNames = null) { this.MappingType = MappingTableType; this.MappingAId = typeAId; this.MappingBId = typeBId; this.NavigatType = NavigateType.ManyToMany; + this.QueryPropertyNames = queryPropertyNames; } - public Navigate(Type MappingTableType, string mappingAId, string mappingBId,string aClassId,string bClassId) + public Navigate(Type MappingTableType, string mappingAId, string mappingBId,string aClassId,string bClassId, string[] queryPropertyNames = null) { this.MappingType = MappingTableType; this.MappingAId = mappingAId; @@ -309,14 +322,16 @@ namespace SqlSugar this.AClassId = aClassId; this.BClassId = bClassId; this.NavigatType = NavigateType.ManyToMany; + this.QueryPropertyNames = queryPropertyNames; } - public Navigate(Type MappingTableType, string typeAiD, string typeBId,string mappingSql) + public Navigate(Type MappingTableType, string typeAiD, string typeBId,string mappingSql, string[] queryPropertyNames = null) { this.MappingType = MappingTableType; this.MappingAId = typeAiD; this.MappingBId = typeBId; this.NavigatType = NavigateType.ManyToMany; this.WhereSql+= mappingSql; + this.QueryPropertyNames = queryPropertyNames; } } diff --git a/Src/Asp.Net/SqlSugar/Enum/ProperyType.cs b/Src/Asp.Net/SqlSugar/Enum/ProperyType.cs index 245b91a18..3490c2b1a 100644 --- a/Src/Asp.Net/SqlSugar/Enum/ProperyType.cs +++ b/Src/Asp.Net/SqlSugar/Enum/ProperyType.cs @@ -27,6 +27,13 @@ namespace SqlSugar @DateTimeOffset, @Single, @TimeSpan, - @char + @char, + @NpgsqlBox, + @NpgsqlCircle, + @NpgsqlLine, + @NpgsqlLseg, + @NpgsqlPath, + @NpgsqlPoint, + @NpgsqlPolygon, } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs index a1c5e6eec..0c8dc166c 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs @@ -303,7 +303,19 @@ namespace SqlSugar GetTopLevelMethodCalls(lambdaExpression.Body, methodCalls); } } - + public static Dictionary GetNewExpressionItemListNew(Expression lamExp) + { + var caseExp = GetLambdaExpressionBody(lamExp); + caseExp = ExpressionTool.RemoveConvert(lamExp); + if (caseExp is MemberExpression c) + { + return new Dictionary() { { c.Member.Name, c } }; + } + else + { + return GetNewExpressionItemList(lamExp); + } + } public static Dictionary GetNewExpressionItemList(Expression lamExp) { var caseExp = GetLambdaExpressionBody(lamExp); @@ -359,10 +371,16 @@ namespace SqlSugar } public static List GetParameters(Expression expr) { - var ps = new ParameterExpressionVisitor(); + var ps = new ParameterExpressionVisitor(); ps.Visit(expr); return ps.Parameters; } + public static bool NoParameterOrSqlfunc(Expression expr) + { + var ps = new ParameterExpressionVisitor(); + ps.Visit(expr); + return ps.Parameters.Count==0&&ps.IsSqlFunc==false; + } public static bool IsComparisonOperatorBool(BinaryExpression binaryExp) { return binaryExp.NodeType.IsIn(ExpressionType.Equal, diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ParameterExpressionVisitor.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ParameterExpressionVisitor.cs index af51a9218..10656be4c 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ParameterExpressionVisitor.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ParameterExpressionVisitor.cs @@ -10,6 +10,7 @@ namespace SqlSugar { internal class ParameterExpressionVisitor : ExpressionVisitor { + public bool IsSqlFunc { get; set; } public List Parameters { get; } = new List(); protected override Expression VisitParameter(ParameterExpression node) @@ -17,6 +18,14 @@ namespace SqlSugar Parameters.Add(node); return base.VisitParameter(node); } + protected override Expression VisitMethodCall(MethodCallExpression node) + { + if (node.Method?.DeclaringType==typeof(SqlFunc)) + { + IsSqlFunc = true; + } + return base.VisitMethodCall(node); + } } internal class MethodCallExpressionVisitor : ExpressionVisitor { diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs index 86bcfbef9..a50908e8c 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs @@ -9,6 +9,7 @@ namespace SqlSugar { public partial class DefaultDbMethod : IDbMethods { + public ISqlSugarClient sqlSugarClient { get; set; } public virtual string ParameterKeyWord { get; set; }= "@"; public virtual string RowNumber(MethodCallExpressionModel model) { diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs index 9da948fb0..4c54c2bcb 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs @@ -11,6 +11,7 @@ namespace SqlSugar { public interface IDbMethods { + ISqlSugarClient sqlSugarClient { get; set; } string IIF(MethodCallExpressionModel model); string HasNumber(MethodCallExpressionModel model); string HasValue(MethodCallExpressionModel model); diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs index a3da545ee..fec394b3d 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs @@ -18,7 +18,7 @@ namespace SqlSugar express.IfFalse }; SetSingleTableNameSubqueryShortName(express); - if (ExpressionTool.GetParameters(express.Test).Count == 0) + if (ExpressionTool.NoParameterOrSqlfunc(express.Test)) { while (express != null) { diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelectStringJoin.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelectStringJoin.cs index 5b6cd921c..3bfa59592 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelectStringJoin.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelectStringJoin.cs @@ -65,6 +65,7 @@ namespace SqlSugar result = string.Join(",",(constant.Value+"").Split(',').Select(it=>this.Context.GetTranslationTableName(it))); } } + this.Context.DbMehtods.sqlSugarClient = this.Context?.SugarContext?.Context; result = this.Context.DbMehtods.GetStringJoinSelector(result, ExpressionTool.GetExpressionValue(exp.Arguments[1]) + ""); return result; diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs index d188dcb7c..cfb72be0f 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs @@ -304,16 +304,34 @@ namespace SqlSugar { this.context.CurrentShortName=ExpressionTool.GetParameters(allMethods.FirstOrDefault()).FirstOrDefault().Name; } + var hasNolock = false; List result = isubList.Select(it => { it.HasWhere = isHasWhere; - return it.GetValue(it.Expression); + if (it is SubWithNolock) + { + hasNolock = true; + } + var innerResult = it.GetValue(it.Expression); + var innerIsJoin = (it is SubLeftJoin || it is SubInnerJoin); + var isSqlServer =UtilMethods.GetDatabaseType(this.context) == DbType.SqlServer; + if (hasNolock && innerIsJoin&& isSqlServer) + { + innerResult = innerResult.Replace("] ON (", "] " + SqlWith.NoLock + " ON ("); + } + return innerResult; }).ToList(); + if (this.context?.SugarContext?.Context?.CurrentConnectionConfig?.DbType == DbType.Oracle && isubList.Any(s => s is SubSelect) && isubList.Any(s => s is SubOrderBy || s is SubOrderByDesc)) + { + result.Insert(0, "SELECT * FROM("); + result.Add(") WHERE ROWNUM = 1 "); + } this.context.JoinIndex = 0; this.context.IsAsAttr = false; return result; } + private static void SetOrderByIndex(List isubList) { var orderByIndex = 0; diff --git a/Src/Asp.Net/SqlSugar/Interface/IFastest.cs b/Src/Asp.Net/SqlSugar/Interface/IFastest.cs index d571397bf..7a4063378 100644 --- a/Src/Asp.Net/SqlSugar/Interface/IFastest.cs +++ b/Src/Asp.Net/SqlSugar/Interface/IFastest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; -using System.Data; +using System.Data; +using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; @@ -45,6 +46,7 @@ namespace SqlSugar int BulkMerge(List datas, string[] whereColumns); Task BulkMergeAsync(List datas, string[] whereColumns, string[] updateColumns); int BulkMerge(List datas, string[] whereColumns, string[] updateColumns); - + Task BulkMergeAsync(List datas, Expression> whereColumnsExp, Expression> updateColumnsExp); + int BulkMerge(List datas, Expression> whereColumnsExp, Expression> updateColumnsExp); } } diff --git a/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs b/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs index 73988a243..cf61bf705 100644 --- a/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs +++ b/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs @@ -18,7 +18,65 @@ namespace SqlSugar { public class UtilMethods { + public static bool IsArrayOrList(Type propertyType) + { + if (propertyType==null||propertyType == typeof(string)) + return false; + var isList = propertyType.FullName.IsCollectionsList(); + var isArray = propertyType.IsArray; + return isList || isArray; + } + public static object ConvertToArray(string input, Type targetType) + { + // 获取元素类型和集合类型 + Type elementType; + bool isArray = targetType.IsArray; + bool isList = targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(List<>); + if (!isArray && !isList) + throw new ArgumentException("目标类型必须是数组或List类型"); + + elementType = isArray ? targetType.GetElementType() : targetType.GetGenericArguments()[0]; + + // 处理空输入 + if (string.IsNullOrEmpty(input)) + { + if (isArray) + return Array.CreateInstance(elementType, 0); + else + return Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + } + + // 解析输入字符串 + var elements = input.Trim('[', ']').Split(','); + + if (isArray) + { + // 处理数组 + Array array = Array.CreateInstance(elementType, elements.Length); + for (int i = 0; i < elements.Length; i++) + { + string element = elements[i]?.Trim()?.TrimStart('"')?.TrimEnd('"'); + array.SetValue(UtilMethods.ChangeType2(element, elementType), i); + } + return array; + } + else + { + // 处理List + var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + for (int i = 0; i < elements.Length; i++) + { + string element = elements[i]?.Trim()?.TrimStart('"')?.TrimEnd('"'); + list.Add(UtilMethods.ChangeType2(element, elementType)); + } + return list; + } + } + internal static DbType? GetDatabaseType(ExpressionContext context) + { + return context?.SugarContext?.Context?.CurrentConnectionConfig?.DbType; + } internal static void SetDefaultValueForBoolean(EntityColumnInfo item, Type propertyType) { if (propertyType == UtilConstants.BoolType && item.DefaultValue != null && item.DefaultValue.EqualCase("true"))