你在哪里把SQL语句放在你的c#项目中?

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

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

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

那么,你们这样做吗? 你怎么会或者你有没有解决这个问题? 什么最适合你?

谢谢!

嗯,有很多选择 – 所以它真的取决于你最迫切需要的是:-)

一种方法可能是在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查询作为字段。 然后,您可以根据需要检索它们并执行它们。 由于它们位于数据库表中,您还可以随意更改,修复,修改它们 – 即使在运行时 – 也无需重新部署整个应用程序。

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

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

LINQ to DataSet听起来像是你的方式。

如果你没有在/ LINQ之前使用过.NET 3.5,那么你就可以享受一下。 LINQ将节省您在字符串文字中编写原始sql,并为您提供更合理的创建查询的方法。

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

我会告诉我不会把它放在哪里,我在一些inheritance的代码中看到的东西。 它是在Java中,但适用于任何语言

  • 一个基类,使用返回单个SQL语句的get方法,为SQL语句声明受保护的静态成员变量(inited为null)

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

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

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

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

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

 class ConnectToSQL() { //connectSql code (read from setting file i assume) XMLDataDocument runProcedure(string procedureName); int runProcedure(string procedureName); //etc.... } 

如果我不得不为SQL和Access创建应用程序,我将使用一些IDAL接口,具有通用function实现的DALCommon以及从DALCommoninheritance的单独DALSql和DALAccess,以及一些特定的东西,如exception,事务处理,安全性等。
我曾经在资源文件中保存存储过程名称或查询。

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

我只为偶尔的自定义报告应用程序执行此操作,但它总是很好用,感觉清爽和解放。 几个月后回来做一个增强,并在一个SQL.cs文件中找到所有等待你的SQL,这是非常好的。 只需读取一个文件,它就会全部回来,而且这通常是唯一需要更改的文件。

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

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

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

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

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

免责声明:我写了QueryFirst。