实体框架&存储过程

时间:2010-11-05 17:21:32

标签: c# vb.net linq-to-sql entity-framework stored-procedures

我注意到在Entity Framework设计器中,您可以映射Insert,Update和Delete操作的存储过程。是否有任何方法可以为Select操作执行此操作,或者是否有新的数据库访问代码方向,我们不再为基本的选择操作编写存储过程了?

我工作的公司非常坚持总是使用存储过程进行每个数据库操作,即使实体框架通过调用sp_executesql使调用安全。

似乎LINQ to SQL和Entity Framework已经不再使用存储过程来选择数据。这是一个准确的陈述吗?

只是为了澄清我的问题:

我的数据库中有一个名为Product的表。我使用实体框架中的向导来生成我的模型......所以我现在有一个名为Product的实体。当我执行以下查询时:

db.Products.SingleOrDefault(p => p.Id == 1);

它生成的代码类似于:

EXEC sp_executesql N'SELECT * FROM Product'

当我真的想做类似的事情时:

EXEC up_GetProduct @Id = 1

如果使用SingleOrDefault无法做到这一点我就可以了。我更愿意拥有以下内容:

db.Products.GetProduct(1);

这是通常完成的事情还是大多数人只是让它动态生成SQL?

2 个答案:

答案 0 :(得分:7)

实体本身不允许存储过程进行选择。有几个原因。在我的头顶:

  1. 如何在存储过程中添加where子句?您可能必须使用LINQ to Objects执行此操作并且查询效率低下,或者以某种方式能够将自定义映射添加到存储过程属性。虽然并非不可能,但它肯定会引入一些实现复杂性。
  2. 实体可以具有用于在查询中进行连接的关系。使用存储过程,您又会遇到类似的问题。如果您有OrderOrderItem表,那么您如何加入?您可以运行SelectOrder,也可以为每个订单运行SelectOrderItem(1 + n个查询),或者让一个存储过程同时返回两者,或者作为一个带有重复Order数据的结果集,或者两个结果集。然后,您必须指定映射到实体的方式。如果必须手动指定映射,则会破坏您必须设置的实体关系的目的。
  3. 你如何做分页?使用LINQ to Entities,您可以将IQueryable公开给业务层或UI层(由您决定)。然后进行LINQ过滤,修改SQL并使其高效。使用存储过程,您将再次以某种方式手动定义所有这些,或使用LINQ对对象进行过滤。
  4. LINQ允许您select new { o.Column1, o.Column2 }。这会生成SQL,只选择您需要的那两列。如果您有BLOB / VARCHAR(MAX),则非常有用。使用存储过程,您通常会返回每一列(在很多方面都会浪费)。您可以拆分为GetOrderDetailMainGetOrderDetailImages(或类似的)存储过程,但创建每个组合是不可行的。
  5. 在我看来,如果您将使用EF框架,请让它为您做CRUD。使用存储过程来处理复杂的逻辑,例如全文搜索,特定查询太慢等等。否则你将无法从中受益。

    编辑:当然,存储过程会带来好处。它们是预先编译/预编译的,定义良好的“数据库API”,你不需要提供对表的访问(虽然使用SP CRUD,你实际上可以做同样的事情),更容易调试/调优查询,更容易知道哪些查询要调整,可以进行批处理等。但是,对于简单的CRUD,你必须问自己,实现/管理存储过程的开销是否值得。

答案 1 :(得分:2)

您当然可以在Entity Framework中使用存储过程进行选择。我使用function importscomplex types和EF4存储过程取得了巨大成功。而且,它们也不难设置。

我将警告您一件事:如果您使用的是SQL Server 2005,则可能必须重新编译要与SET FMTONLY OFF一起使用的任何存储过程,如果您想允许实体建模器生成复杂类型为了你。有关详细信息,请参阅this question

有关详细信息,请参阅Quickstart