简体   繁体   English

实施此通用存储库,工作单元和存储库工厂

[英]Implementing this generic repository, unit of work and repository factory

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? 我将如何为此实现DbContext工厂? 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: 如您所见,构造函数使用DbContext,并且在使用编译到程序集中的edmx文件时,也必须传递从DbContext派生的类,如下所示:

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; 忽略_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. 在我看来,这很臭,因为您必须硬编码EF连接字符串名称的名称。

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. 因此,我们可以有一个基于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. 仅当您具有有关用于映射实体类型的到EDMX的连接字符串的信息时,基于TEntity类型的存储库的工厂才有意义。 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. 它非常适合CRUD操作(一个没有关系的实体),但是一旦您开始在实际实体或聚合根上使用它,就会遇到很多问题。 Just browse questions tagged with and and you will see. 只需浏览标记有 ,您就会看到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM