Ошибка при отсоединении и присоединении объектов в структуре объекта - PullRequest
2 голосов
/ 21 апреля 2011

Я получаю объект, используя NoTracking, конвертирую и манипулирую им, отправляю его в представление asp.net mvc. Я возвращаю отредактированную версию, вызываю метод edit в моем репозитории, пытаюсь присоединить его, он выдает следующую ошибку:

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

Как мне получить данные:

IQueryable<User> query = db.Users.AsNoTracking();

Как я редактирую данные:

    public User UpdateUser(User user, IEnumerable<Expression<Func<User, object>>> properties)
    {
            db.Users.Attach(user); //Error happens right here.
            foreach (var selector in properties)
            {
                string propertyName = Helpers.PropertyToString(selector.Body);
                db.Entry(user).Property(propertyName).IsModified = true;
            }
            db.SaveChanges();
            return user;
    }

Когда я получаю сущности, использующие AsNoTracking, разве это не должно отделить меня? Даже если он не отсоединится, предполагается, что весь жизненный цикл asp.net будет перезапущен при повторной отправке данных, что сделает график пустым.

Что я здесь не так делаю?

Я делаю мои привязки так:

DbContext db = new DbContext("ConnStringName");
Bind<IUserRepository>().To<SqlServerUserRepository>()
                .WithConstructorArgument("db", db);

1 Ответ

1 голос
/ 21 апреля 2011

Похоже, ваш контекст БД создается один раз, и этот экземпляр фактически является одиночным. Когда вы пытаетесь присоединить User, контекст обнаруживает, что он уже есть в кэше, и не удается.

Я рекомендую изменить контекст, который будет создан для каждого запроса. С Ninject вы можете связать его с

Bind<YourDbContext>().ToMethod(context => CreateContext()).InRequestScope();

, где YourDbContext - это тип переменной db, а CreateContext() - метод в вашем global.ascx.

UPDATE

Вы действительно один раз создаете контекст базы данных и сохраняете его как одиночный. Не беспокойтесь, вы можете настроить свои привязки как

// DbContext db = new DbContext("ConnStringName");
Bind<DbContext>().ToMethod(context => new DbContext("ConnStringName")).InRequestScope();
Bind<IUserRepository>().To<SqlServerUserRepository>().InRequestScope();

Это создаст новый DbCOntext для каждого Запроса и предотвратит столкновение кэшированного User с отправленным User при присоединении.

...