我的域模型使用EntityFramework 4.1(我使用代码优先)来更新我的数据库链接的实体。我有一个会员表,然后是一个多对多的MemberPositions表。问题是,当我尝试更改权限更改的成员时,代码会引发运行时错误“实体对象不能被IEntityChangeTracker的多个实例引用”,当我从我的存储库中设置以下类:实体框架4.1与多对多更新产生错误“一个实体对象不能被多个IEntityChangeTracker实例引用”
_context.Entry(实体).STATE = EntityState.Modified
现在我在下面的链接阅读职位,但他们看起来已经过时,有些代码不起作用在EF 4.1/MVC3中:
- ADO.Net Entity Framework An entity object cannot be referenced by multiple instances of IEntityChangeTracker
- http://samscode.com/index.php/2009/12/making-entity-framework-v1-work-part-1-datacontext-lifetime-management/
所以我的问题是:
- 什么我需要做的就是此代码为EF 4.1和MVC 3个工作(例如HttpContext.Current [“myDBEntities”]不能使用今天的框架进行索引)
- 更重要的是,此代码需要驻留在哪里?我似乎无法弄清楚在第一个链接中所描述的“每个用户请求的数据上下文”方法或类。在我的域名项目中没有意义,因为它没有访问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();
}
在行'VAR memberRepository = //创建一个存储库;'什么是“创建一个存储库”究竟做,尤其是你在哪里得到的背景下,从你显然需要注入的构造函数? –
Slauma
2012-01-04 16:43:27
这只是一个快速标记作为示例。在我的实际代码中,我使用ninject在MemberQueryies类的构造函数中注入了依赖项,该类在处理ViewModel创建和解析的控制器之外,例如:“public MemberQueries(IRepository memberRepository,IRepository memberPositionRepository)” –
bigmac
2012-01-04 17:04:50
该错误表示您有一个实体附加到两个不同的上下文(设置EntityState自动附加,因此您会得到该行的错误)。这个问题与特定的模型或映射无关。在大多数情况下,这意味着您要么在请求完成后处理上下文,要么处理多个上下文。如果你使用Ninject,你应该可以使用内置的per-request-lifetime选项来管理上下文的生命周期。我建议彻底改变你的问题,提到Ninject并专注于你如何管理你的上下文生命周期。 – Slauma 2012-01-04 17:55:31