SqlFunc.Subqueryable.Where(Expression) 报错 返回

SqlSugar 处理完成
12 156
该叫什么 n27741 发布于1周前
悬赏:0 飞吻
private void button5_Click(object sender, EventArgs e)
{

    //程序启动时配置
    SqlSugar.SqlSugarClient client = new SqlSugarClient(new ConnectionConfig
    {
        DbType = DbType.SqlServer,
        ConnectionString = "......链接字符串",
        IsAutoCloseConnection = true,
    });

    using (client)
    {
        string sql = "True";
        var expression1 = BuildExpression<View_ReportQuery>(sql);

        // 通过反射访问 Parameters 集合
         

        // 这段代码没有问题
        var list1 = client.Queryable<View_ReportQuery>().Where(expression1).ToPageList(0,10);


        // 这段代码报错 <<<<< 
        /*
         *System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
           at System.String.Substring(Int32 startIndex, Int32 length)
           at SqlSugar.ExpressionContext.GetTranslationColumnName(String columnName)
           at SqlSugar.SubAnd.GetValue(Expression expression)
           at SqlSugar.SubResolve.<>c__DisplayClass10_0.<GetSubItems>b__6(ISubOperation it)
           at System.Linq.Enumerable.SelectListIterator`2.ToList()
           at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
           at SqlSugar.SubResolve.GetSubItems()
           at SqlSugar.SubResolve.GetSql()
           at SqlSugar.MethodCallExpressionResolve..ctor(ExpressionParameter parameter)
           at SqlSugar.BaseResolve.Start()
           at SqlSugar.LambdaExpressionResolve..ctor(ExpressionParameter parameter)
           at SqlSugar.BaseResolve.Start()
           at SqlSugar.ExpressionContext.Resolve(Expression expression, ResolveExpressType resolveType)
           at SqlSugar.QueryBuilder.GetExpressionValue(Expression expression, ResolveExpressType resolveType)
           at SqlSugar.QueryableProvider`1._Where(Expression expression)
           at SqlSugar.QueryableProvider`1.Where(Expression`1 expression)
         *
         */
        var list2 = client.Queryable<View_ReportList>().Where(t=> 
            SqlFunc.Subqueryable<View_ReportQuery>().Where(expression1).Where(s=>s.StudyKey == t.StudyKey).Any())
            .ToPageList(0, 10);


        Expressionable<View_ReportQuery> expressionable = new Expressionable<View_ReportQuery>();
        expressionable.And(t => true);
        var expression2 = expressionable.ToExpression();
        // 这段代码正常
        var list3 = client.Queryable<View_ReportList>().Where(t => SqlFunc.Subqueryable<View_ReportQuery>()
            .Where(expression2)
            .Where(s => s.StudyKey == t.StudyKey)
            .Any()).ToPageList(0, 10);

    }
}

public static Expression<Func<T, bool>> BuildExpression<T>(string queryDynamicExpression) where T : class, new()
{
    if (!string.IsNullOrWhiteSpace(queryDynamicExpression))
    {
        
        var queryExpression = (Expression<Func<T, bool>>)
            DynamicExpressionParser.ParseLambda(typeof(T), typeof(bool),
                queryDynamicExpression);

        return queryExpression;
    }

    return null;
}


我发现,用dynamiclinq的

DynamicExpressionParser

将一个表达式转换为Expression之后,在queryable.Where 中执行正常,在 

 SqlFunc.Subqueryable<View_ReportQuery>().Where(expression1)

执行就报异常。


但是用

Expressionable

构建的相同的Expression

 SqlFunc.Subqueryable<View_ReportQuery>().Where(expression2)

执行又是正常,请问这个问题怎么解决啊?


我注意到

expression1.Parameters[0].Name 是空字符串

expression2.Parameters[0].Name 是字符串t

有没有可能是这里导致的问题?


如何让expression1.Parameters[0].Name有值?


热忱回答12

  • https://www.donet5.com/Home/Doc?typeId=2314 尽量用自带的表格查询

    0 回复
  • 或者提供完整DEMO

    0 回复
  • @fate sta

    WinFormsApp1.zip


    建表脚本


     CREATE TABLE Student

      (

        id int,

        Name varchar(20)

      )

      go

      insert into Student (id,Name) values (1,'s1')

      insert into Student (id,Name) values(2,'s2')

      go



    点击3号按钮即可看到错误。谢谢回复。

    0 回复
  •  

    我发现了,应该是 ParameterExpressionName 导致的问题。


    dynamic linq 可以设置RenameEmptyParameterExpressionNames = true,指定一个随机的ParameterExpressionName。既可以执行SqlFunc.Subqueryable<View_ReportQuery>().Where(exp)


            public static Expression<Func<T, bool>> BuildExpression<T>(string queryDynamicExpression) where T : class, new()
            {
                if (!string.IsNullOrWhiteSpace(queryDynamicExpression))
                {
                    ParsingConfig ps = new ParsingConfig()
                    { 
                       RenameEmptyParameterExpressionNames = true,
                    };
                    var queryExpression = (Expression<Func<T, bool>>)
                        DynamicExpressionParser.ParseLambda<T, bool>(ps, true,
                            queryDynamicExpression);
    
                    return queryExpression;
                }
    
                return null;
            }


    @n27741

    0 回复
  •   //启动时配置
      SqlSugar.StaticConfig.DynamicExpressionParserType = typeof(DynamicExpressionParser);
      
      
      //直接用
      var exp= DynamicCoreHelper.GetWhere<Student>("it", $"it.Id=={1}");


    0 回复
  • 用现成的就行了ORM有封装

    0 回复
  • @fate sta


    请教,GetWhere 方法要求,一个shortName 和 FormattableString WhereSql


    但是我的需求是,写  Name == "Test" 或者 1==1 这样的表达式。那么WhereSql 是不是不好用了?

    0 回复
  • @n27741:都可以用

    0 回复
  • FormattableString 这个类型只要会玩了就全会了。

    0 回复
  • @fate sta


    您说的是这个意思吗?如果写1==1,或者 Name=="test"

                    var formattableString = FormattableStringFactory.Create(queryDynamicExpression, new object[] { });
                    var exp = DynamicCoreHelper.GetWhere<T>("t", formattableString);
                    return exp;


    0 回复
  • 是的 

    0 回复
  • @fate sta:收到,谢谢。

    0 回复