2

一直在从许多资源中使用 EF5 Code First 实现通用存储库、工作单元模式,并提出了以下程序集。

接口、上下文、模型、存储库、工作单元

在上下文程序集中,我有我的迁移文件夹,其中包含 Configuration.cs

internal sealed class Configuration : DbMigrationsConfiguration<Context.SportsContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(Context.SportsContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data. E.g.
        //
        //    context.People.AddOrUpdate(
        //      p => p.FullName,
        //      new Person { FullName = "Andrew Peters" },
        //      new Person { FullName = "Brice Lambson" },
        //      new Person { FullName = "Rowan Miller" }
        //    );
        //
    }
}

正如您所看到的,这个 DbMigrationsConfiguration 接受了我的 SportsContext,它也在上下文程序集中(Contexts 文件夹)中定义

 public class SportsContext : IDbContext
{
    private readonly DbContext _context;

    public SportsContext()
    {
        _context = new DbContext("SportsContext");

    }

    public void Dispose()
    {
        _context.Dispose();
    }

    public IDbSet<T> GetEntitySet<T>() where T : class
    {
        return _context.Set<T>();
    }

    public void ChangeState<T>(T entity, EntityState state) where T : class
    {
        _context.Entry(entity).State = state;
    }

    public void SaveChanges()
    {
        _context.SaveChanges();
    }
}

这实现了在 Interfaces 程序集中定义的 IDbContext

public interface IDbContext : IDisposable
{
    IDbSet<T> GetEntitySet<T>() where T : class;
    void ChangeState<T>(T entity, EntityState state) where T : class;
    void SaveChanges();
}

在我的 UnitsOfWork 程序集中,我有以下课程

public class SportUnitOfWork : IUnitofWork
{
    private readonly IDbContext _context;

    public SportUnitOfWork()
    {
        _context = new SportsContext();
    }

    private GenericRepository<Team> _teamRepository;
    private GenericRepository<Fixture> _fixtureRepository;

    public GenericRepository<Team> TeamRepository
    {
        get { return _teamRepository ?? (_teamRepository = new GenericRepository<Team>(_context)); }
    }

    public GenericRepository<Fixture> FixtureRepository
    {
        get { return _fixtureRepository ?? (_fixtureRepository = new GenericRepository<Fixture>(_context)); }
    }

    public void Save()
    {
        _context.SaveChanges();
    }

    public IDbContext Context
    {
        get { return _context; }
    }

    private bool _disposed;

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _context.Dispose();
            }
        }
        _disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

}

例如,我在 Repositories 程序集中添加了 GenericRepository 类

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    private IDbContext _context;

    public GenericRepository(IDbContext context)
    {
        _context = context;
    }

    public GenericRepository(IUnitofWork uow)
    {
        _context = uow.Context;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposing) return;

        if (_context == null) return;
        _context.Dispose();
        _context = null;
    }

    public void Add(T entity)
    {
        _context.GetEntitySet<T>().Add(entity);
    }

    public void Update(T entity)
    {
        _context.ChangeState(entity, EntityState.Modified);
    }

    public void Remove(T entity)
    {
        _context.ChangeState(entity, EntityState.Deleted);
    }

    public T FindSingle(Expression<Func<T, bool>> predicate = null, params Expression<Func<T, object>>[] includes)
    {
        var set = FindIncluding(includes);
        return (predicate == null) ? set.FirstOrDefault() : set.FirstOrDefault(predicate);
    }

    public IQueryable<T> Find(Expression<Func<T, bool>> predicate = null, params Expression<Func<T, object>>[] includes)
    {
        var set = FindIncluding(includes);
        return (predicate == null) ? set : set.Where(predicate);
    }

    public IQueryable<T> FindIncluding(params Expression<Func<T, object>>[] includeProperties)
    {
        var set = _context.GetEntitySet<T>();

        if (includeProperties != null)
        {
            foreach (var include in includeProperties)
            {
                set.Include(include);
            }
        }

        return set.AsQueryable();
    }

    public int Count(Expression<Func<T, bool>> predicate = null)
    {
        var set = _context.GetEntitySet<T>();
        return (predicate == null) ? set.Count() : set.Count(predicate);
    }

    public bool Exist(Expression<Func<T, bool>> predicate = null)
    {
        var set = _context.GetEntitySet<T>();
        return (predicate == null) ? set.Any() : set.Any(predicate);
    }
}

