我注意到在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?
答案 0 :(得分:7)
实体本身不允许存储过程进行选择。有几个原因。在我的头顶:
Order
和OrderItem
表,那么您如何加入?您可以运行SelectOrder
,也可以为每个订单运行SelectOrderItem
(1 + n个查询),或者让一个存储过程同时返回两者,或者作为一个带有重复Order
数据的结果集,或者两个结果集。然后,您必须指定映射到实体的方式。如果必须手动指定映射,则会破坏您必须设置的实体关系的目的。IQueryable
公开给业务层或UI层(由您决定)。然后进行LINQ过滤,修改SQL并使其高效。使用存储过程,您将再次以某种方式手动定义所有这些,或使用LINQ对对象进行过滤。select new { o.Column1, o.Column2 }
。这会生成SQL,只选择您需要的那两列。如果您有BLOB
/ VARCHAR(MAX)
,则非常有用。使用存储过程,您通常会返回每一列(在很多方面都会浪费)。您可以拆分为GetOrderDetailMain
和GetOrderDetailImages
(或类似的)存储过程,但创建每个组合是不可行的。在我看来,如果您将使用EF框架,请让它为您做CRUD。使用存储过程来处理复杂的逻辑,例如全文搜索,特定查询太慢等等。否则你将无法从中受益。
编辑:当然,存储过程会带来好处。它们是预先编译/预编译的,定义良好的“数据库API”,你不需要提供对表的访问(虽然使用SP CRUD,你实际上可以做同样的事情),更容易调试/调优查询,更容易知道哪些查询要调整,可以进行批处理等。但是,对于简单的CRUD,你必须问自己,实现/管理存储过程的开销是否值得。
答案 1 :(得分:2)
您当然可以在Entity Framework中使用存储过程进行选择。我使用function imports,complex types和EF4存储过程取得了巨大成功。而且,它们也不难设置。
我将警告您一件事:如果您使用的是SQL Server 2005,则可能必须重新编译要与SET FMTONLY OFF
一起使用的任何存储过程,如果您想允许实体建模器生成复杂类型为了你。有关详细信息,请参阅this question。
有关详细信息,请参阅Quickstart。