Entity Framework 4.1 с обновлением «многие ко многим» выдает ошибку «На объектный объект нельзя ссылаться несколькими экземплярами IEntityChangeTracker» - PullRequest
1 голос
/ 04 января 2012

Моя модель домена использует EntityFramework 4.1 (а я использую код в первую очередь) для обновления моей БД с помощью связанных сущностей. У меня есть таблица членов, а затем таблица «многие ко многим». Проблема заключается в том, что когда я пытаюсь выполнить обновление для члена с измененными разрешениями, код выдает ошибку времени выполнения « На объект сущности нельзя ссылаться несколькими экземплярами IEntityChangeTracker », когда я устанавливаю следующие из моего репозитория класса:

_context.Entry (entity) .State = EntityState.Modified

Теперь я прочитал посты по следующим ссылкам, но они выглядят устаревшими, и часть кода не работает в EF 4.1 / MVC3:

Итак, мои вопросы:

  1. Что мне нужно сделать, чтобы этот код работал для EF 4.1 и MVC 3 (например, HttpContext.Current ["myDBEntities"] не может быть проиндексирован с использованием сегодняшнего фреймворка)
  2. Что еще более важно, где должен находиться этот код? Я не могу понять, где разместить метод или класс "datacontext per user per request", как описано в первой ссылке. Это не имеет смысла в моем доменном проекте, потому что у него нет доступа к HttpContext, поэтому, если он находится в моем веб-проекте, как мне передать его в домен?

Чтобы помочь вам, ниже приведена урезанная версия модели моего домена:

public class Entity
{
  public int Id { get; set; }
}

public class Member : Entity
{
  public string Name { get; set; }
  public virtual List<MemberPosition> Positions { get; set; }
}

public class MemberPosition : Entity
{
  public string Name { get; set; }
}

public class EfDbContext : DbContext
{
  public DbSet<Member> Members { get; set; }
  public DbSet<MemberPosition> MemberPositions { get; set; }
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Configurations.Add(new MemberMap());
    modelBuilder.Configurations.Add(new MemberPositionMap());
  }
}

public class MemberMap : EntityTypeConfiguration<Member>
{
  public MemberMap()
  {
    ToTable("Members");
    HasMany(m => m.Positions).WithMany().Map(
      m => m.ToTable("Member_MemberPositions").MapLeftKey("MemberId").MapRightKey("PositionId"));
  }
}

public class MemberPositionMap : EntityTypeConfiguration<MemberPosition>
{
  public MemberPositionMap()
  {
    ToTable("MemberPositions");
    Property(x => x.Name).IsRequired().HasMaxLength(100);
  }
}

public interface IRepository<TEntity>
{
  bool Update(TEntity entity);
}

public class Repository<TEntity> : IRepository<TEntity> where TEntity : Entity
{
  private readonly EfDbContext _context;
  private readonly DbSet<TEntity> _dbSet;

  public Repository(EfDbContext context)
  {
    _context = context;
    _dbSet = _context.Set<TEntity>();
  }

  public bool Update(TEntity entity)
  {
    _context.Entry(entity).State = EntityState.Modified;
    _context.SaveChanges();
    return true;
  }
}

И, наконец, урезанная версия метода Edit в моем MemberController:

public class MemberController : Controller
{
  [HttpPost]
  public ActionResult Edit(MemberDetailViewModel memberDetailViewModel)
  {
    if (ModelState.IsValid)
    {
      var updatedMember = // Gets the member data from the view model...
      var memberRepository = // Creates a Repository<Member>;
      memberRepository.Update(updatedMember);
      return // blah... blah... blah...
    }
  }
}

Любые предложения приветствуются!

РЕДАКТИРОВАТЬ: ЭТО РЕШЕНИЕ (ЭТО ЛЕГКО!)

В контроллере App_Start.NinjectMVC3 используйте следующий код (убедитесь, что InRequestScope) присутствует. В моем исходном коде это не было, следовательно, оно не работало ...

private static void RegisterServices(IKernel kernel)
{
  kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
}

1 Ответ

1 голос
/ 05 января 2012

Как сказал Слаума (и в том виде, в котором он включен в мой исходный пост в качестве правки), вот решение.

В контроллере App_Start.NinjectMVC3 используйте следующий код (убедитесь, что InRequestScope) присутствует.В моем исходном коде это не было, следовательно, оно не работало ...

private static void RegisterServices(IKernel kernel)
{
  kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
}
...