【问题标题】:Build sql query object by lambda通过 lambda 构建 sql 查询对象
【发布时间】:2016-09-27 16:23:42
【问题描述】:

任何人都可以建议一个库通过 lambda 表达式构建原始 sql 代码吗? 不建议使用 EF 和 Linq2sql,因为它不提供对查询的控制。

类似的东西。 这是我自己库中的代码。但如果这个案例有其他好的解决方案,我不希望支持。

[Fact]
public void TotalTest()
{
    var countFld = SqlField<Person>.Count(p => p.LastName);
    var select = new SqlSelect<Person>()
        .AddFields(p => p.LastName, p => p.Name)
        .AddFields<Passport>(p => p.Number)
        .AddField(countFld)
        .InnerJoin<Person, Passport>((person, passport) => person.Id == passport.PersonId)
        .Where(SqlFilter<Passport>.From(p => p.Number).IsNotNull().And(p => p.Number).NotEqualTo("3812-808316"))
        .GroupBy(p => p.LastName)
        .Having(SqlFilter<Person>.From<int>(countFld).GreaterThan(2))
        .OrderBy(p => p.LastName);

    var expected =
@"SELECT
    pe.LastName, pe.Name, pa.Number, COUNT(pe.LastName)
FROM
    Person pe
INNER JOIN
    Passport pa ON pe.Id = pa.PersonId
WHERE
    pa.Number IS NOT NULL AND pa.Number <> '3812-808316'
GROUP BY
    pe.LastName
HAVING
    COUNT(pe.LastName) > 2
ORDER BY
    pe.LastName";
    Assert.Equal(expected, select.CommandText);
}

【问题讨论】:

  • 你考虑过实体框架吗?还是您实际上需要 SQL 输出?
  • 我正在使用 Dapper,我需要原始 sql。而且 EF 有时会生成一个非常复杂的查询,并且它不提供对我不喜欢 EF 及其 QueryableProvider 的查询的控制
  • 当您查询构建本手册时,lambda 实际上为您添加了什么?为什么不直接对 TSQL 进行编码?至少你会知道你在运行什么......
  • @MarcGravell,因为 lambda 提供了重构源代码的能力。
  • @Serg046 能够通过按 f2 重命名列并不是重构的结束;实际上,在任何包含进程外部分的代码(如 RDBMS)中,您总是需要知道自己在做什么无论如何。我们在 C# 中广泛使用原始 SQL,重构从来都不是一个痛点。就个人而言,我认为在这种情况下基于编译器的检查的好处被夸大了。现实情况是编译器无法检查您的 RDBMS。

标签: c# sql code-generation sqlbuilder


【解决方案1】:

我已使用 nuget 包将 lib 发布到 GitHub。 它包含基本场景,并将根据需要进行更新。已经支持设置字段、where、group by、have、order by、joins、嵌套查询。

https://github.com/Serg046/LambdaSql

例子:

var qry = new SqlSelect
(
    new SqlSelect<Person>()
        .AddFields(p => p.Id, p => p.Name)
        .Where(SqlFilter<Person>.From(p => p.Name).EqualTo("Sergey"))
    , new SqlAlias("inner")
).AddFields<Person>(p => p.Name);

Console.WriteLine(qry.ParametricSql);
Console.WriteLine("---");
Console.WriteLine(string.Join("; ", qry.Parameters
    .Select(p => $"Name = {p.ParameterName}, Value = {p.Value}")));

输出:

SELECT
    inner.Name
FROM
(
    SELECT
        pe.Id, pe.Name
    FROM
        Person pe
    WHERE
        pe.Name = @w0
) AS inner
---
Name = @w0, Value = Sergey

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多