2012-01-04 61 views
1

我的域模型使用EntityFramework 4.1(我使用代码优先)来更新我的数据库链接的实体。我有一个会员表,然后是一个多对多的MemberPositions表。问题是,当我尝试更改权限更改的成员时,代码会引发运行时错误“实体对象不能被IEntityChangeTracker的多个实例引用”,当我从我的存储库中设置以下类:实体框架4.1与多对多更新产生错误“一个实体对象不能被多个IEntityChangeTracker实例引用”

_context.Entry(实体).STATE = EntityState.Modified

现在我在下面的链接阅读职位,但他们看起来已经过时,有些代码不起作用在EF 4.1/MVC3中:

所以我的问题是:

  1. 什么我需要做的就是此代码为EF 4.1和MVC 3个工作(例如HttpContext.Current [“myDBEntities”]不能使用今天的框架进行索引)
  2. 更重要的是,此代码需要驻留在哪里?我似乎无法弄清楚在第一个链接中所描述的“每个用户请求的数据上下文”方法或类。在我的域名项目中没有意义,因为它没有访问HttpContext的权限,所以如果它在我的Web项目中,我应该如何将它传递给域名?

为了帮助你,下面是我的域模型的一个精简版:

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; 
    } 
} 

最后,在我的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(); 
} 
+0

在行'VAR memberRepository = //创建一个存储库;'什么是“创建一个存储库”究竟做,尤其是你在哪里得到的背景下,从你显然需要注入的构造函数? – Slauma 2012-01-04 16:43:27

+0

这只是一个快速标记作为示例。在我的实际代码中,我使用ninject在MemberQueryies类的构造函数中注入了依赖项,该类在处理ViewModel创建和解析的控制器之外,例如:“public MemberQueries(IRepository memberRepository,IRepository memberPositionRepository)” – bigmac 2012-01-04 17:04:50

+1

该错误表示您有一个实体附加到两个不同的上下文(设置EntityState自动附加,因此您会得到该行的错误)。这个问题与特定的模型或映射无关。在大多数情况下,这意味着您要么在请求完成后处理上下文,要么处理多个上下文。如果你使用Ninject,你应该可以使用内置的per-request-lifetime选项来管理上下文的生命周期。我建议彻底改变你的问题,提到Ninject并专注于你如何管理你的上下文生命周期。 – Slauma 2012-01-04 17:55:31

回答

1

由于Slauma陈述(和包含在我原来的职位为编辑),这里的解决方案。

在App_Start.NinjectMVC3控制器中,使用以下代码(确保InRequestScope)存在。在我原来的代码中,它不是,因此它不工作......

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

我永远搜索找到这个! – 2013-01-22 06:27:35

相关问题