使用dapper时在哪里放sql?

我在工作中使用dapper进行mvc3项目,我喜欢它。 但是,在使用dapper时,您应该如何对应用程序进行分层? 目前我只是把我所有的sql直接塞进控制器( slap ),但我正在考虑用静态字符串创建一个类..所以我可以做

var reports = Dapper.Query(conn, MySql.ReportsRunningQuery) 

使用dapper时如何存储sql?

我会说把你的SQL放在等效的LINQ查询,或者用于DataContext.ExecuteQuery的sql 。 至于那个……好吧,这取决于你,取决于你想要多少分离。

但是,我个人认为将SQL隐藏在远离Query调用的单独类中没有任何好处 – 您希望在上下文中看到它们,以便您可以轻松validation数据(实际上是参数)。 您可能还在原位构建查询(仍参数化)。 但对于常规静态查询,我会将TSQL保持为代码附近的文字,除非我有充分的理由需要抽象,即

 var reports = conn.Query(@" select x.blah, y.blah from x (snip) where x.ParentId = @parentId and y.Region = @region", new {parentId, region}); 

(另请注意上面的替代扩展方法用法)

IMO,上面的关键是你不可能任何其他地方重新使用该查询 – 逻辑将被放入一个方法,并且该方法从多个地方调用。 因此,如果您需要支持不同的数据库提供程序(使用不同的SQL方言),则可能用于隐藏中央包装器后面的查询的唯一原因是。 这比人们所知道的要少。

使用资源文件对我们非常有用。 我们在文件夹call / Sql中创建.sql文件,并将它们拖到我们的SqlResource对象的’Files’部分。 对于较小的sql片段(例如我们可能正在查询的函数),资源文件的“字符串”部分非常简洁且容易。

所以,我们的sql看起来像:

 var reports = conn.Query(SqlResource.Blahs_get, new {parentId, region}); 

这使存储库真正干净。 将所有sql放在资源文件中还有其他好处,您可以遍历这些条目,并可能使用PARSEONLY查询数据库,以确保如果db对象发生更改,您的查询将会中断(请注意,这主要是但不是100%可靠)。

因此,总而言之,对于我们来说资源文件保持真正干净,但对于Marc Gravell而言,它们不是生产代码中的可重用性……每个sql语句只应由应用程序中的一个点使用。

虽然这个问题现在已经很老了,但我想进一步建议SQL的外部存储。 Visual Studio(至少2015+)具有语法突出显示function,以及* .sql文件的小型调试器和连接管理器。 这些文件可以进一步标记为嵌入式资源,并完全包含在程序集中,但与您的代码分开。 你会厌倦看到非语法validation字符串中嵌入的无色SQL。

我在我最近的所有项目中采用了这种模式,并结合像Dapper这样的ORM,C#和SQL之间的接口变得非常小。 我有一个开源项目,可以在GitHub上扩展Dapper,它可以提供示例,以及NuGet包 。 它还包括一个小胡子启发的字符串替换引擎,它可用于模拟脚本以使其可重用,或插入动态过滤条件。