我正在使用dapper工作的mvc3项目,我喜欢它。但是,在使用dapper时,您应该如何对应用程序进行分层?目前我只是将所有的sql直接填充到控制器中( slap ),但我正在考虑使用静态字符串创建一个类..所以我可以做到
var reports = Dapper.Query<Report>(conn, MySql.ReportsRunningQuery)
使用dapper时如何存储sql?
答案 0 :(得分:22)
我会说将sql放在你应该放置等效LINQ查询的位置,或者将sql用于DataContext.ExecuteQuery 。至于那个......好吧,那取决于你想要多少分离。
但是,我个人认为将SQL隐藏在远离Query<T>
调用的单独类中没有任何好处 - 您希望在上下文中查看它们,以便您可以轻松验证数据(以及的确,参数)。您可能还在原位构建查询(仍参数化)。但是对于常规静态查询,我会将TSQL保持为代码附近的文字,除非我有有充分理由需要抽象,即
var reports = conn.Query<Report>(@"
select x.blah, y.blah
from x (snip)
where x.ParentId = @parentId and y.Region = @region", new {parentId, region});
(另请注意上面的替代扩展方法用法)
IMO,上面的关键是极不可能您可以从 任何其他地方重新使用该查询 - 逻辑将被放入一个方法,并从多个地方调用该方法。因此,如果您需要支持不同的数据库提供程序(使用不同的SQL方言),则可能用于隐藏查询隐藏在中央包装器后面的唯一其他原因。这比人们想象的要少。
答案 1 :(得分:6)
使用资源文件对我们非常有用。我们在文件夹call / Sql中创建.sql文件,并将它们拖到我们的SqlResource对象的'Files'部分。对于较小的sql片段(例如我们可能正在查询的函数),资源文件的“字符串”部分非常简洁且容易。
所以,我们的sql看起来像:
var reports = conn.Query<Report>(SqlResource.Blahs_get, new {parentId, region});
这使存储库真正干净。将所有sql放在资源文件中还有其他好处,你可以迭代这些条目,并可能使用PARSEONLY查询数据库,以确保如果db对象发生更改,你的查询就会中断(注意这主要是但不是100%可靠)。
因此,总而言之,对于我们来说资源文件保持真正干净,但对于Marc Gravell而言,它们不是生产代码中的可重用性......每个sql语句只应由应用程序中的一个点使用。
答案 2 :(得分:3)
虽然这个问题现在已经相当老化,但我还想进一步建议SQL的外部存储。 Visual Studio(至少2015+)具有语法突出显示功能,以及* .sql文件的小型调试器和连接管理器。这些文件可以进一步标记为嵌入式资源,并完全包含在程序集中,但与您的代码分开。你会厌倦看到嵌入在非语法验证字符串中的无色SQL。
我在我最近的所有项目中采用了这种模式,并结合了像 Dapper 这样的ORM,C#和SQL之间的接口变得非常小。我有一个开源项目,可以在GitHub上提供Dapper,它可以提供示例,以及NuGet Package。它还包括一个小胡子启发的字符串替换引擎,它可用于模拟脚本以使其可重用,或插入动态过滤条件。