Note that there are some explanatory texts on larger screens.

plurals
  1. POGeneric Repository
    primarykey
    data
    text
    <p>I'm working on incorporating some common repository infrastructure into some applications that wrap EF, L2SQL and WCF Data Services (though the underlying Data Access implementations should be arbitrary). I've done some reading on the matter but can't seem to find an example that really satisfies.</p> <p>I started with:</p> <pre><code>public interface IRepository : IDisposable { IQueryable&lt;T&gt; Query&lt;T&gt;(); void Attach(object entity); void ForDeletion(object entity); void SaveChanges(); } </code></pre> <p>But I like the idea of a repository with narrow <em>domain</em> contracts (<a href="http://codebetter.com/blogs/gregyoung/archive/2009/01/16/ddd-the-generic-repository.aspx" rel="nofollow">http://codebetter.com/blogs/gregyoung/archive/2009/01/16/ddd-the-generic-repository.aspx</a>). The above leaves the consumer to know all of the entity types supported by the repository.</p> <p>I'm not going to say it's out of the question, but I'd be very hard pressed to be convinced that IQueryables themselves should not be part of the repository contract. I'm not a fan of boiler plate code and I firmly believe that the more you have, the more maintenance black holes you introduce. So, what I'm saying is that it would be very hard to convince me that anything that looks like:</p> <pre><code> Public IEnumerable&lt;Customer&gt; GetCustomersWithFirstNameOf(string _Name) { internalGenericRepository.FetchByQueryObject(new CustomerFirstNameOfQuery(_Name)); //could be hql or whatever } </code></pre> <p>is anything but an utterly <em>abysmal</em> idea. What about when you want to search on first name <em>and</em> last name. Or first name <em>or</em> last name...etc. You end up with a repository with 1000+ operations, half of which repeat the same logic. NOTE: I'm NOT the calling code should be responsible for applying all filtering and such, but rather that having a complementary specification source makes sense to me:</p> <pre><code>public static class CustomerSpecifications { public IQueryable&lt;Customer&gt; WithActiveSubscriptions(this IQueryable&lt;Customer&gt; customers, DateTime? start, DateTime? end) { // expression manipulation return customers; } } // bind some data source repository.GetQueryable().WithActiveSubscriptions(); </code></pre> <p>Ok, so moving forward, I think having domain model explicit repositories sound like a good idea in the following format:</p> <pre><code>public interface IRepository : IDisposable { void SaveChanges(); } public interface IRepository&lt;T&gt;: IRepository { IQueryable&lt;T&gt; GetQueryable(); void Attach(T entity); void ForDeletion(T entity); } </code></pre> <p>then</p> <pre><code>public class CustomerRepository:IRepository&lt;Customer&gt; { private ObjectContext _context; // trivial implementation } </code></pre> <p>but my problem with this is that it only allows me to delete Customers. What about the case where I want to delete a Customer's address? That is, I use the repository to query a Customer entity, but then want to delete myCustomer.CustomerAddresses[0]? I need to create a second repository simply to attach and delete the address I want? </p> <p>I guess I could have my CustomerRepository be:</p> <pre><code>public class CustomerRepository:IRepository&lt;Customer&gt;, IRepository&lt;CustomerAddress&gt; { private ObjectContext _context; // trivial implementation } </code></pre> <p>which would let me reuse the repository to delete CustomerAddresses, but I'm not sure how I feel about inheriting <code>IRepository&lt;T&gt;</code> for every part of the graph I want to expose deletions for...</p> <pre><code>public class CustomerRepository:IRepository&lt;Customer&gt;, IRepository&lt;CustomerAddress&gt; /* this list may get pretty long, and then I really just have a masked EF ObjectContext, don't I? */ { </code></pre> <p>Anyone have any suggestions for a better implementation?</p>
    singulars
    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.
    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