Entity framework 实体框架4.1通用存储库设置

Entity framework 实体框架4.1通用存储库设置,entity-framework,generics,repository-pattern,Entity Framework,Generics,Repository Pattern,我是实体框架的新手,加入了一个使用通用存储库的项目,如下所示。存储库的设置方式是否有任何缺点?我注意到,大多数教程描述的是基于通用基本存储库创建多个存储库,而不是使用一个通用存储库来处理所有问题 为了提供一些背景信息,这段代码是ASP.NETMVC3网站的一部分,我们使用unity作为IOC容器。业务层中的所有组件都继承自基类,该基类通过构造函数注入了IEntityRepository 这是通用存储库类 public class MyRepository { private const

我是实体框架的新手,加入了一个使用通用存储库的项目,如下所示。存储库的设置方式是否有任何缺点?我注意到,大多数教程描述的是基于通用基本存储库创建多个存储库,而不是使用一个通用存储库来处理所有问题

为了提供一些背景信息,这段代码是ASP.NETMVC3网站的一部分,我们使用unity作为IOC容器。业务层中的所有组件都继承自基类,该基类通过构造函数注入了IEntityRepository

这是通用存储库类

public class MyRepository
{
    private const string containerName = "myEntities";
    private readonly ObjectContext context;
    private readonly Hashtable objectSets;

    // Track whether Dispose has been called.
    private bool disposed;

    public MyRepository()
    {
        string connectionString = ConfigurationManager.ConnectionStrings[containerName].ConnectionString;

        context = new ObjectContext(connectionString) {DefaultContainerName = containerName};
        context.ContextOptions.LazyLoadingEnabled = true;
        context.ContextOptions.ProxyCreationEnabled = true;

        objectSets = new Hashtable();
    }

    private ObjectSet<TEntity> GetObjectSet<TEntity>() where TEntity : class
    {
        ObjectSet<TEntity> objectSet;

        var type = typeof (TEntity);
        if (objectSets.ContainsKey(type))
        {
            objectSet = objectSets[type] as ObjectSet<TEntity>;
        }
        else
        {
            objectSet = context.CreateObjectSet<TEntity>();
            objectSets.Add(type, objectSet);
        }

        return objectSet;
    }

    public IQueryable<TEntity> GetAll<TEntity>(params string[] entities) where TEntity : class
    {
        ObjectQuery<TEntity> objectQuery = GetObjectSet<TEntity>();

        foreach (var entity in entities)
        {
            objectQuery = objectQuery.Include(entity);
        }

        return objectQuery;
    }


    public void Insert<TEntity>(TEntity entity) where TEntity : class
    {
        ObjectSet<TEntity> objectSet = GetObjectSet<TEntity>();
        objectSet.AddObject(entity);
    }

    public void Update<TEntity>(TEntity entity) where TEntity : class
    {
        ObjectSet<TEntity> objectSet = GetObjectSet<TEntity>();

        EntityKey key = objectSet.Context.CreateEntityKey(objectSet.EntitySet.Name, entity);

        object originalItem;
        if (objectSet.Context.TryGetObjectByKey(key, out originalItem))
        {
            objectSet.ApplyCurrentValues(entity);
        }
        else
        {
            objectSet.Attach(entity);
            objectSet.ApplyCurrentValues(entity);
        }
    }

    public void Delete<TEntity>(TEntity entity) where TEntity : class
    {
        ObjectSet<TEntity> objectSet = GetObjectSet<TEntity>();
        objectSet.DeleteObject(entity);
    }

    public void SaveChanges()
    {
        try
        {
            context.SaveChanges();
        }
        catch (Exception ex)
        {
            ex.ToString();
            throw ex;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        // Take yourself off the Finalization queue 
        // to prevent finalization code for this object
        // from executing a second time.
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        // Check to see if Dispose has already been called
        if (!disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        disposed = true;
    }

    ~MyRepository()
    {
        Dispose(false);
    }
}
公共类MyRepository
{
私有常量字符串containerName=“myEntities”;
私有只读对象上下文;
私有只读哈希表对象集;
//跟踪是否已调用Dispose。
私人住宅;
公共MyRepository()
{
string connectionString=ConfigurationManager.connectionString[containerName].connectionString;
context=newObjectContext(connectionString){DefaultContainerName=containerName};
context.ContextOptions.LazyLoadingEnabled=true;
context.ContextOptions.ProxyCreationEnabled=true;
objectSets=newhashtable();
}
私有对象集GetObjectSet(),其中tenty:class
{
对象集对象集;
变量类型=类型(强度);
if(objectset.ContainsKey(类型))
{
objectSet=objectSets[type]作为objectSet;
}
其他的
{
objectSet=context.CreateObjectSet();
添加(类型,objectSet);
}
返回对象集;
}
公共IQueryable GetAll(参数字符串[]实体),其中tenty:class
{
ObjectQuery ObjectQuery=GetObjectSet();
foreach(实体中的var实体)
{
objectQuery=objectQuery.Include(实体);
}
返回objectQuery;
}
公共无效插入(TEntity实体),其中TEntity:class
{
ObjectSet ObjectSet=GetObjectSet();
objectSet.AddObject(实体);
}
公共无效更新(TEntity实体),其中TEntity:类
{
ObjectSet ObjectSet=GetObjectSet();
EntityKey=objectSet.Context.CreateEntityKey(objectSet.EntitySet.Name,entity);
对象源项;
if(objectSet.Context.TryGetObjectByKey(key,out originalItem))
{
objectSet.ApplyCurrentValues(实体);
}
其他的
{
objectSet.Attach(实体);
objectSet.ApplyCurrentValues(实体);
}
}
公共void Delete(tenty实体),其中tenty:class
{
ObjectSet ObjectSet=GetObjectSet();
objectSet.DeleteObject(实体);
}
公共void SaveChanges()
{
尝试
{
SaveChanges();
}
捕获(例外情况除外)
{
例如ToString();
掷骰子;
}
}
公共空间处置()
{
处置(真实);
//把你自己从完成队列中拿出来
//阻止此对象的终结代码的步骤
//从第二次执行开始。
总干事(本);
}
受保护的虚拟void Dispose(bool disposing)
{
//检查是否已调用Dispose
如果(!已处置)
{
如果(处置)
{
context.Dispose();
}
}
这是真的;
}
~MyRepository()
{
处置(虚假);
}
}
这是用于公开方法的接口:

public interface IEntityRepository : IDisposable
{
    void Delete<TEntity>(TEntity entity) where TEntity : class;

    IQueryable<TEntity> GetAll<TEntity>(params string[] entities) where TEntity : class;

    void Insert<TEntity>(TEntity entity) where TEntity : class;

    void Update<TEntity>(TEntity entity) where TEntity : class;

    void SaveChanges();
}
公共接口客户端存储:IDisposable
{
void Delete(tenty实体),其中tenty:class;
IQueryable GetAll(参数字符串[]实体),其中tenty:class;
无效插入(TEntity实体),其中TEntity:class;
无效更新(TEntity实体),其中TEntity:类;
void SaveChanges();
}

使用通用存储库而不是每个聚合根都有一个具体的存储库实现的主要缺点是,您无法为特定用途创建特定方法

让您的所有存储库都从基础存储库继承,可以创建如下方法:
getProductsSinssock()
或类似于
updateOnlyProductsHattsatisfySomething()
的方法

但有些变通办法是可用的!;-)

如果通用存储库适合您的团队,请继续使用它,您可能需要添加的唯一内容是一个接受
规范作为参数的方法。正如埃里克·埃文斯和马丁·福勒所说:

规范的中心思想是将如何进行的陈述分开 要匹配候选对象,请从匹配的候选对象 反对

在您的情况下,它可以作为一个过滤器来检索正确的实体,而无需创建特定的方法

您只需将其添加到您的
IRepository
界面:

IEnumerable<T> Find(Specification<T> predicate);
规范
类可以如下所示:

public class Repository<T> : IRepository<T> where T : class
{
  public Repository(IDbContext context)
  {
    _context = context;
    _dbset   = context.Set<T>();
  }

  // some code...

  public IEnumerable<T> Find(Specification<T> specification)
  {
    return _dbset.Where(specification.Predicate);
  }

  // some code...
}
public class Specification<T>
{
  public Specification(Expression<System.Func<T, bool>> predicate)
  {
    _predicate = predicate;
  }

  internal Expression<System.Func<T, bool>> Predicate
  {
    get { return _predicate; }
  }

  private readonly Expression<System.Func<T, bool>> _predicate;
}
最后是
ProductSpecification
类:

internal static class ActionSpecification
{
  internal static Specification<Product> InStock()
  {
    return new Specification<Product>(p => p.IsInStock == true);
  }
}
内部静态类操作规范
{
内部静态规格InStock()
{
返回新规范(p=>p.IsInStock==true);
}
}
internal static class ActionSpecification
{
  internal static Specification<Product> InStock()
  {
    return new Specification<Product>(p => p.IsInStock == true);
  }
}