title: Querying against DbContext.Set(TypeVariable) in Entity Framework
body: <p>I'm re-factoring an application to invert some dependencies. Part of the original code uses <code>DbContext.Set&lt;MyEntityType&gt;()</code> to obtain the set to query against.</p>
  
  <p>With the inversion, the MyEntityType is no longer explicitly known to the code using <code>DbContext.Set&lt;MyEntityType&gt;()</code>, so now I'm using <code>DbContext.Set(TypeVariable)</code> instead.</p>
  
  <p>The re-factoring works to the extent that the correct DbSet is being returned.</p>
  
  <p>However, the type <code>DbContext.Set(TypeVariable).Local</code> is <code>IList</code> (contained type unknown) where-as the type of <code>DbContext.Set&lt;MyEntityType&gt;().Local</code> was <code>ObservableCollection&lt;MyEntityType&gt;</code>. This means that it's now impossible to do Linq against the DbSet.</p>
  
  <p>The best workaround I've been able to achieve is to cast to an interface that MyEntityType and other entity types implement (some code omitted for clarity)</p>
  
  <pre><code>var set = Context.Set(targetType);
  var entity = set.Local.OfType&lt;IActionTarget&gt;()
      .FirstOrDefault(l =&gt; l.Id == key.Id &amp;&amp; l.EffectiveDate == key.EffectiveDate);
  var querables = set as IQueryable&lt;IActionTarget&gt;;
  entity = querables.FirstOrDefault(e =&gt; e.Id == key.Id &amp;&amp; e.EffectiveDate == key.EffectiveDate);
  </code></pre>
  
  <p>So, two questions:</p>
  
  <p>Why doesn't <code>DbContext.Set(TypeVariable)</code> return a strongly typed set?</p>
  
  <p>Is there a better way to do the dependency inversion? </p>
  
  <p><strong>Some further details as requested</strong></p>
  
  <p>It's all about dependencies. The Model contains POCO classes which are persisted via EF Code First in the typical way (but via a <strong>Repository</strong>). An <strong>ActionEvaluator</strong> takes some incoming data, and via Repository methods, determines what actions need to occur - hence the queries against the DbSets.</p>
  
  <p>In the original code, there was only one type of incoming data (CSV of a particular format) and the ActionEvaluator had a tight dependency to this data and knew which POCO classes were applicable to which CSV records.</p>
  
  <p>Now, we want to expand to use different CSV formats and web api messages. To do this, we need to invert the dependencies so that the <strong>DataSource</strong> tells the ActionEvaluator what POCO classes it's records apply to. This is done by way of a Type variable.</p>
  
  <p>So, the ActionEvaluator can no longer use a generic type parameter, but it can pass the type variable to the Repository which uses it to find the correct DbSet.</p>
  
  <p>The problem is the difference between the two ways of finding the DbSet - <code>DbContext.Set&lt;AnEntity&gt;()</code> and <code>DbContext.Set(TypeVariable)</code>.</p>
  
  <p>I guess I'm asking for an enhancement in EF to make these two functionally equivalent in their return values, but that may not be possible since the types of the second version are determined at runtime.</p>
  
  <p>Here's the full method code as requested:</p>
  
  <pre><code>    private IActionTarget DbContextGetEntity(Type targetType, IActionTarget key)
      {
          var set = Context.Set(targetType);
          if (set == null)
          {
              throw new Exception("Unable to find DbSet for type '{0}'".F(targetType.Name));
          }
  
          // Look in the local cache first
          var entity = set.Local.OfType&lt;IActionTarget&gt;()
              .FirstOrDefault(l =&gt; l.Id == key.Id &amp;&amp; l.EffectiveDate == key.EffectiveDate);
  
          if (entity == null)
          {
              // If not found locally, hit the database
              var querables = set as IQueryable&lt;IActionTarget&gt;;
              if (querables != null)
              {
                  entity = querables.FirstOrDefault(e =&gt; e.Id == key.Id &amp;&amp; e.EffectiveDate == key.EffectiveDate);
              }
          }
          return entity;
      }
  </code></pre>
  
  <p>Ideally, I want to replace </p>
  
  <pre><code>var entity = set.Local.OfType&lt;IActionTarget&gt;()
      .FirstOrDefault(l =&gt; l.Id == key.Id &amp;&amp; l.EffectiveDate == key.EffectiveDate);
  </code></pre>
  
  <p>with</p>
  
  <pre><code>var entity = set.Local.OfType(targetType)
      .FirstOrDefault(l =&gt; l.Id == key.Id &amp;&amp; l.EffectiveDate == key.EffectiveDate);
  </code></pre>