Note that there are some explanatory texts on larger screens.

plurals
  1. POEntity Framework, Generic Repository Pattern and strange SQL generation
    primarykey
    data
    text
    <p>I've implemented a generic repository for Entity Framework 4. Here's a dumbed down version, where AllAppContainer is the EF4 object context:</p> <pre><code>public class Repository&lt;T&gt; where T : class { protected AllAppContainer objectContext; protected ObjectSet&lt;T&gt; entitySet; public Repository() { objectContext = new AllAppContainer(); entitySet = objectContext.CreateObjectSet&lt;T&gt;(); } public int QueryCount(Func&lt;T, bool&gt; predicate) { int queryCount = entitySet.Count(predicate); return queryCount; } } </code></pre> <p>The one method is QueryCount(), which I want to act as a <strong>select Count(*) ... where</strong> line of SQL (not returning the actual records).</p> <p>Straight-forward? You'd think... First, let's do a non-Repository version of the same thing, performing a count on Item entities:</p> <pre><code>AllAppContainer allAppContainer = new AllAppContainer(); int nonRepCount = allAppContainer.Items.Count(item =&gt; item.Id &gt; 0); </code></pre> <p>SQL Server Profiler says the generated SQL is:</p> <pre><code>SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT COUNT(1) AS [A1] FROM [dbo].[Items] AS [Extent1] WHERE [Extent1].[Id] &gt; 0 ) AS [GroupBy1] </code></pre> <p>Woo-hoo! Score!</p> <p>Now let's call the same using my Repository QueryCount:</p> <pre><code>Repository&lt;Item&gt; repository = new Repository&lt;Item&gt;(); int repCount = repository.QueryCount(item =&gt; item.Id &gt; 0); </code></pre> <p>Here's the generated SQL:</p> <pre><code>SELECT [Extent1].[Id] AS [Id], [Extent1].[SmallField] AS [SmallField] FROM [dbo].[Items] AS [Extent1] </code></pre> <p>Yep, EF is returning the full set of data, then calling <em>Count()</em> on it in-memory.</p> <p>For fun I tried changing the relevant line in Repository QueryCount to:</p> <pre><code>int queryCount = new AllAppContainer().CreateObjectSet&lt;T&gt;().Count(predicate); </code></pre> <p>and the non-repository line to:</p> <pre><code>int nonRepCount = allAppContainer1.CreateObjectSet&lt;Item&gt;().Count(item =&gt; item.Id &gt; 0); </code></pre> <p>but the generated SQL for each is the same as before.</p> <p>Now why would all this repository-returns-all-matching-records-then-counts be happening, when it doesn't for non-repository? And is there any way to do what I want via my generic repository i.e. count at db. I can't take the in-memory count performance hit.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload