EF4: 如何使用通用仓储模式?

3

我正在尝试通过使用一个可以从中继承的通用仓库来简化我的现有仓库。问题是我不知道如何编写一些基类方法。目前我的代码如下:

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;
    }
}

我困惑于我的 GetSingle()Save() 方法。它们需要依赖每种类型 T 稍微不同的信息。以下是来自我非泛型仓库的示例:

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();
}

正如您所看到的,文章有自己特定的ID。我的其他实体也是一样(例如新闻项目有一个NewsID属性)。

我如何创建一个抽象基本方法,可以被调和成更具体的版本?


1
第一个问题应该是_为什么_使用存储库 - Gert Arnold
很棒的链接。话说,我的项目相当简单,我的后端只是简单的CRUD功能。其中没有DDD。 - Major Productions
1
更多的理由避免使用沙袋代码,不是吗? - Gert Arnold
嗯...也许吧。对我而言,将我使用的保存实体的代码(例如在我的问题中)隐藏到方法接口背后会更加清晰。但是另一方面,GetByXXX方法让我想起了丑陋的PHP样板代码。 - Major Productions
1个回答

3
你可以为你的GetSingle方法使用一个通用的表达式参数:
public interface IRepository<T> : IDisposable where T : class
{
    ....
    T GetSingle(Expression<Func<T, bool>> filter);
    void Save(T entity);
}

HGRepository<T> 中:

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

使用方法:

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

如果您有特殊场景,通用接口/存储库类无法涵盖,您可以创建继承自通用类的新接口/类:

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接