我正在处理的新项目的一个要求是所有SQL查询都必须使用存储过程。我将使用Entity Framework&用于管理数据访问的存储库模式,在我的存储库中,我将使用“查找(谓词)”和“FindAll()”方法。目前他们都使用相同的存储过程(“select * from Foo”)。
因为我无法访问SQL事件探查器,所以我不太确定LINQ表达式如何在我的Find(谓词)方法中转换?如果我有类似的东西:
List<Foo> myFoo = repository.Find( f => f.Country == "Australia" && f.Status = "New" );
我是否正确假设这将通过sproc检索所有记录,结果数据在内存中过滤?如果是这种情况,我如何构建sproc以仅检索所需的记录,同时允许使用linq表达式(需要允许&amp;&amp;,||,!=等)?这是否有可能,甚至不必抛弃sprocs?
答案 0 :(得分:3)
如果您被迫使用存储过程来处理所有内容,那么使用EF没有多大意义。实际上,EF的最大优点之一是它自动生成查询,具有大量参数和正确的查询sintax来获取/插入/更新/删除数据。
你将失去EF的两个优势:
如果你不让EF生成查询,你将无法轻松导航,塑造数据,自动生成正确的查询和过滤器等。有些人可以做到这一点,只有你做了一个非常努力的工作模特。但是,如果从数据库更新模型,则可能会丢失一些更改
如果您正在使用EF,那么使用存储过程的合理时机是:
对于所有其他查询,让EF为你做的工作要好得多。
如果您需要对所有内容使用存储过程,使用EF的优势在于将数据自动映射到实体,但您将失去许多其他EF的优势。
你必须这样做:
很难定义一个模型,它具有在它们之间有关系的实体之间的关系。
关于最佳情况下repository.Find(...)
的问题,你是对的,将查询所有数据,然后在客户端进行过滤。在最坏的情况下,如果您的模型没有正确定义,它可能会失败。
如果让EF创建查询,它会将正确的过滤器发送到数据库(在一个案例中就像你的样本一样)。 如果你有专门的存储过程以特定方式过滤,你将不得不忘记LINQ,并直接调用映射函数。
因此,除非有充分的理由使用SP,否则让EF为您创建查询会更好。
答案 1 :(得分:1)
你是对的,开箱即用的东西会检索所有记录并在内存中过滤。我不会说组合表达式和sprocs是不可能的,但它是非常不切实际的,并且可能首先违背了你的sproc要求的目的。您必须解释表达式树并生成参数化的sql并将其传递给sproc(可能会破坏sproc要求的目的),或者解释表达式树并将参数正确地传递给“generic sproc”。 “Generic”意味着它有任何你想要过滤的可以为零的参数(非常不切实际,并且会有很多限制 - 没有连接等)。
如果您尊重sproc要求,我会放弃任何暴露IQueryable的数据访问api(除非您愿意在内存中执行表达式,否则您将失去组合表达式和sprocs的能力)。
即使没有表达式和sprocs之间的可组合性,正如JotaBe所指出的那样,EF仍然可以方便地处理模型并避免使用样板。