简体   繁体   中英

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? 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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