Мы реализовали шаблон Generic Repository, Unit of Work с 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, который также определен в сборке контекстов (папка «Контексты»).
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();
}
}
Это реализует 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);
}
}
Для примера я добавил класс GenericRepository в сборку Repositories.
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);
}
}
У меня проблема в том, что класс Configuration, который наследуется от DbMigrationsConfiguration, ожидает параметр DbContext.
Ошибка — это ошибка 1. Тип «Contexts.Context.SportsContext» не может использоваться в качестве параметра типа «TContext» в универсальном типе или методе «System.Data.Entity.Migrations.DbMigrationsConfiguration». Неявное преобразование ссылок из «Contexts.Context.SportsContext» в «System.Data.Entity.DbContext» отсутствует.
Я могу изменить SportsContext, чтобы он также наследовался от DbContext, но тогда мне нужно добавить ссылку на EntityFramework 5 в сборке UnitsOfWork, поскольку мы хотим, возможно, изменить или удалить каждый слой без какой-либо ссылки на базовые модели, поэтому я выбрал этот шаблон. .
Поскольку мы рассматриваем возможность добавления дополнительных контекстов и моделей в будущем, мы хотели настроить архитектуру таким образом, чтобы мы могли просто добавлять контекст, модель, а затем реализовывать соответствующие интерфейсы по мере необходимости.
Веб-служба WebAPI Restful будет взаимодействовать с нашими данными через SportUnitOfWork, если я правильно понял шаблоны.
Если у кого-то есть какие-либо идеи о том, как я могу это сделать или что-то, что я делаю неправильно, пожалуйста, дайте мне знать
заранее спасибо Марк
new DbContext("SportsContext")
.) Если это так, то Code First Migrations все равно не будет работать. - person bricelam   schedule 01.03.2013