[英]Which ORM is the best when using Stored Procedures

I have Business objects (DEVELOPERS WRITE) and some SPROCS (DBA WRITE)

我有業務對象(開發人員編寫)和一些SPROCS (DBA編寫)

Can anyone recommend a good object mapper to deal with this kind of setup.


I tried codesmith and nhibernate and had trouble. I do not mind if my ORM is free or paid.


8 个解决方案



SubSonic has excellent support for sprocs. It will wrap each one in a helper method and you can retrieve strongly-typed collections or entities from the results if you want. I show a way to do that in this blog post. As long as your sproc returns the same schema as SELECT * FROM TableName would, it will work with your SubSonic entities.

亞音速對sprocs有很好的支持。它將把每一個都封裝在一個helper方法中,如果您願意,您可以從結果中檢索強類型的集合或實體。我在這篇博客文章中展示了一種方法。只要您的sproc返回與SELECT *相同的模式,它將與您的亞音速實體一起工作。

As far as generating classes based on your db, SubSonic generates partial classes so you can extend them as needed. You could also do mappings from the SubSonic generated classes to your actual model.




Subsonic has a flexible solution:


    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<CustomerOrder> orders = Northwind.SPs.CustOrderHist("ALFKI")

Subsonic is a solid "Swiss Army knife" style ORM.




Disclaimer: I am the author of Dapper.


If you are looking for a simple object mapper that handles mapping procs to business objects Dapper is a good fit.


Keep in mind it ships with no "graph management", "identity map" and so on. It offers a bare bone, complete solution which covers many scenarios other ORMs do not.


Nonetheless, it offers one of the fastest object materializers out there, which can be 10x faster than EF or even 100x faster than subsonic in some benchmarks.


The trivial:


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

Can be mapped with the following:


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

Additionally you have support for:


  1. A multi-mapper that allows you single rows to multiple objects
  2. 一個多映射器,允許單個行到多個對象。
  3. Input/Output/Return param support
  4. 輸入/輸出/返回參數的支持
  5. An extensible interface for db specific parameter handling (like TVPs)
  6. 用於db特定參數處理的可擴展接口(如TVPs)

So for example:


create proc spGetOrderFancy
   @Id int,
   @Message nvarchar(100) output 
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

Can be mapped with:


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<Order,User,Order>((o,u) => {o.Owner = u; return o;});
order.Items = grid.Read<OrderItems>(); 

var returnVal = p.Get<int>("rval"); 
var message = p.Get<string>("message"); 

Finally, dapper also allow for a custom parameter implementation:


public interface IDynamicParameters
   void AddParameters(IDbCommand command);

When implementing this interface you can tell dapper what parameters you wish to add to your command. This allow you to support Table-Valued-Params and other DB specific features.




Depending on the database Entity Framework, or NHibernate are likely your best options (examples in links).




The LINQ to SQL designer will give you type-safe sprocs as methods on the DataContext object. You can map those to objects for CRUD operations fairly easily.

LINQ to SQL designer將為您提供類型安全的sprocs作為DataContext對象的方法。您可以很容易地將它們映射到CRUD操作的對象。

In fact, I'm in the middle of doing exactly that.




Since you've got a DBA writing the sprocs, I would think the best thing to do would be to work closely with him to figure out how to map the tables to objects, and how to structure the database so that it works with your domain model. There's nothing wrong with sprocs, they just require close collaboration between the developers and the DBAs.


Ideally, the DBA in question is part of your project team...




I like the way the Entity Framework handles sprocs right now. You can associate sprocs with the crud operations of an entity, it even detects which sprocs match up with the properties of your entity. The one big downside right now is if you associate one sproc with an entity you must associate all the crud operations with a sproc.


This EF Sproc article has some great examples of how to use sprocs in EF and has some really nice Extension methods for it as well.

這篇EF Sproc文章有一些關於如何在EF中使用Sproc的很好的例子,並且有一些很好的擴展方法。



The main issue I see with this, is that by going with SP you are automatically loosing lot of the flexibility you get when using ORM, specially on the retrieval of information. Because of this, I am sure you won't be able to use All of the features of most ORM.


For example, if you use linq2sql, you will have pretty much wrapper to the SPs. You can also map insert, deletes and updates of the generated entities to stored procedures. Where you loose a lot is on the retrieval of information, both because the queries are now fixed (and you might retrieve more information than needed i.e. extra columns - or create lots of SPs) and on lazy loading.


Update: I am more a linq2sql guy, but I would take a second look at the assumptions you are taking about NHibernate. In particular, I doubt it will force column order as it is configured with column names (see http://nhibernate.info/blog/2008/11/23/populating-entities-from-stored-procedures-with-nhibernate.html). It also supports something I don't know how to do with linq2sql: http://nhibernate.info/blog/2008/11/23/populating-entities-with-associations-from-stored-procedures-with-nhibernate.html. Note, I don't mean that last one isn't supported with linq2sql, just that I don't know how to ;)

更新:我更喜歡linq2sql,但是我想再看看您對NHibernate的假設。特別是,我懷疑它會強制列順序,因為它配置了列名(參見http://nhibernate.info/blog/2008/11/23/populatentis-from-storing-procedure - hibernate -nhibernate.html)。它還支持一些我不知道如何使用linq2sql的東西:http://nhibernate.info/blog/2008/11/23/populating-entiation -with- associated -from-stored-procedure -with-nhibernate.html。注意,我並不是說最后一個不支持linq2sql,只是我不知道如何;)



粤ICP备14056181号  © 2014-2020 ITdaan.com