我正在构建用户在SQL Server数据库上执行即席查询的功能。生成的查询将采用以下基本形式:
SELECT <ONE TO MANY USER SELECTED FIELDS>
FROM <ONE TO MANY TABLES DETERMINED BY FIELDS SELECTED BY USER>
WHERE <ZERO TO MANY CRITERIA FOR THE SELECTED FIELDS>
这保证了选择很可能跨越多个表。 某些(并非所有)字段可能具有0或更多特定字段的过滤条件。
我的应用程序使用C#在ASP.NET MVC 2中使用默认的EF4类。我目前正在传递一个名为QueryItem
的对象,其中包含特定条件的所有信息。
我的问题是:
注意:我打算将其重构为SQLParameter对象,以防止SQL注入。我现在的目标是首先开发查询的最佳做法。
QueryItem类:
public class QueryItem
{
public bool IsIncluded { get; set; }
public bool IsRequired { get; set; }
public string LabelText { get; set; }
public string DatabaseLoc { get; set; }
public List<string> SelectedValue { get; set; }
public List<SelectListItem> SelectList { get; set; }
}
查询解析代码
foreach(QueryItem qi in viewModel.StandardQueryItems)
{
string[] dLoc = qi.DatabaseLoc.Split(new Char[] { '.' }); //Split the table.fieldname value into a string array
if(qi.IsIncluded == true) //Check if the field is marked for inclusion in the final query
{
fields.Append(qi.DatabaseLoc + ","); //Append table.fieldname to SELECT statement
if(!tables.ToString().Contains(dLoc[0])) // Confirm that the table name has not already been added to the FROM statement
{
tables.Append(dLoc[0] + ","); //Append the table value to the FROM statement
}
}
if(qi.SelectedValue != null)
{
if(qi.SelectedValue.Count == 1)
{
query.Append(qi.DatabaseLoc + " = '" + qi.SelectedValue[0].ToString() + "'");
}
else
{
foreach(string s in qi.SelectedValue)
{
//Needs to handle "IN" case properly
query.Append(qi.DatabaseLoc + " IN " + qi.SelectedValue.ToString());
}
}
}
}
答案 0 :(得分:0)
我通过将一个参数传递给xml类型的存储过程,构建了一个类似于过去描述的系统。通过这样做,您可以实际指定(以xml为单位),您想要报告的内容并构建返回所需结果所需的SQL。
这也使您的C#代码更容易,因为您所要做的就是生成一些您的过程将读取的xml。生成动态SQL绝对不是你应该使用的东西,除非你必须这样做,但当你想让用户动态选择他们想要报告的内容时,它几乎是唯一的方法。
您的另一个选择可能是查看Reporting Services - 这将允许用户选择他们想要查看的字段,并将特定的“报告”保存在他们自己的部分中,然后他们可以返回并再次运行它任何时候..如果他们不精通计算机,你也可以为他们创建报告(这对于报表生成器来说要容易得多,只要他们需要的只是数据而没有特殊功能)。
无论哪种方式,它们都是两种解决方案的利弊。你必须确定哪种方案最适合你。
xml / dynamic sql:难以维护/进行更改。(对于那些不得不支持生成动态sql的人并尝试理解混乱背后的逻辑的人,我感到很遗憾。)
报告服务:很容易吐出看起来不错的报告,但它的灵活性稍差,而且不是免费的。