【问题标题】:Why won't C# accept a (seemingly) perfectly good Sql Server CE Query?为什么 C# 不接受(看似)完美的 Sql Server CE 查询?
【发布时间】:2013-07-02 13:44:16
【问题描述】:

完美的 sql 查询,我的意思是说,在 WebMatrix 内部,如果我执行以下查询,它会完美运行:

SELECT page AS location, (len(page) - len(replace(UPPER(page), UPPER('o'), ''))) / len('o') AS occurences, 'pageSettings' AS tableName FROM PageSettings WHERE page LIKE '%o%'
UNION
SELECT pageTitle AS location, (len(pageTitle) - len(replace(UPPER(pageTitle), UPPER('o'), ''))) / len('o') AS occurences, 'ExternalSecondaryPages' AS tableName FROM ExternalSecondaryPages WHERE pageTitle LIKE '%o%' 
UNION
SELECT eventTitle AS location, (len(eventTitle) - len(replace(UPPER(eventTitle), UPPER('o'), ''))) / len('o') AS occurences, 'MainStreetEvents' AS tableName FROM MainStreetEvents WHERE eventTitle LIKE '%o%'

这里我使用'o' 作为静态搜索字符串进行搜索。没问题,但不是非常动态。

现在,当我将这个查询写成 C# 中的字符串时,并且我认为它应该是(甚至我之前做过)时,我收到一个服务器端错误,表明该字符串的格式不正确。这是该错误的图片:

而且(虽然我只是在测试输出,我是否应该让它退出错误),这里是查询数据库的实际 C#(即.cshtml)页面:

@{
    Layout = "~/Layouts/_secondaryMainLayout.cshtml";    

    var db = Database.Open("Content");
    string searchText = Request.Unvalidated["searchText"];
    string selectQueryString = "SELECT page AS location, (len(page) - len(replace(UPPER(page), UPPER(@0), ''))) / len(@0) AS occurences, 'pageSettings' AS tableName FROM PageSettings WHERE page LIKE '%' + @0 + '%' ";
    selectQueryString += "UNION ";
    selectQueryString += "SELECT pageTitle AS location, (len(pageTitle) - len(replace(UPPER(pageTitle), UPPER(@0), ''))) / len(@0) AS occurences, 'ExternalSecondaryPages' AS tableName FROM ExternalSecondaryPages WHERE pageTitle LIKE '%' + @0 + '%' ";
    selectQueryString += "UNION ";
    selectQueryString += "SELECT eventTitle AS location, (len(eventTitle) - len(replace(UPPER(eventTitle), UPPER(@0), ''))) / len(@0) AS occurences, 'MainStreetEvents' AS tableName FROM MainStreetEvents WHERE eventTitle LIKE '%' + @0 + '%'";

    @:beginning <br/>
    foreach (var row in db.Query(selectQueryString, searchText))
    {
        @:entry
        @:@row.location &nbsp;
        @:@row.occurences &nbsp;
        @:@row.tableName
        <br/>
    }
}

由于它在foreach (var row in db.Query(selectQueryString, searchText)) 行上出错,这严重表明我的查询有问题,但是,这里的语法对我来说一切似乎都是正确的,如果我查询数据库,它甚至可以完美执行(请注意,未参数化)直接。

从逻辑上讲,我会假设我在参数化此查询所涉及的语法上犯了错误,但是,我的双重和三重检查(以及我过去这样做的经验)坚持一切看起来都很好。

我是否弄乱了参数化此查询所涉及的语法,还是我忽略了其他在起作用的东西?

我知道我可以肯定地告诉你,正如之前已经测试过的那样,我从查询字符串中得到的值确实是我所期望的,但实际上并不多.cshtml 页面上的其他内容,我能告诉你的就这些了。

【问题讨论】:

  • 如果您传递给.Query() 的参数对象类型与SQL @0 变量的预期不匹配,通常会发生此错误。在这种情况下,我想知道在查询字符串中的多个位置指定相同的参数是否有效。
  • 是因为有0而不是o吗?真的只是一个平底船
  • @ebyrob 实际上,这是合法的,因为我以前使用过它(谢天谢地)。但是待机,我想我其实已经找到了问题所在。将在一秒钟内发布。

标签: c# sql sql-server-ce webmatrix asp.net-webpages


【解决方案1】:

在我在这里发布一个问题之后找到我为期 2 天的寻找解决方案的答案,但是唉,当仔细查看我使用的一些旧代码时,我发现在LIKE 短语中我实际上使用了CAST 这样,如果在我上面的示例中的 LIKE 短语中使用,它看起来像这样:

LIKE '%' + CAST(@0 AS nvarchar) + '%'

我认为常规 C# 字符串与 sql nvarchar 数据类型不同。

对于任何可能从更准确的解释中受益的任何人(包括我自己)可能会对此有更多了解的人(也就是说,如果它除了简单的“它只是不同的数据类型”解释)。

(注意:如果它有助于任何未来的观众知道,LIKE 短语中的参数是我更改的 ALL。我不必强制转换或更改有关参数中涉及的语法的任何内容写在 LIKE 短语之外)。

【讨论】:

    【解决方案2】:

    这是一个长镜头,但可能会有所启发。尝试执行以下查询并读取结果:

    select top 1 sql_variant_property(@0, 'BaseType') as type from MainStreetEvents;
    

    对于任何未出错的传递对象参数,您应该获取有关用于表示它的 sql 类型的信息。

    【讨论】:

    • 这是一个非常好的主意,但SQL Server CE 似乎无法识别sql_variant_property。同样,尽管这是一个测试的好主意。
    • @VoidKing 拍摄。我唯一能想到的另一件事是运行与服务器的未加密 tcp 连接并嗅探连接以查看进入 SQL Server 的原始命令是什么样的。 (可能在你的设置中都是本地的,对吧?为什么还要运行 SQL CE?)
    • 嗯,实际上,虽然在开发过程中它完全是本地的,但我必须不断更新我迄今为止在服务器环境中设计的内容,以便我可以测试网站的外观(和行为) 32 位机器(即,机器上的 32 位浏览器)。你会用什么来嗅探 tcp 数据包,比如 WireShark?我在考虑合适的程序吗?
    • @VoidKing 是的,wireshark...但诀窍是使用不难阅读的 SQL 驱动程序/连接字符串(尽管 wireshark 可能有一些 SQL 内容的解析器)
    • 非常感谢,我会看看的。而且,非常聪明的方法可以找到 C# 字符串和 sql-server-CE 的 nvarchar 数据类型之间差异背后的真相,顺便说一句。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多