我的域模型使用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