使用存储库模式我们应该为DAL中的每个表或业务层中的对象定义类吗?

时间:2013-12-31 06:39:39

标签: c# entity-framework repository-pattern

如果拥有更大的数据库,如何在c#中使用实体框架正确实现存储库模式?

我们应该为在DAL(数据访问层)中实现Repository接口的每个表定义类,还是在业务层中定义这样的对象?

Repository<RetailerMarketplace> retailerMarketplaceRepo = null;
Repository<Marketplace> marketplaceRepo = null;
Repository<Product> productRepo = null;
Repository<OP_FLAGS> opFlagsRepo = null;
Repository<RetailerMarketplaceAttributeMapping> retailerMPAttributesMappingRepo = null;
Repository<EbayVariation> ebayVariationRepo = null;
Repository<ProductIsListed> productIsListedRepo = null;
Repository<Skus_OpFlags> skusOpFlagsRepo = null;

目前我已定义了上述对象,但我对在DAL或业务层中定义对象和使用它们的正确方法感到困惑?

2 个答案:

答案 0 :(得分:2)

不要在业务层中创建任何Repository个对象。您应该将工作单元模块与存储库模式一起使用。您的DAL应该有一个工作类单元,它只将必需的存储库公开为属性。此工作单元作为业务层和数据访问层之间的唯一网关。

例如,假设我有两个实体FooBar结构如下:

public class Foo
{
    public int FooId { get; set; }
    public virtual ICollection<Bar> Bars { get; set; }
}

public class Bar
{
    public int BarId { get; set; }
    public int FooId { get; set; }
    public virtual Foo Foo { get; set; }
}

我的UnitOfWork课程可能如下所示:

public class UnitOfWork
{
    private Repository<Foo> foos;

    public Repository<Foo> Foos
    {
        get
        {
            if(foos == null)
                foos = new Repository<Foo>();
            return foos;
        }
    }

    ...
}

至于为每个实体定义存储库,您需要确定哪些实际需要包含。例如,我的UnitOfWork不包含Repository<Bar>。也许我这样做是因为我可以通过关联的Bar上的链接属性访问所有Foo,但在我的域中查找Bar是没有意义的它自己的。底线:这完全取决于您的域名您公开的存储库。只要明智地选择。

This article由ASP.NET / MVC团队编写,但其中的存储库/工作原理单元是使用Entity Framework的任何实践的良好实践。无论您是否使用MVC,都可以很好地阅读。

答案 1 :(得分:2)

EF有内置的存储库对象,它们是DbSet类型,EF自己初始化。所以在你的代码示例中,它们就像:

public DbSet<RetailerMarketplace> RetailerMarketplaces { get; set; }
public DbSet<Marketplace> MarketPlaces  { get; set; }

那么为什么你想要一个额外的存储库层呢?

可能的一个原因是能够伪造存储库对象,因为DbSet不提供可用于模拟或伪造的接口。例如,让我们从IRepostory的接口类型创建一个通用的存储库类。在这种情况下,类Repository将封装任何模型T的DbSet。

public interface IRepository<T> where T : class
{
    void Add(T model);
    void Edit(T model);
    void Delete(T model);
    T Get(object id);
    IQueryable<T> List();
}

public class Repository<T> : IRepository<T> where T : class
{
    DatabaseContext context;
    DbSet<T> dbSet;

    public Repository(DatabaseContext context)
    {
        this.context = context;
        this.dbSet = context.Set<T>();
    }

    public void Add(T model)
    {
        dbSet.Add(model);
    }

    public void Edit(T model)
    {
        dbSet.Attach(model);
        context.Entry(model).State = EntityState.Modified;
    }

    public void Delete(T model)
    {
        if (context.Entry(model).State == EntityState.Detached)
        {
            dbSet.Attach(model);
        }
        dbSet.Remove(model);
    }

    public T Get(object id)
    {
        return dbSet.Find(id);
    }

    public IQueryable<T> List()
    {
        return dbSet;
    }
}

实例化存储库

var context = new DbContext();
var repo = new Repository<Marketplace>(context);

上面的上下文是UoW对象。 Repo 是实例化的存储库对象。要创建一个虚假对象,您需要的是从IRepository派生。