【问题标题】:How do I escape special characters when using ServiceStack OrmLite with SQLite?将 ServiceStack OrmLite 与 SQLite 一起使用时,如何转义特殊字符?
【发布时间】:2014-05-01 15:55:39
【问题描述】:

我们有一段代码尝试将模式与数据库中的数据进行匹配。

我们对我们的 SQLite 数据库使用 ServiceStack.OrmLite。

例如,给定以下记录:

ColA    ColB
-----   ---------
ABC     ABC_Long
GHI     GHI_Long
GHIP    GHIP_Long

我们使用谓词:

var result = db.Select(x => x.ColA.StartsWith("GHI_")); 

在我们有一个包含 SQL 特殊字符(例如 '%' 或 '_' )的搜索模式之前一切正常,例如给定搜索模式“GHI_”:

预期的行应该是:

GHI     GHI_Long

然而我们得到:

GHI     GHI_Long
GHIP    GHIP_Long

这是由于 ORMLite 没有转义特殊字符并生成以下 SQL:

SELECT * FROM myTable WHERE UPPER(colA) LIKE 'GHI_%' OR UPPER(colB) LIKE 'GHI_%';

而不是正确转义的版本应该是:

SELECT * FROM myTable WHERE UPPER(colA) LIKE 'GHI\_%' OR UPPER(colB) LIKE 'GHI\_%' ESCAPE '\';

你能想办法解决这个问题吗?

【问题讨论】:

    标签: c# sqlite servicestack ormlite-servicestack


    【解决方案1】:

    我刚刚添加了对escaping wildcards in this commit 的隐式支持,现在它将在使用LIKE 的类型表达式中转义通配符,即StartsWithEndsWithContains,例如:

    using (var db = OpenDbConnection())
    {
        db.DropAndCreateTable<Poco>();
    
        db.Insert(new Poco { Name = "a" });
        db.Insert(new Poco { Name = "ab" });
        db.Insert(new Poco { Name = "a_c" });
        db.Insert(new Poco { Name = "a_cd" });
        db.Insert(new Poco { Name = "abcd" });
        db.Insert(new Poco { Name = "a%" });
        db.Insert(new Poco { Name = "a%b" });
        db.Insert(new Poco { Name = "a%bc" });
        db.Insert(new Poco { Name = "a\\" });
        db.Insert(new Poco { Name = "a\\b" });
        db.Insert(new Poco { Name = "a\\bc" });
    
        Assert.That(db.Count<Poco>(q => q.Name == "a_"), Is.EqualTo(0));
        Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a_")), Is.EqualTo(2));
        Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a%")), Is.EqualTo(3));
        Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a_c")), Is.EqualTo(2));
        Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a\\")), Is.EqualTo(3));
        Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a\\b")), Is.EqualTo(2));
    }
    

    这将在 v4.0.19 中可用,即now available on MyGet

    【讨论】:

    • 太棒了。感谢您的超快速响应。
    • @mythz,是否有计划公开 api 以在没有“上层”功能的情况下发出类似的请求?我需要这个来优化带有索引搜索的 sql server 请求,这不是 "upper" 的选项。
    • @VictorSuzdalev 我可能不得不将此选项设置为可配置的,因为更改它将是一项重大更改。
    • @VictorSuzdalev 好的,刚刚在this commit 中添加了对OrmLiteConfig.StripUpperInLike 的支持。注意:使用upper() 可以在不同的数据库提供者之间提供一致的行为,因为它们对于LIKE 可以有不同的区分大小写的行为,这也受外部环境设置的影响。
    【解决方案2】:

    OrmLite 没有内置此功能,但它确实允许您在需要时轻松提供正确的 SQL。你可以简单地做这样的事情:

    var notes = db.Select<NoteDto>(" upper(\"NoteText\") like 'GHI@_%' ESCAPE '@' ");
    

    通过这种方式,您只需要编写 where 子句,您仍然可以获得 DTO 自动填充的好处。

    为了清楚起见,我更改了转义字符并证明它可以是 SQLite 中的任何内容。

    【讨论】:

    • 感谢您的回答,我们避免编写直接 SQL,而是创建 OrmLite 然后将其转换为 SQL 查询的谓词,因此我们将有一个返回 Expression> 的方法,所以我们非常希望有一个解决现有谓词用法的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多