Я использую расширения MVC3, Ninject, Ninject MVC, EF 4.1.
Я реализовал следующий шаблон репо.
Репозиторий.cs
public interface IRepository<T> where T : class
{
IQueryable<T> AsQueryable();
IEnumerable<T> GetAll();
IEnumerable<T> Find(Expression<Func<T, bool>> where);
T Single(Expression<Func<T, bool>> where);
T First(Expression<Func<T, bool>> where);
void Delete(T entity);
void Add(T entity);
void Attach(T entity);
}
public class Repository<T> : IRepository<T> where T : class
{
IObjectSet<T> _objectSet;
public Repository(IObjectContext objectContext)
{
_objectSet = objectContext.CreateObjectSet<T>();
//_objectSet.MergeOption = MergeOption.NoTracking;
}
public IQueryable<T> AsQueryable()
{
return _objectSet;
}
public IEnumerable<T> GetAll()
{
return _objectSet.ToList();
}
public IEnumerable<T> Find(Expression<Func<T, bool>> where)
{
return _objectSet.Where(where);
}
public T Single(Expression<Func<T, bool>> where)
{
return _objectSet.Single(where);
}
public T First(Expression<Func<T, bool>> where)
{
return _objectSet.First(where);
}
public void Delete(T entity)
{
_objectSet.DeleteObject(entity);
}
public void Add(T entity)
{
_objectSet.AddObject(entity);
}
public void Attach(T entity)
{
_objectSet.Attach(entity);
}
}
Единица работы.cs
public interface IUnitOfWork
{
void Commit();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly IObjectContext _objectContext;
public UnitOfWork(IObjectContext objectContext)
{
_objectContext = objectContext;
}
public void Dispose()
{
if (_objectContext != null)
{
_objectContext.Dispose();
}
GC.SuppressFinalize(this);
}
public void Commit()
{
_objectContext.SaveChanges();
}
}
ObjectContext.cs
public interface IObjectContext : IDisposable
{
IObjectSet<T> CreateObjectSet<T>() where T : class;
void SaveChanges();
}
public class ObjectContextAdapter : IObjectContext
{
readonly ObjectContext _context;
public ObjectContextAdapter(ObjectContext context)
{
_context = context;
}
public void Dispose()
{
_context.Dispose();
}
public IObjectSet<T> CreateObjectSet<T>() where T : class
{
return _context.CreateObjectSet<T>();
}
public void SaveChanges()
{
_context.SaveChanges();
}
}
Я использовал Ninject для привязки их в IOC, используя следующую реализацию
public override void Load()
{
Bind(typeof(IRepository<>)).To(typeof(Repository<>));
Bind<IObjectContext>().To<ObjectContextAdapter>().WithConstructorArgument("context", new MGTContainer());
Bind<IUnitOfWork>().To<UnitOfWork>();
}
Шаблон репо взят отсюда Реализация шаблона репо
Вот пример использования шаблона в контроллере
eventRepository.Attach(model);
unitOfWork.Commit();
Все отлично работает для вставки, чтения и удаления записей, но когда я вызываю присоединение, у меня возникает следующая ошибка
Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом.
Я попытался изменить привязку к InRequestScope, но это приводит к последующим ошибкам.
Заранее спасибо за помощь
Attach
иSaveChanges
не вызывают такого исключения. - person Slauma   schedule 17.08.2011model
и откуда оно взялось? Внимательно прочитайте исключение: в нем говорится о нескольких объектах в ObjectStateManager. Откуда берется хотя бы второй объект с таким же ключом? Ваш код показывает только один объект с именемmodel
. Другая проблема может заключаться в том, что ваш контекст не удаляется после веб-запроса. Тогда старые объекты (с тем же ключом!) из более ранних запросов могут все еще находиться в контексте, вызывая исключение.InRequestScope
звучит неплохо для веб-приложения. Вы уверены, что вам не нужно использовать эту привязку? - person Slauma   schedule 17.08.2011var list = context.ChangeTracker.Entries().ToList();
. Если вы вызываете это в начале действия публикации, этот список всегда должен быть пустым, как для самого первого, так и для всех последующих запросов. Я подозреваю, что список не пуст для второго и последующих запросов, что будет означать, что ваш контекст не удаляется после запроса. Я не знаком с Ninject, поэтому подробно ответить не могу. Попробуйте узнать, как правильно настроитьInRequestScope
время жизни дляDbContext
. Я думаю, что решение есть. - person Slauma   schedule 21.08.2011