EF4: how to use a generic repository pattern ?

孤者浪人 提交于 2019-12-22 09:38:25

问题


I'm trying to streamline my existing repos by using a generic repo I can subclass from. The problem is that I can't figure out how to write a few of my base class methods. I currently have:

public interface IRepository<T> : IDisposable where T : class
{
    IQueryable<T> GetAll();
    T GetSingle(int id);
    T GetSingle(string slug);
    void Save(T entity);
}

public class HGRepository<T> : IRepository<T> where T : class
{
    protected HGEntities _siteDB;
    protected IObjectSet<T> _objectSet;

    public HGRepository(HGEntities context)
    {
        _siteDB = context;
        _objectSet = _siteDB.CreateObjectSet<T>();
    }

    public IQueryable<T> GetAll()
    {
        return _objectSet;
    }

    public T GetSingle(int id)
    {
        return null;
    }

    public T GetSingle(string slug)
    {
        return null;
    }

    public void Save(T entity)
    {
        // code to save entity
    }

    public void Dispose()
    {
        _siteDB = null;
    }
}

My confusion lies with my GetSingle() and Save() methods. They'll need to rely on information that's slightly different with each type of T. Example from my non-generic repos:

public Article GetArticle(int id)
{
    return _siteDB.Articles.SingleOrDefault(a => a.ArticleID == id);
}

public Article GetArticle(string slug)
{
    return _siteDB.Articles.SingleOrDefault(a => a.Slug == slug);
}

public void SaveArticle(Article article)
{
    if (article.ArticleID > 0)
    {
        _siteDB.ObjectStateManager.ChangeObjectState(article, System.Data.EntityState.Modified);
    }
    else
    {
        _siteDB.Articles.AddObject(article);
    }

    _siteDB.SaveChanges();
}

As you can see, Articles have their own, specific id. The same thing for my other entities (News items have a NewsID property, for instance).

How can I make an abstract base method that can be reconciled into a more specific version?


回答1:


You can have a generic expression parameter for your GetSingle method:

public interface IRepository<T> : IDisposable where T : class
{
    ....
    T GetSingle(Expression<Func<T, bool>> filter);
    void Save(T entity);
}

and in HGRepository<T>:

public T GetSingle(Expression<Func<T, bool>> filter)
{
        return _objectSet.Where(filter).SingleOrDefault();
}

And usage:

IRepository<Article> rep = new HGRepository<Article>();
return rep.GetSingle(p => p.Slug == slug);

If you have particular scenarios which the generic interface / repository class don't cover, you can create new interface / class which inherit from the generic ones:

public interface IArticleRepository : IRepository<Article>
{
   ...
}

public class ArticleRepository : HGRepository<Article>, IArticleRepository
{
   ...
}


来源:https://stackoverflow.com/questions/11149272/ef4-how-to-use-a-generic-repository-pattern

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!