使用C#,SQL构建灵活的参数化adhoc查询

时间:2011-01-31 23:34:58

标签: tsql linq-to-sql entity-framework parameters

我正在构建用户在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的对象,其中包含特定条件的所有信息。

我的问题是:

  1. 编码的最佳方法是什么? (我在下面提到的代码样本)。
  2. 可以使用Linq2SQL完成,还是应该使用ADO.NET(我当前的方法)
  3. 如果ADO.NET是最好的方法,那么如何在EF4中访问DBConnection?
  4. 注意:我打算将其重构为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());
                    }
                }
            }
        }
    

1 个答案:

答案 0 :(得分:0)

我通过将一个参数传递给xml类型的存储过程,构建了一个类似于过去描述的系统。通过这样做,您可以实际指定(以xml为单位),您想要报告的内容并构建返回所需结果所需的SQL。

这也使您的C#代码更容易,因为您所要做的就是生成一些您的过程将读取的xml。生成动态SQL绝对不是你应该使用的东西,除非你必须这样做,但当你想让用户动态选择他们想要报告的内容时,它几乎是唯一的方法。

您的另一个选择可能是查看Reporting Services - 这将允许用户选择他们想要查看的字段,并将特定的“报告”保存在他们自己的部分中,然后他们可以返回并再次运行它任何时候..如果他们不精通计算机,你也可以为他们创建报告(这对于报表生成器来说要容易得多,只要他们需要的只是数据而没有特殊功能)。

无论哪种方式,它们都是两种解决方案的利弊。你必须确定哪种方案最适合你。

xml / dynamic sql:难以维护/进行更改。(对于那些不得不支持生成动态sql的人并尝试理解混乱背后的逻辑的人,我感到很遗憾。)

报告服务:很容易吐出看起来不错的报告,但它的灵活性稍差,而且不是免费的。