Невозможно обновить запись с помощью структуры сущностей и нинектить с помощью шаблона репозитория.

Я использую расширения 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, но это приводит к последующим ошибкам.

Заранее спасибо за помощь


person Si Robinson    schedule 17.08.2011    source источник
comment
Можете ли вы показать полный код, который вызывает исключение? Создание контекста, вызов Attach и SaveChanges не вызывают такого исключения.   -  person Slauma    schedule 17.08.2011
comment
Контекст создается в привязке IOC, я уже включил вызов метода attach и вызов фиксации unitof work, который затем вызовет метод submitchanges. Не уверен, что еще вам нужно.   -  person Si Robinson    schedule 17.08.2011
comment
Что такое model и откуда оно взялось? Внимательно прочитайте исключение: в нем говорится о нескольких объектах в ObjectStateManager. Откуда берется хотя бы второй объект с таким же ключом? Ваш код показывает только один объект с именем model. Другая проблема может заключаться в том, что ваш контекст не удаляется после веб-запроса. Тогда старые объекты (с тем же ключом!) из более ранних запросов могут все еще находиться в контексте, вызывая исключение. InRequestScope звучит неплохо для веб-приложения. Вы уверены, что вам не нужно использовать эту привязку?   -  person Slauma    schedule 17.08.2011
comment
Привет, Слаума, модель - это экземпляр объекта Event, переданный методом публикации из html-формы. Он предоставляется как объект Event привязкой MVC, если вы знакомы с этим. Я не знаю, откуда берется второй объект, и я подозреваю, что проблема заключается в том, как я привязываю контекст в IOC. надеюсь, это поможет   -  person Si Robinson    schedule 21.08.2011
comment
Вы можете проверить, есть ли объекты в контексте, используя var list = context.ChangeTracker.Entries().ToList();. Если вы вызываете это в начале действия публикации, этот список всегда должен быть пустым, как для самого первого, так и для всех последующих запросов. Я подозреваю, что список не пуст для второго и последующих запросов, что будет означать, что ваш контекст не удаляется после запроса. Я не знаком с Ninject, поэтому подробно ответить не могу. Попробуйте узнать, как правильно настроить InRequestScope время жизни для DbContext. Я думаю, что решение есть.   -  person Slauma    schedule 21.08.2011


Ответы (1)


Прикрепление работает плохо. То, что я делаю, это просто

  1. получить единственную запись
  2. скопируйте все свойства в эту запись и
  3. совершить.
person Tae-Sung Shin    schedule 17.08.2011