通用的SQL构建器.NET

7
我正在寻找一种方法,在C#中编写针对不同提供商的SQL语句。 SQL语句区分的典型例子是PostgreSQL中的LIMIT与MSSQL中的TOP。解决像上面两个SQL语法的唯一方法是编写if语句,这取决于用户选择哪个提供程序,或者使用try catch语句作为流程控制(LIMIT不起作用,我尝试TOP)。 我已经看到了LINQ Take方法,但我想知道是否可以在没有LINQ的情况下做到这一点?换句话说,C#是否有一些通用的SQL Provider类,我无法找到可以使用的类?

1
为什么你不想使用LINQ呢? - Mark Byers
有很多种方法可以解决这些差异,你确定使用SQL是解决问题的方式吗?也就是说,找到一种系统,允许你编写一个SQL语句,可以在不同的提供商之间运行? - Lasse V. Karlsen
@Mark Byers:嗯,我经常会以.NET 2为目标,据我所知,LINQ在这方面表现不佳。历史上,这是因为我想能够轻松地移植到Mono,然后我就陷入了困境。由于Mono现在可以很好地使用LINQ,我真的无法给出任何其他的好答案,解释为什么我仍然活在过去.. - Patrick
@Lasse V. Karlsen:在C#中,如何在不使用SQL语句的情况下从SQL数据库获取数据?您有一个示例系统可以解决这些差异吗? - Patrick
1
不,那不是我想要表达的意思。你可以设置一个系统,在这个系统里,你需要编写两个SQL语句,分别针对不同的数据库引擎进行优化,然后将其层叠起来,这样使用它的代码就不需要知道当前使用的是哪个引擎。在这里,可以使用IoC容器或类似的工具。然而,如果你想要/需要采用一种SQL面向不同提供商的方式,那么我已经走过这条路,可能有一些代码可以给你参考。 - Lasse V. Karlsen
5个回答

7
实体框架(Entity Framework)能够针对不同的数据库进行定位。这将使您编写的LINQ语句与两个数据库都兼容。您需要为实体框架找到一个postgresql提供程序,有几种选择。
希望这可以帮助到您。

3

有一个DBLinq

适用于Oracle、PostgreSQL、MySQL、Ingres、SQLite、Firebird和...SQL Server(C# 3.0)的LINQ提供程序

当您使用LINQ to SQL生成查询时,可以查看生成的SQL并保存它。

虽然它不符合您“不使用LINQ”的要求。但是如果您有可用的LINQ,为什么不使用呢?


3
我认为没有“通用的SQL提供程序”。在我们的商店,我们需要支持DB2和SQL Server,因此我们选择实现一个层次结构模式,创建模型、数据访问和业务逻辑类。数据访问层处理与不同数据库管理系统的连接,并加载模型类将其传递给业务逻辑。业务逻辑和模型类不知道数据访问层获取数据的位置。
SQL中的差异是通过数据访问层调用数据库中的存储过程来处理的。我们已经在两个系统中使用适当的语法实现了存储过程。如果我们需要转到另一个数据库,我们只需在新的数据库管理系统上实现必要的过程,一切都应该正常运行。

哎呀,我的第一个踩票。能否解释一下原因?谢谢。 - Marc Tidd
所以基本上,要自己实现? :-) 就我所知,存储过程在数据库中并不是“标准”,尽管它是一个很好的点,因为它可以减少在处理业务逻辑时可能发生的错误。我正在寻找一种方法,例如列出数据库中的表,然后从“任何数据库”中获取特定表中的列,在这种情况下,存储过程并不是很匹配。 - Patrick
我明白了,你的问题没有详细说明需要“发现”数据库对象的要求,这远远超出了SQL实现上的差异。感谢解释,我理解这并不是你想要的,因此做出了负评。 - Marc Tidd
我没有给你的回答点踩。我很感激你的回答,实际上我认为它是一个很好的回答,符合我在问题中指定的要求。 - Patrick
@Patrick,我以为你是在回应我的澄清请求。不管怎样,感谢你的反馈。 - Marc Tidd

1
加入Marc Tidd的想法 - 如果您不想使用Linq,则为每个提供程序创建单独的DAL类,或者使用将在每个DB上实现的存储过程。

是的,解决SQL问题的主要思路是使用存储过程,如果不适合您的解决方案,您不必经过完整的层模式。 - Marc Tidd

0

由于某些原因,我不喜欢Linq作为查询接口,所以我一段时间以前开始创建了一个SQL生成库。请看LambdaSql。 目前它包含基本的select子句和where过滤器场景。已经支持设置字段、where、group by、having、order by、joins和嵌套查询。插入、更新和删除将在以后得到支持。它还包含一些扩展现有行为的要点。例如,Limit就是使用这种方式实现的。

示例:

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

在这里查看更多内容 https://github.com/Serg046/LambdaSql


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接