WebMatrix - 条款中的数据库帮助者

有时需要查询与匹配一系列值匹配的记录的数据库,但您不知道这些值是什么,甚至在设计时有多少值。您可以使用多个或多个动态构建您的Where子句,或者您可以使用子句中的SQL - 除了WebMatrix中当前的数据库帮助者不会使其变得简单。这是关于固定的时间....

以防您毫无清楚地了解通过使用子句解决的问题,这是一个示例方案:您希望允许您的用户从列表中选择任意数量的项目,并使用他们的选择来过滤您的下一个Databse查询上。例如,您可能决定向用户提供一份类别列表,然后在他们选择的所有类别中查找所有书籍。您的起点可能如下所示:

@{
    var. db = Database.Open("Books");
    var. categories = db.Query("Select CategoryId, Category FROM Categories");

}

<!DOCTYPE html>
<html>
    <head>
        <title></title>
    </head>
    <body>
    
    @if(!IsPost){
        <h3>Choose your categories</h3>
        <form method="post">
        @foreach(var. item in categories){
            <input type="checkbox" name="categoryid" value="@item.CategoryId" /> @item.Category<br />
        }
        <input type="submit" value="Choose" />
        </form>
    }
    @if(IsPost){
        <h3>You chose:</h3>
        foreach(var. item in categories){
            @item.Category<br />
        }
    }
    </body>
</html>

运行时,结果页面呈现一系列复选框,允许用户从多个类别中进行选择:

假设用户选择第一个,第三和第五个,要获取相关书籍的SQL可以有两个味道。第一个如下:

选择*从Bookid = 1或Bookid = 3或Bookid = 5的书籍中选择*

采用此方法意味着通过连接多个或语句来动态生成SQL。生成这种语句的代码可以变得凌乱,但通常会发现,大多数常常导致开发人员连接到不安全的SQL中的用户输入。第二种方法是使用子句:

选择*来自书籍中的书籍(1,3,5)

一个在子句中采用逗号分隔的值字符串,如果您查看第一个代码示例,则会看到每个复选框给出相同的名称属性:"categoryId"。当表单发布到倍数相同命名的元素时,结果将作为逗号分隔的字符串传递,因此在发布后,请求["categoryId"] give us "1,3,5"。但是,只需插入请求["categoryId"作为参数值,不起作用。这将为您提供错误:

var. books = db.Query("选择*从书籍中的书籍(@ 0)", 要求["categoryId"]);

子句中的每个值都需要自己参数化。你真正需要最终需要的东西是如此:

var. books = db.Query("选择*来自书籍中的书籍(@ 0,@ 1,@ 2)",value1,value2,value3);

网页巧妙地巧妙地看到参数值1,value2和value3是需要在运行时传递到参数占位符的单独项目。这是因为Database.Query()方法的第二个参数接受对象数组。因此,任务是生成正确数量的参数占位符,并将数组传递为第二个参数。考虑到逗号分隔的字符串,这是您可以做到的方式:

@{
    var. db = Database.Open("Books");
    var. categories = db.Query("Select CategoryId, Category FROM Categories");
    if(IsPost){
        var. 临时 = Request["compouttsid."].Split(new[]{','}, StringSplitOptions.RemoveEmptyEntries);
        var. parms = temp.Select((s, i) => "@" + i.ToString()).ToArray();
        var. inclause = string.Join(",", parms);
        var. sql = "SELECT Category FROM Categories WHERE CategoryId IN ({0})";
        categories = db.Query(String.Format(sql, inclause), temp);
    }

代码采用逗号分隔的字符串,并从中生成一个数组,该数组存储在变量中"temp"。创建了一个第一个阵列,其中包含启动字符串"@0"然后,此数组将转换为表示SQL中参数占位符的字符串。然后使用String.Format融合了核心SQL,以及"temp"阵列传入。它有效:

然而,它有点不整洁,所以请在这里使用辅助方法。创建一个名为app_code的文件夹,然后添加一个新的C#类文件。我打电话给我的databaseee伸展。该文件的完整代码如下:

using System;
using System.Collections.Generic;
using WebMatrix..Data;
using System.Linq;

public static class DatabaseExtensions
{
    public static IEnumerable<dynamic> QueryIn(Database db, string commandText, string values)
    {
        if(string.IsNullOrEmpty(values))
            throw new ArgumentException("Value cannot be null or an empty string", "values");
        var. 临时 = values.Split(new[]{','}, StringSplitOptions.RemoveEmptyEntries);
        var. parms = temp.Select((s, i) => "@" + i.ToString()).ToArray();
        var. inclause = string.Join(",", parms);
        return db.Query(string.Format(commandText, inclause), temp);
    }
    
    public static int ExecuteIn(Database db, string commandText, string values)
    {
        if(string.IsNullOrEmpty(values))
            throw new ArgumentException("Value cannot be null or an empty string", "values");
        var. 临时 = values.Split(new[]{','}, StringSplitOptions.RemoveEmptyEntries);
        var. parms = temp.Select((s, i) => "@" + i.ToString()).ToArray();
        var. inclause = string.Join(",", parms);
        return db.Execute(string.Format(commandText, inclause), temp);
    }
}

这些方法扩展了数据库类以提供对条款的支持。它们有效地添加了两种新方法 - Database.Queryin()和database.executein()。两种方法中的第一个参数用单词前缀"this",它表示要扩展的对象。其余方法采用所有关联的代码在实际的.cshtml文件中从剃刀部分中创建阵列,以便可以像这样替换:

@{
    var. db = Database.Open("Books");
    var. categories = db.Query("Select CategoryId, Category FROM Categories");
    if(IsPost){
        var. sql = "SELECT Category FROM Categories WHERE CategoryId IN ({0})";
        categories = db.QueryIn(sql, Request["compouttsid."]); 
    }
}