2016-10-31 26 views
0

我有发送XML存储过程:如何将参数添加到C#中的过滤器存储过程XML?

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[ChartEnergyKPIS] 
    @columns varchar(max), 
    @groupBy varchar(max), 
    @filters varchar(max) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @query varchar(max) 
    SET @query = 'declare @xml XML 

    SET @xml = (SELECT '+ @columns + ' 
       FROM [dbo].[KPIS] k (NOLOCK) 
       INNER JOIN [dbo].[KPISEnergy] ke (NOLOCK) ON k.Id = ke.IdKPI 
       INNER JOIN [dbo].[Meter] m (NOLOCK) ON ke.IdMeter = m.Id 
       ' + @filters + ' ' + 
       @groupBy + ' FOR XML RAW) SELECT @xml'; 

    PRINT @query 
    EXEC(@query) 
END 

,我想要做的是过滤这个XML通过k.BranchOfficeId,在C#类我打电话查询是这样的:

public static string GetChartEnergy(string initDate, string endDate, string type) 
{ 
    string result = string.Empty; 
    var structure = new List<QueryStructure>(); 

    try 
    { 
     structure.Add(initDate.CreateQueryStructure(endDate, true, null, "convert(datetime,'15/' + CONVERT(varchar(10), k.Month) + '/' + CONVERT(varchar(10), k.Year), 103)", null, false)); 
     structure.Add(type.CreateQueryStructure(string.Empty, false, "CASE WHEN m.Type = 1 THEN 'Agua' ELSE CASE WHEN m.Type = 2 THEN 'Luz' ELSE 'Gas' END END AS Type", " m.type", "m.Type", false)); 

     //agrega una columna para sacar el total de registros por filtro 
     structure.Add(new QueryStructure 
       { 
        ColumnSelect = "SUM(ke.Month) AS Total", 
        Operator = Operator.Nothing, 
        ColumnWhere = string.Empty 
       }); 

     result = Chars.GetChartInfo(structure, "ChartEnergyKPIS"); 
    } 
    catch (Exception) 
    { 
     throw; 
    } 

    return result; 
} 

所以我尝试做到这一点很简单,添加滤镜为创建像查询与和currentUser比较我调用方法:

public static string GetChartEnergy(string initDate, string endDate, string type, int currentUser) 
{ 
    string result = string.Empty; 
    var structure = new List<QueryStructure>(); 

    try 
    { 
     structure.Add(initDate.CreateQueryStructure(endDate, true, null, "convert(datetime,'15/' + CONVERT(varchar(10), k.Month) + '/' + CONVERT(varchar(10), k.Year), 103,k.BranchOfficeId = currentUser)", null, false)); 

终于在一类我执行存储过程并获得取决于应用的过滤器的JSON:

public static string GetChartInfo(List<QueryStructure> queryStructure, string procedureName) 
{ 
    string result = string.Empty; 
    string xml = string.Empty; 

    try 
    { 
     var queryWhere = queryStructure.GetWhere(); 
     var columnsQuery = queryStructure.GetSelectGroupBy(true); 
     var groupByQuery = queryStructure.GetSelectGroupBy(false); 

     using (var oContext = new EF.SSMA()) 
     { 
      SqlParameter param1 = new SqlParameter("@columns", columnsQuery); 
      SqlParameter param2 = new SqlParameter("@groupBy", groupByQuery); 
      SqlParameter param3 = new SqlParameter("@filters", queryWhere); 

      xml = oContext.Database.SqlQuery<string>(string.Format("dbo.{0} @columns, @groupBy, @filters", procedureName), param1, param2, param3).First(); 
     } 

     if (!string.IsNullOrEmpty(xml)) 
     { 
      XmlDocument doc = new XmlDocument(); 
      doc.LoadXml(string.Format("<root>{0}</root>", xml)); 
      doc.LoadXml("<root>" + xml + "</root>"); 

      result = Newtonsoft.Json.JsonConvert.SerializeXmlNode(doc); 
      result = result.Replace("{\"root\":{\"row\":", ""); 
      result = result.Replace("}}", ""); 
      result = result.Replace("\"@", "\""); 

      if (result.Substring(0, 1) == "{") 
      { 
       result = string.Format("[{0}]", result); 
      } 
     } 
     else 
     { 
      result = "[]"; 
     } 
    } 
    catch (Exception) 
    { 
     throw; 
    } 

    return result; 
} 

创建查询结构类:

public static QueryStructure CreateQueryStructure(this String value, string endDate, bool isDate, 
     string columnName, string whereName, string groupByName, bool isNullField) 
    { 
     QueryStructure structure = new QueryStructure(); 

     if (!string.IsNullOrEmpty(value)) 
     { 
      if (value != ",") 
      { 
       if (isDate) 
       { 
        //obtiene la estructura para un filtro entre fechas 
        structure.ColumnSelect = columnName; 
        structure.ColumnGroupBy = groupByName; 
        structure.ColumnWhere = string.Format("({0} BETWEEN convert(datetime,\'{1}\', 103) and convert(datetime,\'{2}\', 103))", whereName, value.Remove(value.Length - 1), endDate.Remove(value.Length - 1)); 
        structure.Values = null; 
        structure.Operator = Operator.Nothing; 
       } 
       else 
       { 
        if (isNullField) 
        { 
         //obtiene la estructura de un filtro por un campo que es null o no 
         if (value.Remove(value.Length - 1) != "-1") 
         { 
          structure.ColumnWhere = string.Format("{0} IS{1} NULL", whereName, 
           value.Remove(value.Length - 1) == "0" 
                    ? " NOT" : 
                    string.Empty); 

          structure.Values = null; 
          structure.Operator = Operator.And; 
         } 
        } 
        else 
        { 
         //obtiene la estructura de un campo aplicando la regla IN seleccionando 
         //el campo a mostrar y el campo en groupBy 
         structure.ColumnSelect = columnName; 
         structure.ColumnGroupBy = groupByName; 
         structure.ColumnWhere = whereName; 
         structure.Values = value.Remove(value.Length - 1); 
         structure.Operator = Operator.And; 
        } 
       } 
      } 
     } 

     return structure; 
    } 
+0

你的问题是什么? –

+0

对不起,我如何将参数添加到C#中的Filter存储过程XML? @RobertHarvey – Dawin

+0

SQL Server具有允许您在XML元素上查询的机制。那是你在找什么? https://www.simple-talk.com/sql/learn-sql-server/the-xml-methods-in-sql-server/ –

回答

1

你的错误发生在这里:

structure.Add(initDate.CreateQueryStructure(endDate, true, null, "convert(datetime,'15/' + CONVERT(varchar(10), k.Month) + '/' + CONVERT(varchar(10), k.Year), 103,k.BranchOfficeId = currentUser)", null, false) 

,或者更具体,在这里:

CONVERT(varchar(10), k.Month) + '/' + CONVERT(varchar(10), k.Year), 103,k.BranchOfficeId = currentUser) 

您正在做的是将k.BranchOfficeId = currentUser作为第四个参数添加到CONVERT-功能中。这是'''附近的一个肯定的语法错误。

如果这个附加条件是要东西在任何情况下添加这将是最简单的,你以这种方式设置您的ColumnWhere添加此的地方:

k.BranchOfficeId = currentUser AND (The other condition you use normally) 

但这里是你的下一个问题:它看起来像currentUser是您的应用程序中的一个变量。您必须使用的价值,而不是名称

喜欢的东西

string.Format(" k.BranchOfficeId = {0} AND ({1}) ",currentUser,TheConditionAsItWasBefore) 

希望这有助于...

并坦率地说:这看起来远复杂,容易出现SQL注入和你可能会向人们展示这件事Code Review

相关问题