实现这个通用的存储库,工作单元和存储库工厂 [英] Implementing this generic repository, unit of work and repository factory

查看:206
本文介绍了实现这个通用的存储库,工作单元和存储库工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经修改了这一点,从我找到这个例子的原始文章中删除了一个方法。这是通用资源库。

  ///< summary> 
///与DbContext一起使用的存储库基类最初来自http://dotnetspeak.com/index.php/2011/03/repository-pattern-with-entity-framework/
///< /总结>
///< typeparam name =TContext>此存储库操作的DdContext的类型< / typeparam>
public class RepositoryBase< TContext> :IDisposable,IRepositoryBase其中TContext:DbContext,IObjectContextAdapter,new()
{
private DbContext _dbContext;
public DbContext CurrentContext {get;组; }

///< summary>
///创建存储库的新实例
///< / summary>
///< param name =DbContext>对于嵌入式edmx资源,请在从DBContext< / param>指派的类中定义base(name = yourAppEntities)。
public RepositoryBase(DbContext _context)
{
_dbContext = new TContext();
CurrentContext = _dbContext;
}
///< summary>
///从数据库
中选择数据///< / summary>
///< typeparam name =TItem>要选择的数据类型< / typeparam>
///<返回>< /返回>
public IQueryable< TItem>选择< TItem>()
其中TItem:class,new()
{
DbSet< TItem> _set = _dbContext.Set< TItem>();
return _set;
}
///< summary>
///将新项目插入数据库
///< / summary>
///< typeparam name =TItem>要插入的项目类型< / typeparam>
///< param name =item>插入项目< / param>
///<返回>已插入项目< /返回>
public TItem Insert< TItem>(TItem item)
where TItem:class,new()
{
DbSet< TItem> _set = _dbContext.Set< TItem>();
_set.Add(item);
_dbContext.SaveChanges();

退货项目;
}
///< summary>
///更新一个项目
///< / summary>
///< typeparam name =TItem>要更新的项目类型< / typeparam>
///< param name =item>要更新的项目< / param>
///<返回>已更新项目< /返回>
public TItem Update< TItem>(TItem item)
其中TItem:class,new()
{
DbSet< TItem> _set = _dbContext.Set< TItem>();
_set.Attach(item);
_dbContext.Entry(item).State = System.Data.EntityState.Modified;
_dbContext.SaveChanges();
退货项目;
}
///< summary>
///删除一个项目
///< / summary>
///< typeparam name =TItem>要删除的项目类型< / typeparam>
///< param name =item>要删除的项目< / param>
public void删除< TItem>(TItem item)
其中TItem:class,new()
{
DbSet< TItem> _set = _dbContext.Set< TItem>();
var entry = _dbContext.Entry(item);
if(entry!= null)
{
entry.State = System.Data.EntityState.Deleted;
}
else
{
_set.Attach(item);
}
_dbContext.Entry(item).State = System.Data.EntityState.Deleted;
_dbContext.SaveChanges();
}


///< summary>
/// Dipose存储库
///< / summary>
public void Dispose()
{
if(_dbContext!= null)
{
_dbContext.Dispose();
_dbContext = null;



$ / code $ / pre

如何实现一个DbContext工厂呢?正如你所看到的构造函数接受一个DbContext,以及使用编译到程序集中的edmx文件时,你必须传入一个从DbContext派生的类,如下所示:

  public class ContextWrapper:DbContext 
{
public string _connectionString {get;组; }
public ContextWrapper()
:base(name =+ ConfigurationManager.ConnectionStrings [MyEFStringName]。Name)
{
_connectionString = this.Database.Connection.ConnectionString ;



$ b

忽略_connectionstring获得;设置;它是用于测试的。



对我来说,这看起来很臭,因为你必须硬编码EF连接字符串名称。



我想找出一种方法来阻止工厂周围也是通用工厂。因此,我们可以根据TEntity生成一个存储库。

解决方案

这个怎么样:

  public class ContextWrapper:DbContext 
{
public ContextWrapper(string ConnectionStringName)
:base(name =+ ConnectionctionStringName)




$ b

基于TEntity类型的存储库工厂只有在您有关于用于映射实体类型的EDMX连接字符串的信息。但是这些信息必须硬编码到工厂,或者我不明白你的问题。

顺便说一句。一旦您尝试使用它,您的通用方法将完全失败。它对CRUD操作非常有用,一个实体没有关系,但一旦你开始在真实实体或聚合根上使用它,你将会遇到很多问题。只需浏览带有 entity-framework 存储库模式和你会看到。


I have modifed this a bit, removed one method, from the original post where I found this example. Here is the generic repository.

/// <summary>
/// Repository base class used with DbContext Originally From http://dotnetspeak.com/index.php/2011/03/repository-pattern-with-entity-framework/
/// </summary>
/// <typeparam name="TContext">Type of DdContext that this repositiory operates on</typeparam>
public class RepositoryBase<TContext> : IDisposable, IRepositoryBase where TContext : DbContext, IObjectContextAdapter, new()
{
    private DbContext _dbContext;
    public DbContext CurrentContext { get; set; }

    /// <summary>
    /// Create new instance of repository
    /// </summary>
    /// <param name="DbContext">For embeded edmx resource please define base("name=yourAppEntities") in a class derrived from DBContext</param>
    public RepositoryBase(DbContext _context)
    {
        _dbContext = new TContext();
        CurrentContext = _dbContext;
    }
    /// <summary>
    /// Select data from database
    /// </summary>
    /// <typeparam name="TItem">Type of data to select</typeparam>
    /// <returns></returns>
    public IQueryable<TItem> Select<TItem>()
       where TItem : class, new()
    {
        DbSet<TItem> _set = _dbContext.Set<TItem>();
        return _set;
    }
    /// <summary>
    /// Insert new item into database
    /// </summary>
    /// <typeparam name="TItem">Type of item to insert</typeparam>
    /// <param name="item">Item to insert</param>
    /// <returns>Inserted item</returns>
    public TItem Insert<TItem>(TItem item)
        where TItem : class, new()
    {
        DbSet<TItem> _set = _dbContext.Set<TItem>();
        _set.Add(item);
        _dbContext.SaveChanges();

        return item;
    }
    /// <summary>
    /// Update an item
    /// </summary>
    /// <typeparam name="TItem">Type of item to update</typeparam>
    /// <param name="item">Item to update</param>
    /// <returns>Updated item</returns>
    public TItem Update<TItem>(TItem item)
        where TItem : class, new()
    {
        DbSet<TItem> _set = _dbContext.Set<TItem>();
        _set.Attach(item);
        _dbContext.Entry(item).State = System.Data.EntityState.Modified;
        _dbContext.SaveChanges();
        return item;
    }
    /// <summary>
    /// Delete an item
    /// </summary>
    /// <typeparam name="TItem">Type of item to delete</typeparam>
    /// <param name="item">Item to delete</param>
    public void Delete<TItem>(TItem item)
       where TItem : class, new()
    {
        DbSet<TItem> _set = _dbContext.Set<TItem>();
        var entry = _dbContext.Entry(item);
        if (entry != null)
        {
            entry.State = System.Data.EntityState.Deleted;
        }
        else
        {
            _set.Attach(item);
        }
        _dbContext.Entry(item).State = System.Data.EntityState.Deleted;
        _dbContext.SaveChanges();
    }


    /// <summary>
    /// Dipose repository
    /// </summary>
    public void Dispose()
    {
        if (_dbContext != null)
        {
            _dbContext.Dispose();
            _dbContext = null;
        }
    }
}

How would i implement a DbContext factory for this? As you can see the constructor takes a DbContext, as well when using edmx files compiled in to an assembly you have to pass in a class that derives from DbContext like so:

public class ContextWrapper: DbContext
{
    public string _connectionString { get; set; }
    public ContextWrapper()
        : base("name=" + ConfigurationManager.ConnectionStrings["MyEFStringName"].Name)
    {
        _connectionString = this.Database.Connection.ConnectionString;


    }
}

Ignore the _connectionstring get;set; it was for testing.

To me this seems very smelly because of the fact you have to hard code the name of the EF connectionstring name.

I would like to figure out a way to impement a Factory around this that is Generic as well. So we can have a repository generated based on TEntity.

解决方案

What about this:

public class ContextWrapper : DbContext
{
    public ContextWrapper(string ConnectionStringName)
        : base("name=" + ConnectionctionStringName)
    { }
}

Factory for repositories based on TEntity type makes sense only if you have information about connections string to EDMX used to map the entity type. But such information must be hardcoded to factory or perhaps I don't understand your question.

Btw. your generic approach will completely fail once you try to use it. It works great for CRUD operations one entities without relations but once you start to use it on real entities or aggregate roots you will have so many problems. Just browse questions tagged with and and you will see.

这篇关于实现这个通用的存储库,工作单元和存储库工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