title: Polymorphism with generics on the repository pattern
body: <p>I have a problem using the Repository pattern in C# especially when I try to implement a Façade pattern too. My concept follows: </p>
  
  <p>When I first started the generic repository, I began with one which has all the CRUD operations in a single file (and their related interfaces in a separate single file). But because of the SOLID principles and in particular the ISP principle, I decided to segregate all the interfaces into separate files, and do likewise with the classes.</p>
  
  <p>So for example instead of having IGenericRepo with the various Create, Read ... methods in one file, and the corresponding GenericRepo in another. I segregated them all out having a base repo to do anything common. So I ended up with an ICreateRepo, an IReadOneRepo, an IReadManyRepo...etc.</p>
  
  <p>As time passed, my project needs grew, and I found myself needing multiple "Read" operations:</p>
  
  <ul>
  <li>Read a single record with the given id,</li>
  </ul>
  
  <blockquote>
  <pre><code>     public T Read(int id)
  </code></pre>
  </blockquote>
  
  <ul>
  <li>Read a single record which could potentially have compound primaries having to pass in multiple values. Works like the EF Find Method...i.e.</li>
  </ul>
  
  <blockquote>
  <pre><code>     public T Read(params object[] keyValues)
  </code></pre>
  </blockquote>
  
  <ul>
  <li>Return the first record based on a search on any field...like the EF Where Method, which had parameter like...</li>
  </ul>
  
  <blockquote>
  <pre><code>     public T Read(Expression&lt;Func&lt;T&gt;,bool&gt;&gt; predicate)
  </code></pre>
  </blockquote>
  
  <p>This was fine until I came across a situation where I needed to read multiple records and return a list of all records that matched the criteria. Essentially the read operation had the same method signature as the last one mentioned, differing only in its return type. One returned a single entity, the other returned a list of matching entities.</p>
  
  <pre><code>   public IQueryable&lt;T&gt; Read(Expression&lt;Func&lt;T&gt;,bool&gt;&gt; predicate)
  </code></pre>
  
  <p>While separated out into their own classes there was no issue. However I found in my controllers (I use MVC) that I had long lists of repositories about 6 or 9 and I wanted to simplify this to one like what I had for the single generic. So I turned to the Façade pattern.</p>
  
  <p>Now when I bring together the read functionalities, I will have a problem with polymorphic behaviour because the signatures are the same.</p>
  
  <pre><code>    //ReadOne 1
      public T Read(int id)
      { }
      //ReadOne 2
      public T Read(params object[] keyValues)
      { }
      //ReadOne 3 *** Signature same as search except for return type.
      public T Read(Expression&lt;Func&lt;T, bool&gt;&gt; predicate)
      {
          //SingleOrDefault used purposefully instead of FirstOrDefault to cause exception if
          //there is more than one instance that meets the predicate.
          return dbSet.Where(predicate).SingleOrDefault&lt;TEntity&gt;();
      }
  
      //Search
      public IQueryable&lt;T&gt; Read(Expression&lt;Func&lt;T, bool&gt;&gt; predicate)
      {
          return dbSet.Where(predicate);
      }
  
      //ReadAll
      public IQueryable&lt;T&gt; Read()
      { }
  </code></pre>
  
  <p>As mentioned... When separated into separate files, these worked fine as they were explicitly called as needed. But I want to use the Façade pattern to simplify the code.</p>
  
  <p>The problem I am having of course is that there is no polymorphism based on return type. I understand the and fully appreciate reasons for this.</p>
  
  <p>I was thinking of adding an optional bool parameter to the end of the search. But it doesn't feel right for some reason. Something like...</p>
  
  <pre><code>    //Search
      public IQueryable&lt;T&gt; Read(Expression&lt;Func&lt;T, bool&gt;&gt; predicate, bool returnOne = false)
      { }
  </code></pre>
  
  <p>So my question is, has anyone got ideas on how to get around this limitation?</p>