我遇到的问题是从 DbMigrationsConfiguration 继承的 Configuration 类需要一个 DbContext 参数。

错误是错误 1 ​​类型“Contexts.Context.SportsContext”不能用作泛型类型或方法“System.Data.Entity.Migrations.DbMigrationsConfiguration”中的类型参数“TContext”。没有从“Contexts.Context.SportsContext”到“System.Data.Entity.DbContext”的隐式引用转换。

我可以将 SportsContext 更改为也从 DbContext 继承,但随后我需要在 UnitsOfWork 程序集中添加对 EntityFramework 5 的引用,因为我们希望在不引用底层模型的情况下更改或取出每一层,这就是我采用这种模式的原因.

由于我们正在考虑在未来添加更多的上下文和模型,因此希望建立一个架构,我们可以只添加上下文、模型,然后在需要时实现相关接口。

如果我正确理解了模式,WebAPI Restful Web 服务将通过 SportUnitOfWork 与我们的数据进行交互。

如果有人对我如何做到这一点或任何我做错的事情有任何想法,请告诉我

提前谢谢马克

4

1 回答 1

1

通过执行以下操作解决了这个问题

将我的 SportsContext 类更改为抽象的 BaseContext

public abstract class BaseContext : IDbContext
{
    protected DbContext Context;

    public void Dispose()
    {
        Context.Dispose();
    }

    public IDbSet<T> GetEntitySet<T>() where T : class
    {
        return Context.Set<T>();
    }

    public void Add<T>(T entity) where T : class
    {
        DbEntityEntry dbEntityEntry = GetDbEntityEntrySafely(entity);
        dbEntityEntry.State = EntityState.Added;
    }

    public void Update<T>(T entity) where T : class
    {
        DbEntityEntry dbEntityEntry = GetDbEntityEntrySafely(entity);
        dbEntityEntry.State = EntityState.Modified;
    }

    public void Delete<T>(T entity) where T : class
    {
        DbEntityEntry dbEntityEntry = GetDbEntityEntrySafely(entity);
        dbEntityEntry.State = EntityState.Deleted;
    }

    public void SaveChanges()
    {
        // At the moment we are conforming to server wins when handling concurrency issues
        // http://msdn.microsoft.com/en-us/data/jj592904

        try
        {
            Context.SaveChanges();
        }
        catch (DbUpdateConcurrencyException e)
        {
            //Refresh using ServerWins
            var objcontext = ((IObjectContextAdapter) Context).ObjectContext;
            var entry = e.Entries;

            objcontext.Refresh(RefreshMode.StoreWins, entry);

            SaveChanges();
        }
    }

    private DbEntityEntry GetDbEntityEntrySafely<T>(T entity) where T : class
    {
        DbEntityEntry dbEntityEntry = Context.Entry(entity);

        if (dbEntityEntry.State == EntityState.Detached)
        {
            // Set Entity Key
            var objcontext = ((IObjectContextAdapter) Context).ObjectContext;

            if (objcontext.TryGetObjectByKey(dbEntityEntry.Entity))

            Context.Set<T>().Attach(entity);
        }

        return dbEntityEntry;
    }
}

在 Context 文件夹中创建了一个名为 FootballContext 的新类,它继承自 BaseContext。

public class FootballContext : BaseContext
{
    public FootballContext(string connectionstringName)
    {
        Context = new BaseFootballContext(connectionstringName);

    }
}

创建了一个名为 DbContexts 的新文件夹

在这里创建了以下类,

public class BaseFootballContext : DbContext
{
    public BaseFootballContext(string nameOrConnectionString) : base(nameOrConnectionString)
    {
    }

    public IDbSet<Fixture> Fixtures { get; set; }
    public IDbSet<Team> Teams { get; set; }  
}

public class MigrationsContextFactory : IDbContextFactory<BaseFootballContext>
{
    public BaseFootballContext Create()
    {
        return new BaseFootballContext("FootballContext");
    }
}

现在我的配置类可以接受 BaseFootballContext,因为这是一个 DbContext。

我的 UnitOfWork 类现在可以将上下文设置为 FootballContext,因此不必引用 EntityFramework。

这也适用于迁移。

我现在唯一的问题是弄清楚如何让它在断开连接的环境中工作,因为我在重新附加实体和应用更新时遇到问题。

于 2013-03-04T10:52:18.897 回答