30

我可能会负责将 vb6 应用程序移植到 c#。此应用程序是一个与访问数据库交互的 Windows 应用程序。数据访问被封装在基本业务对象中。基本上一桌一课。现有的 vb6 业务对象通过 DAO 读取和写入 DB。我之前写过几次 DAL 和 ORM,但它们都只针对 SQL Server。这将需要针对访问和 sql server。在之前的项目中,我会将 SQL 字符串放在业务对象的私有部分中,并且可能会将多余的 sql 代码(如连接、创建命令)移到公共基类中以减少代码。

这一次,我正在考虑将 SQL 字符串写入 .settings 文件或其他键/值类型的文本文件。然后我会编写一个 sql 实用程序来编辑这个文件并允许我运行和测试参数化查询。这些查询将在业务对象中按名称引用,而不是将 sql 嵌入代码中。

我知道一种标准方法是为每个目标数据库创建一个 DAL,并具有要使用的 DAL 的配置状态。我真的不想为每个数据库创建两个 DAL 类。如果我只是通过键名引用正确的查询并具有正确的连接类型,那么代码似乎会更少。

那么,你们是在做这样的事情吗?您将如何或曾经如何解决这个问题?什么最适合你?

谢谢!

4

9 回答 9

41

好吧,有很多选择 - 所以这真的取决于你最迫切的需求是什么:-)

一种方法可能是在 VS 解决方案中将 SQL 语句创建为文本文件,并在“构建操作”中将它们标记为“嵌入式资源”。这样,SQL 将包含在生成的程序集中,并且可以在运行时使用 .NET 框架的 ResourceManifestStream 从中检索:

private string LoadSQLStatement(string statementName)
{
    string sqlStatement = string.Empty;

    string namespacePart = "ConsoleApplication1";
    string resourceName = namespacePart + "." + statementName;

    using(Stream stm = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
    {
        if (stm != null)
        {
            sqlStatement = new StreamReader(stm).ReadToEnd();
        }
    }

    return sqlStatement;
}

您需要将“ConsoleApplication1”替换为您的实际命名空间,其中 sql 语句文件驻留。您需要通过完全限定名称来引用它们。然后您可以使用以下行加载您的 SQL 语句:

string mySQLStatement = LoadSQLStatement("MySQLStatement.sql");

然而,这使得查询相当“静态”,例如,您无法在运行时配置和更改它们 - 它们被直接烘焙到编译的二进制位中。但另一方面,在 VS 中,您的 C# 程序代码和 SQL 语句之间有一个很好的清晰分离。

如果您需要能够在运行时调整和更改它们,我会将它们放入单个 SQL 表中,其中包含例如关键字和作为字段的实际 SQL 查询。然后,您可以根据需要检索它们并执行它们。由于它们位于数据库表中,因此您也可以随意更改、修复、修改它们——甚至在运行时——而无需重新部署整个应用程序。

马克

于 2009-02-23T06:28:18.023 回答
14

当我真正需要它时,我将查询放入单独的 *.sql 文件中,然后将它们包含在 Resources.resx 中。其中有一个“文件”部分,允许您包含嵌入式资源文件。

之后,我可以使用生成的 Resources.MyQuery 属性,它既保证资源存在,又使我免于编写自定义资源加载方法。

于 2009-02-23T07:52:27.540 回答
2

LINQ to DataSet听起来很适合您。

如果您之前没有使用过 .NET 3.5 / LINQ,那么您就可以大快朵颐了。LINQ 将节省您以字符串文字编写原始 sql,并为您提供一种更合乎逻辑的方式来创建查询。

无论如何,请查看此链接以在 Access 数据库上使用 LINQ - http://msdn.microsoft.com/en-us/library/bb386977.aspx

于 2009-02-23T05:39:05.333 回答
2

如果我必须为 SQL 和 Access 创建应用程序,我会使用一些 IDAL 接口,具有通用功能实现的 DALCommon 以及从 DALCommon 继承的独立 DALSql 和 DALAccess,以及一些特定的东西,如异常、事务处理、安全等.
我曾经在资源文件中保存存储过程名称或查询。

于 2009-02-23T13:22:58.947 回答
1

我会告诉我永远不会把它放在哪里,这是我在继承的一些代码中看到的。它是用 Java 编写的,但适用于任何语言

  • 为 SQL 语句声明受保护的静态成员变量的基类,初始化为 null,具有返回单个 SQL 语句的 get 方法

  • 每个受支持的数据库服务器的子类,具有分配给基类成员变量的 init 方法

  • 使用基类方法检索 SQL 语句的几个 DA 类

  • 应用程序启动类,负责创建正确的子类对象并调用其 init 方法

我也不会解释为什么我永远不会这样做:-)

于 2009-02-23T05:23:33.793 回答
1

我们使用的一种方法是拥有一个可以连接到数据库的类和调用过程的方法,并在方法参数中提供过程名称。所以所有的 SQL 代码都在过程中。我们将为不同的返回类型使用重载

class ConnectToSQL()
{
        //connectSql code (read from setting file i assume)

        XMLDataDocument runProcedure(string procedureName);
        int runProcedure(string procedureName);

        //etc....
}
于 2009-02-23T05:36:53.047 回答
0

有时,就像使用自定义报告应用程序一样,您确实需要接受阻抗不匹配,并特别重视 SQL。在这些情况下,我建议如下: 对于每个包含 SQL 字符串的模块,创建一个静态“SQL”类来保存它们。一些 SQL 字符串可能需要参数,所以要保持一致并将每个字符串放在它自己的静态方法后面。

我只为偶尔的自定义报告应用程序这样做,但它总是效果很好,让人耳目一新和解放。很高兴几个月后回来进行增强,并在单个 SQL.cs 文件中找到所有等待您的 SQL。只需读取一个文件,它就会全部恢复,而且通常这是唯一需要更改的文件。

在这些情况下,我认为不需要将 SQL 隐藏在资源或其他地方。当 SQL 很重要时,它就很重要。有趣的是,现在越来越多的开发人员自由地将 SQL 与 C# 混合在一起,包括我相信这个站点,因为本质上,这就是 LINQ。

最后,与往常一样,确保您不易受到 SQL 注入攻击。特别是如果涉及用户输入,请确保您使用某种参数化并且您没有使用字符串连接。

于 2009-03-08T15:38:40.917 回答
0

如果 SQL Query 有类似的“where”原因,则上面显示的嵌入解决方案可能不起作用,但对于相同的 Query,下一次运行需要 PropertyID='113',因为 PropertyID 是读入的。

于 2013-06-15T22:11:56.090 回答
0

很高兴你问!将您的 sql 放入 QueryFirst .sql 模板中。

它会作为嵌入式资源自动编译到您的应用程序中,但您不在乎。您只需在一个真实的 sql 窗口中编写它,连接到您的数据库,对表和列进行语法验证和智能感知,然后通过生成的Execute()方法使用它,对您的输入和结果使用智能感知。

免责声明:我写了 QueryFirst。

于 2016-10-06T09:57:34.233 回答