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

时间:2009-03-26 22:13:59

标签: c# .net database stored-procedures orm

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

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

我尝试使用codesmith和nhibernate并遇到麻烦。我不介意我的ORM是免费的还是付费的。

9 个答案:

答案 0 :(得分:7)

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

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

答案 1 :(得分:5)

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

Subsonic是一种坚固的“瑞士军刀”式ORM。

答案 2 :(得分:5)

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


如果您正在寻找一个简单的对象映射器来处理映射过程到业务对象Dapper是一个很好的选择。

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

尽管如此,它提供了最快的对象物化器之一,在某些benchmarks中可以比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>();
order.Items = grid.Read<OrderItems>(); 

此外,您还支持:

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

    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<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"); 
    

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

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

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

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

事实上,我正在做这件事。

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

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

例如,如果你使用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不支持最后一个,只是我不知道如何;)

答案 7 :(得分:0)

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

这个EF Sproc article有一些很好的例子,说明如何在EF中使用sprocs,并且还有一些非常好的扩展方法。

答案 8 :(得分:0)

现在您可以尝试 Nfinity.Data,它对存储过程提供强类型支持,包括表值参数 (TVP) 和输出参数。要读取任何结果,您需要手动访问读取器(它为此提供了读取器抽象)。

我不相信 NHibernate 或 EF 将实体映射到存储过程的想法,因为它们的内部工作是不确定的,即,在运行时之前无法以任何方式进行验证。通过上面的阅读器,在代码中完成所有事情更具声明性。