使用存储过程时哪种ORM最佳

我有Business对象(DEVELOPERS WRITE)和一些SPROCS(DBA WRITE)

任何人都可以推荐一个好的对象映射器来处理这种设置。

我尝试了代码匠和nhibernate并遇到了麻烦。 我不介意我的ORM是免费的还是付费的。

SubSonic对sprocs有很好的支持。 它将每个都包装在一个帮助器方法中,如果需要,您可以从结果中检索强类型集合或实体。 我在这篇博客文章中展示了一种方法。 只要你的sproc返回与SELECT * FROM TableName相同的模式,它就可以与你的SubSonic实体一起使用。

至于基于db生成类,SubSonic会生成部分类,因此您可以根据需要扩展它们。 您还可以从SubSonic生成的类到您的实际模型进行映射。

Subsonic有一个灵活的解决方案:

class CustomerOrder { private string productName; public string ProductName { get { return productName; } set { productName = value; } } private int total; public int Total { get { return total; } set { total = value; } } } 

然后:

 List orders = Northwind.SPs.CustOrderHist("ALFKI") .ExecuteTypedList(); 

亚力士是一款坚固的“瑞士军刀”式ORM。

免责声明:我是Dapper的作者。


如果您正在寻找一个简单的对象映射器来处理业务对象的映射过程,那么Dapper非常适合。

请记住,它没有“图形管理”,“身份图”等。 它提供了一个完整的解决方案,涵盖了其他ORM所不具备的许多场景。

尽管如此,它提供了最快的对象物化器之一,在某些基准测试中可以比EF快10倍,甚至比亚音速快100倍。


琐碎的:

 create proc spGetOrder @Id int as select * from Orders where Id = @Id select * from OrderItems where OrderId = @Id 

可以使用以下内容进行映射:

 var grid = cnn.QueryMultiple("spGetOrder", new {Id = 1}, commandType: CommandType.StoredProcedure); var order = grid.Read(); order.Items = grid.Read(); 

此外,您还支持:

  1. 一个多映射器,允许您将单行添加到多个对象
  2. 输入/输出/返回参数支持
  3. 用于数据库特定参数处理的可扩展接口(如TVP)

例如:

 create proc spGetOrderFancy @Id int, @Message nvarchar(100) output as set @Message = N'My message' select * from Orders join Users u on OwnerId = u.Id where Id = @Id select * from OrderItems where OrderId = @Id return @@rowcount 

可以映射:

 var p = new DynamicParameters(); p.Add("Id", 1); p.Add("Message",direction: ParameterDirection.Output); p.Add("rval",direction: ParameterDirection.ReturnValue); var grid = cnn.QueryMultiple("spGetOrder", p, commandType: CommandType.StoredProcedure); var order = grid.Read((o,u) => {o.Owner = u; return o;}); order.Items = grid.Read(); var returnVal = p.Get("rval"); var message = p.Get("message"); 

最后,dapper还允许自定义参数实现:

 public interface IDynamicParameters { void AddParameters(IDbCommand command); } 

实现此接口时,您可以告诉dapper您希望添加到命令中的参数。 这允许您支持Table-Valued-Params和其他DB特定function。

根据数据库entity framework ,或NHibernate可能是您的最佳选择(链接中的示例)。

LINQ to SQL设计器将为您提供类型安全的sprocs作为DataContext对象的方法。 您可以非常轻松地将这些映射到CRUD操作的对象。

事实上,我正处于这样做的中间。

既然你有一个DBA编写sprocs,我认为最好的办法是与他密切合作,弄清楚如何将表映射到对象,以及如何构建数据库以使其适用于您的域模型。 sprocs没有任何问题,他们只需要开发人员和DBA之间的密切合作。

理想情况下,有问题的DBA是您项目团队的一部分……

我喜欢Entity Framework现在处理sprocs的方式。 您可以将sprocs与实体的crud操作相关联,甚至可以检测哪些sprocs与实体的属性匹配。 现在一个很大的缺点是如果你将一个sproc与一个实体关联起来,你必须将所有crud操作与一个sproc相关联。

这篇EF Sproc文章有一些关于如何在EF中使用sprocs的很好的例子,并且它也有一些非常好的扩展方法。

我看到的主要问题是,通过使用SP,您将自动失去使用ORM时获得的大量灵活性,特别是在检索信息时。 因此,我相信您将无法使用大多数ORM的所有function。

例如,如果你使用linq2sql,你将拥有很多SP的包装器。 您还可以将生成的实体的插入,删除和更新映射到存储过程。 你松散的地方在于信息的检索,因为现在修复了查询(并且你可能检索到比需要更多的信息,即额外的列 – 或者创建大量的SP)以及延迟加载。

更新:我更像是一个linq2sql人,但我会再看看你对NHibernate所做的假设。 特别是,我怀疑它会强制列顺序,因为它配置了列名称(请参阅http://nhibernate.info/blog/2008/11/23/populating-entities-from-stored-procedures-with-nhibernate.html )。 它还支持我不知道如何处理linq2sql: http ://nhibernate.info/blog/2008/11/23/populating-entities-with-associations-from-stored-procedures-with-nhibernate.html 。 注意,我不是说linq2sql不支持最后一个,只是我不知道如何;)