问题
For a simple repository
public interface ISimpleRepository<T>
{
IApplicationState AppState { get; set; }
void Add(T instance);
void Delete(T instance);
void Delete(Guid rowGuid);
IQueryable<T> GetAll();
T Load(Guid rowGuid);
void SaveChanges();
void Update(T instance);
}
my implementation of the Load()
method for specific repository for class Product
might look like this:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
Now this is assumed when my repository implementation class looks like this:
public class EntityFrameworkProductsProvider : IRepository<Product> ...
What if I had like dozens or hundreds of this small and simple entities that would all use the same behaviour when doing CRUDs (use the same implementation of methods)? I certainly don't want to go and create a class to implement IRepository for each one of them..
I want something like this:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
but I don't know how to implement the LINQ Select expression then because of course I can't write from e in _ctx.T where e...
or do I?
I haven't run into this scenario yet because so far I only had very specific entities with custom repository implementation.
回答1:
Instead of writing _ctx.Products
, you can write _ctx.Set<T>
. That takes care of half of the problem (you need to add a generic constraint where T: class
to your repository)
Then, if rowid is the object's key, you can use _ctx.Set<T>.Find(rowid)
instead of a LINQ query to retrieve by Id.
Alternatively, you can create a base interface IHaveId
(or a BaseEntity
class, whatever you like) which has the Id
property, and then add that as an generic constraint on T, so you can use it in your queries.
回答2:
Because you tagged your question with entity-framework and entity-framework-4 I assume you are using ObjectContext API. ObjectContext
offers method CreateObjectSet<T>
which is equivalent of Set<T>
on DbContext
.
This question is actually duplicate of either:
- Generic GetById with DbContext
- Generic GetById with ObjectContext
回答3:
If you're using EF 4.1, see the sample generic repository here: http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
回答4:
I know that this is possible in EF4.1 with the DbContext API, where you have a "Set" method on the context that gets you the entity set corresponding to the type T. this way, you could have your repository like this:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
one more remark: I think you could use this syntax :
return _ctx.Products.FirstOrDefault(c=>c.id == rowid);
to get the entity you want instead of using the (from... in...). it's clearer (in my opinion) :)
Hope this helps
来源:https://stackoverflow.com/questions/5779316/generic-repository-implementation-with-ef