C# 是否对导致问题的字符串值进行简洁的参数化查询?

C# 是否对导致问题的字符串值进行简洁的参数化查询?,c#,sql,sql-server,dapper,C#,Sql,Sql Server,Dapper,我有下面这个方法1查询,它是使用dapper参数化的,问题是使用这种方法,即使在等待30秒之后,查询也会超时,通常在使用纯sql的SSM上最多需要1秒 然而,方法2查询实际上在查询构建在服务器端而不是参数化查询的情况下工作。我注意到的一件事是,它可能与FirstName和LastName的筛选器有关,我在方法2中对这些筛选器引用了单引号,但对方法1没有引用 方法1有什么问题 Method # 1 string query = "SELECT * FROM dbo

我有下面这个方法1查询,它是使用dapper参数化的,问题是使用这种方法,即使在等待30秒之后,查询也会超时,通常在使用纯sql的SSM上最多需要1秒

然而,方法2查询实际上在查询构建在服务器端而不是参数化查询的情况下工作。我注意到的一件事是,它可能与FirstName和LastName的筛选器有关,我在方法2中对这些筛选器引用了单引号,但对方法1没有引用

方法1有什么问题

Method # 1

string query = "SELECT *
                FROM dbo.Customer c                
                WHERE c.MainCustomerId = @CustomerId 
                AND (@IgnoreCustomerId = 1 OR c.CustomerID = @FilterCustomerId)
                AND (@IgnoreFirstName = 1 OR c.FirstName = @FilterFirstName)
                AND (@IgnoreLastName = 1 OR c.LastName = @FilterLastName)
                AND (@IgnoreMemberStatus = 1 OR c.CustomerStatusID = @FilterMemberStatus)
                AND (@IgnoreMemberType = 1 OR c.CustomerTypeID = @FilterMemberType)
                AND (@IgnoreRank = 1 OR c.RankID = @FilterRank)
                ORDER BY c.CustomerId
                OFFSET @OffSet ROWS
                FETCH NEXT 50 ROWS ONLY";       



                _procExecutor.ExecuteSqlAsync<Report>(query, new
            {
                CustomerId = customerId,
                IgnoreCustomerId = ignoreCustomerId,
                FilterCustomerId = filter.CustomerID,
                IgnoreFirstName = ignoreFirstName,
                FilterFirstName = filter.FirstName,
                IgnoreLastName = ignoreLastName,
                FilterLastName = filter.LastName,
                IgnoreMemberStatus = ignoreMemberStatus,
                FilterMemberStatus = Convert.ToInt32(filter.MemberStatus),
                IgnoreMemberType = ignoreMemberType,
                FilterMemberType = Convert.ToInt32(filter.MemberType),
                IgnoreRank = ignoreRank,
                FilterRank = Convert.ToInt32(filter.Rank),
                OffSet = (page - 1) * 50
            });


    Method # 2      

            string queryThatWorks =
                            "SELECT *
                 FROM dbo.Customer c                
                WHERE c.MainCustomerId = @CustomerId 
                AND ({1} = 1 OR c.CustomerID = {2})
                AND ({3} = 1 OR c.FirstName = '{4}')
                AND ({5}= 1 OR c.LastName = '{6}')
                AND ({7} = 1 OR c.CustomerStatusID = {8})
                AND ({9} = 1 OR c.CustomerTypeID = {10})
                AND ({11} = 1 OR c.RankID = {12})
                ORDER BY c.CustomerId
                OFFSET {13} ROWS
                FETCH NEXT 50 ROWS ONLY";

                _procExecutor.ExecuteSqlAsync<Report>(string.Format(queryThatWorks,
                customerId,
                ignoreCustomerId,
                filter.CustomerID,
                ignoreFirstName,
                filter.FirstName,
                ignoreLastName,
                filter.LastName,
                ignoreMemberStatus,
                 Convert.ToInt32(filter.MemberStatus),
                 ignoreMemberType,
                 Convert.ToInt32(filter.MemberType),
                 ignoreRank,
                  Convert.ToInt32(filter.Rank),
                 (page - 1) * 50
                ), null);

我已经看过无数次了

我愿意打赌您的列是varChar,但Dapper正在以nVarChar的形式发送您的参数。发生这种情况时,SQL Server必须对存储在每一行中的值进行转换。除了速度非常慢之外,这还阻止您使用索引


请参见

中的Ansi字符串和varchar。您知道如何获取执行计划XML吗?如果是,请张贴。这始终是解决这类问题的第一步。因为一个查询是通过dapper参数化的,另一个是普通sql,我可以得到普通sql的执行计划,但运行速度很快。对于参数化的,我不确定是否可以生成执行计划要获得Dapper的执行计划,请使用SQL Profiler工具。这将捕获发送到数据库的实际SQL。从那里你可以将它粘贴到SSM中,并获得正常的计划。出于好奇,为什么你使用“ignoreColumn”方法而不是简单地测试可空性:@firstName为NULL或c.firstName=@firstName…只会大大减少参数数量。这就是为什么我要创建自己的ORM,Tortuga链。在进行常规查询时,它将自动检测要使用的参数类型。