我有一个发送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
我要做的是通过k.BranchOfficeId
过滤XML,在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;
}
您的错误发生在这里:
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上的人