mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 01:05:27 +08:00 
			
		
		
		
	@@ -532,5 +532,14 @@
 | 
				
			|||||||
            <param name="that"></param>
 | 
					            <param name="that"></param>
 | 
				
			||||||
            <returns></returns>
 | 
					            <returns></returns>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            批量注入 Repository,可以参考代码自行调整
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <param name="services"></param>
 | 
				
			||||||
 | 
					            <param name="globalDataFilter"></param>
 | 
				
			||||||
 | 
					            <param name="assemblies"></param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
    </members>
 | 
					    </members>
 | 
				
			||||||
</doc>
 | 
					</doc>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2304,6 +2304,67 @@ WHERE ((a.""CreateTime"" >= '2010-10-10 00:00:00' AND a.""CreateTime"" < '2010-1
 | 
				
			|||||||
FROM ""D_District"" a 
 | 
					FROM ""D_District"" a 
 | 
				
			||||||
LEFT JOIN ""D_District"" a__Parent ON a__Parent.""Code"" = a.""ParentCode"" 
 | 
					LEFT JOIN ""D_District"" a__Parent ON a__Parent.""Code"" = a.""ParentCode"" 
 | 
				
			||||||
WHERE ((not((a.""Code"") LIKE '%val1%') AND not((a.""Name"") LIKE 'val2%') OR not((a.""Name"") LIKE '%val3') OR a.""ParentCode"" <> 'val4' OR a__Parent.""Code"" = 'val11' AND (a__Parent.""Name"") LIKE '%val22%' OR a__Parent.""Name"" = 'val33' OR a__Parent.""ParentCode"" = 'val44'))", sql);
 | 
					WHERE ((not((a.""Code"") LIKE '%val1%') AND not((a.""Name"") LIKE 'val2%') OR not((a.""Name"") LIKE '%val3') OR a.""ParentCode"" <> 'val4' OR a__Parent.""Code"" = 'val11' AND (a__Parent.""Name"") LIKE '%val22%' OR a__Parent.""Name"" = 'val33' OR a__Parent.""ParentCode"" = 'val44'))", sql);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            sql = fsql.Select<VM_District_Parent>().OrderByPropertyName("Parent.Name").WhereDynamicFilter(JsonConvert.DeserializeObject<DynamicFilterInfo>(@"
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ""Logic"" : ""Or"",
 | 
				
			||||||
 | 
					  ""Filters"" :
 | 
				
			||||||
 | 
					  [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ""Field"" : ""Code"",
 | 
				
			||||||
 | 
					      ""Operator"" : ""NotContains"",
 | 
				
			||||||
 | 
					      ""Value"" : ""val1"",
 | 
				
			||||||
 | 
					      ""Filters"" :
 | 
				
			||||||
 | 
					      [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          ""Field"" : ""Name"",
 | 
				
			||||||
 | 
					          ""Operator"" : ""NotStartsWith"",
 | 
				
			||||||
 | 
					          ""Value"" : ""val2"",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ""Field"" : ""Name"",
 | 
				
			||||||
 | 
					      ""Operator"" : ""NotEndsWith"",
 | 
				
			||||||
 | 
					      ""Value"" : ""val3""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ""Field"" : ""ParentCode"",
 | 
				
			||||||
 | 
					      ""Operator"" : ""NotEqual"",
 | 
				
			||||||
 | 
					      ""Value"" : ""val4""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ""Field"" : ""Parent.Code"",
 | 
				
			||||||
 | 
					      ""Operator"" : ""eq"",
 | 
				
			||||||
 | 
					      ""Value"" : ""val11"",
 | 
				
			||||||
 | 
					      ""Filters"" :
 | 
				
			||||||
 | 
					      [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          ""Field"" : ""Parent.Name"",
 | 
				
			||||||
 | 
					          ""Operator"" : ""contains"",
 | 
				
			||||||
 | 
					          ""Value"" : ""val22"",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ""Field"" : ""Parent.Name"",
 | 
				
			||||||
 | 
					      ""Operator"" : ""eq"",
 | 
				
			||||||
 | 
					      ""Value"" : ""val33""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ""Field"" : ""Parent.ParentCode"",
 | 
				
			||||||
 | 
					      ""Operator"" : ""eq"",
 | 
				
			||||||
 | 
					      ""Value"" : ""val44""
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					")).ToSql();
 | 
				
			||||||
 | 
					            Assert.Equal(@"SELECT a.""Code"", a.""Name"", a.""CreateTime"", a.""testint"", a.""ParentCode"", a__Parent.""Code"" as6, a__Parent.""Name"" as7, a__Parent.""CreateTime"" as8, a__Parent.""testint"" as9, a__Parent.""ParentCode"" as10 
 | 
				
			||||||
 | 
					FROM ""D_District"" a 
 | 
				
			||||||
 | 
					LEFT JOIN ""D_District"" a__Parent ON a__Parent.""Code"" = a.""ParentCode"" 
 | 
				
			||||||
 | 
					WHERE ((not((a.""Code"") LIKE '%val1%') AND not((a.""Name"") LIKE 'val2%') OR not((a.""Name"") LIKE '%val3') OR a.""ParentCode"" <> 'val4' OR a__Parent.""Code"" = 'val11' AND (a__Parent.""Name"") LIKE '%val22%' OR a__Parent.""Name"" = 'val33' OR a__Parent.""ParentCode"" = 'val44')) 
 | 
				
			||||||
 | 
					ORDER BY a__Parent.""Name""", sql);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1943,6 +1943,25 @@
 | 
				
			|||||||
            <param name="parms">参数</param>
 | 
					            <param name="parms">参数</param>
 | 
				
			||||||
            <returns></returns>
 | 
					            <returns></returns>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.ISelect0`2.OrderByPropertyName(System.String,System.Boolean)">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            按属性名字符串排序(支持导航属性)<para></para>
 | 
				
			||||||
 | 
					            属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <param name="property">属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name</param>
 | 
				
			||||||
 | 
					            <param name="isAscending">顺序 | 倒序</param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.ISelect0`2.OrderByPropertyNameIf(System.Boolean,System.String,System.Boolean)">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            按属性名字符串排序(支持导航属性)<para></para>
 | 
				
			||||||
 | 
					            属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <param name="condition">true 时生效</param>
 | 
				
			||||||
 | 
					            <param name="property">属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name</param>
 | 
				
			||||||
 | 
					            <param name="isAscending">顺序 | 倒序</param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
        <member name="M:FreeSql.ISelect0`2.Skip(System.Int32)">
 | 
					        <member name="M:FreeSql.ISelect0`2.Skip(System.Int32)">
 | 
				
			||||||
            <summary>
 | 
					            <summary>
 | 
				
			||||||
            查询向后偏移行数
 | 
					            查询向后偏移行数
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -337,6 +337,23 @@ namespace FreeSql
 | 
				
			|||||||
        /// <param name="parms">参数</param>
 | 
					        /// <param name="parms">参数</param>
 | 
				
			||||||
        /// <returns></returns>
 | 
					        /// <returns></returns>
 | 
				
			||||||
        TSelect OrderBy(bool condition, string sql, object parms = null);
 | 
					        TSelect OrderBy(bool condition, string sql, object parms = null);
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 按属性名字符串排序(支持导航属性)<para></para>
 | 
				
			||||||
 | 
					        /// 属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="property">属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name</param>
 | 
				
			||||||
 | 
					        /// <param name="isAscending">顺序 | 倒序</param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        TSelect OrderByPropertyName(string property, bool isAscending = true);
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 按属性名字符串排序(支持导航属性)<para></para>
 | 
				
			||||||
 | 
					        /// 属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="condition">true 时生效</param>
 | 
				
			||||||
 | 
					        /// <param name="property">属性名:Name<para></para>导航属性:Parent.Name<para></para>多表:b.Name</param>
 | 
				
			||||||
 | 
					        /// <param name="isAscending">顺序 | 倒序</param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        TSelect OrderByPropertyNameIf(bool condition, string property, bool isAscending = true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// 查询向后偏移行数
 | 
					        /// 查询向后偏移行数
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -442,6 +442,60 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
            return this as TSelect;
 | 
					            return this as TSelect;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Expression ConvertStringPropertyToExpression(string property)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (string.IsNullOrEmpty(property)) return null;
 | 
				
			||||||
 | 
					            var field = property.Split('.').Select(a => a.Trim()).ToArray();
 | 
				
			||||||
 | 
					            Expression exp = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (field.Length == 1)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                foreach (var tb in _tables)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (tb.Table.ColumnsByCs.TryGetValue(field[0], out var col) &&
 | 
				
			||||||
 | 
					                        tb.Table.Properties.TryGetValue(field[0], out var prop))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        tb.Parameter = Expression.Parameter(tb.Table.Type, tb.Alias);
 | 
				
			||||||
 | 
					                        exp = Expression.MakeMemberAccess(tb.Parameter, prop);
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (exp == null) throw new Exception($"无法匹配 {property}");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var firstTb = _tables[0];
 | 
				
			||||||
 | 
					                var firstTbs = _tables.Where(a => a.AliasInit == field[0]).ToArray();
 | 
				
			||||||
 | 
					                if (firstTbs.Length == 1) firstTb = firstTbs[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                firstTb.Parameter = Expression.Parameter(firstTb.Table.Type, firstTb.Alias);
 | 
				
			||||||
 | 
					                var currentType = firstTb.Table.Type;
 | 
				
			||||||
 | 
					                Expression currentExp = firstTb.Parameter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (var x = 0; x < field.Length; x++)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var tmp1 = field[x];
 | 
				
			||||||
 | 
					                    if (_commonUtils.GetTableByEntity(currentType).Properties.TryGetValue(tmp1, out var prop) == false)
 | 
				
			||||||
 | 
					                        throw new ArgumentException($"{currentType.DisplayCsharp()} 无法找到属性名 {tmp1}");
 | 
				
			||||||
 | 
					                    currentType = prop.PropertyType;
 | 
				
			||||||
 | 
					                    currentExp = Expression.MakeMemberAccess(currentExp, prop);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                exp = currentExp;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return exp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public TSelect OrderByPropertyName(string property, bool isAscending = true) => OrderByPropertyNameIf(true, property, isAscending);
 | 
				
			||||||
 | 
					        public TSelect OrderByPropertyNameIf(bool condition, string property, bool isAscending = true)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (condition == false) return this as TSelect;
 | 
				
			||||||
 | 
					            Expression exp = ConvertStringPropertyToExpression(property);
 | 
				
			||||||
 | 
					            if (exp == null) return this as TSelect;
 | 
				
			||||||
 | 
					            var field = _commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null);
 | 
				
			||||||
 | 
					            if (isAscending) return this.OrderBy(field);
 | 
				
			||||||
 | 
					            return this.OrderBy($"{field} DESC");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static MethodInfo MethodStringContains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
 | 
					        static MethodInfo MethodStringContains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
 | 
				
			||||||
        static MethodInfo MethodStringStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
 | 
					        static MethodInfo MethodStringStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
 | 
				
			||||||
        static MethodInfo MethodStringEndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
 | 
					        static MethodInfo MethodStringEndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
 | 
				
			||||||
@@ -460,44 +514,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                if (string.IsNullOrEmpty(fi.Field) == false)
 | 
					                if (string.IsNullOrEmpty(fi.Field) == false)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var field = fi.Field.Split('.').Select(a => a.Trim()).ToArray();
 | 
					                    Expression exp = ConvertStringPropertyToExpression(fi.Field);
 | 
				
			||||||
                    Expression exp = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (field.Length == 1)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        foreach (var tb in _tables)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            if (tb.Table.ColumnsByCs.TryGetValue(field[0], out var col) &&
 | 
					 | 
				
			||||||
                                tb.Table.Properties.TryGetValue(field[0], out var prop))
 | 
					 | 
				
			||||||
                            {
 | 
					 | 
				
			||||||
                                tb.Parameter = Expression.Parameter(tb.Table.Type, tb.Alias);
 | 
					 | 
				
			||||||
                                exp = Expression.MakeMemberAccess(tb.Parameter, prop);
 | 
					 | 
				
			||||||
                                break;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        if (exp == null) throw new Exception($"无法匹配 {fi.Field}");
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    else
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        var firstTb = _tables[0];
 | 
					 | 
				
			||||||
                        var firstTbs = _tables.Where(a => a.AliasInit == field[0]).ToArray();
 | 
					 | 
				
			||||||
                        if (firstTbs.Length == 1) firstTb = firstTbs[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        firstTb.Parameter = Expression.Parameter(firstTb.Table.Type, firstTb.Alias);
 | 
					 | 
				
			||||||
                        var currentType = firstTb.Table.Type;
 | 
					 | 
				
			||||||
                        Expression currentExp = firstTb.Parameter;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        for (var x = 0; x < field.Length; x++)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            var tmp1 = field[x];
 | 
					 | 
				
			||||||
                            if (_commonUtils.GetTableByEntity(currentType).Properties.TryGetValue(tmp1, out var prop) == false)
 | 
					 | 
				
			||||||
                                throw new ArgumentException($"{currentType.DisplayCsharp()} 无法找到属性名 {tmp1}");
 | 
					 | 
				
			||||||
                            currentType = prop.PropertyType;
 | 
					 | 
				
			||||||
                            currentExp = Expression.MakeMemberAccess(currentExp, prop);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        exp = currentExp;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    switch (fi.Operator)
 | 
					                    switch (fi.Operator)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        case DynamicFilterOperator.Contains: exp = Expression.Call(exp, MethodStringContains, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value?.ToString()), exp.Type)); break;
 | 
					                        case DynamicFilterOperator.Contains: exp = Expression.Call(exp, MethodStringContains, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value?.ToString()), exp.Type)); break;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user