2 つのドメイン オブジェクトがあります。どちらも同じですが、PK プロパティが異なります。
public partial class Maintenance : MaintenanceBase
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int MaintenanceId { get; set; }
public virtual Employee Employee { get; set; }
}
public partial class MyMaintenance : MaintenanceBase
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int RowId { get; set; }
public virtual Employee Employee { get; set; }
}
残りのプロパティは基本クラスから継承されます。私が抱えている問題は、ポストコントローラーで変更の保存を呼び出そうとすると、次のエラーが発生することです。
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
これは(基本的に)私のコントローラーメソッドです:
[HttpPost]
public ActionResult SubmitMyMaintenance(IList<MyMaintenance> myMaintenanceList, string userName)
{
foreach (var result in myMaintenanceList)
{
var m = iMyMaintenanceRepository.GetSingle(result.RowId);
Maintenance maintenance = new Maintenance();
// Use Injector to handle mapping between viewmodel and model
maintenance.InjectFrom(m);
try
{
if (ModelState.IsValid)
{
// save the maintenance item
iMaintenanceRepository.Add(maintenance);
iMaintenanceRepository.Save();
// delete the item in MyMaintenance
iMyMaintenanceRepository.Delete(m);
iMyMaintenanceRepository.Save();
}
}
catch (DataException ex)
{
message = ex.InnerException.ToString();
}
}
// refresh the view
var mvm = new MyMaintenanceListViewModel
{
MyMaintenanceList = iMyMaintenanceRepository.FindBy(v => v.CreatedBy.Equals(userName)).ToList(),
Message = "Your maintenance items were successfully added."
};
return View("MyMaintenance", mvm);
}
これは、同じコントローラー post メソッド内に両方のドメイン オブジェクトのリポジトリ ( iMaintenanceRepository
& )のインスタンスがあり、両方が Employee エンティティへの参照を持っているためだと思われます。iMyMaintenanceRepository
たとえば、iMyMaintenanceRepository を破棄して新しいインスタンスを作成すると (最後にビューを更新する前に)、何も挿入していない Employee テーブルに null 値を挿入するとエラーが発生します。これが、Employee エンティティが 2 つの異なるデータ コンテキストに存在すると思われる理由です。私はそれを解決する方法がわかりません。私が見つけた解決策はどれも当てはまらないようで、それは私の側の実装上の問題であると考えています。
編集:リポジトリ
namespace EMMS.Models.Interfaces
{
public interface IMyMaintenanceRepository : IGenericRepository<MyMaintenance>
{
MyMaintenance GetSingle(int RowId);
}
}
namespace EMMS.Models.Repositories
{
public class MyMaintenanceRepository : GenericRepository<AppDBContext, MyMaintenance>, IMyMaintenanceRepository
{
public MyMaintenance GetSingle(int RowId)
{
var query = GetAll().FirstOrDefault(x => x.RowId == RowId);
return query;
}
}
}
namespace EMMS.ViewModels.Repositories
{
public class GenericRepository<C, T> : IDisposable, IGenericRepository<T>
where T : class
where C : DbContext, new()
{
private C _entities = new C();
public C Context
{
get { return _entities; }
set { _entities = value; }
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = _entities.Set<T>();
return query;
}
public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IQueryable<T> query = _entities.Set<T>().Where(predicate);
return query;
}
// enforce referential itegrity
public bool ValueInUse(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IQueryable<T> query = _entities.Set<T>().Where(predicate);
int count = query.Count();
return count > 0 ? true : false;
}
public virtual void Add(T entity)
{
_entities.Set<T>().Add(entity);
}
public virtual void Delete(T entity)
{
_entities.Entry(entity).State = System.Data.EntityState.Deleted;
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = System.Data.EntityState.Modified;
}
public virtual void Save()
{
_entities.SaveChanges();
}
private bool disposed = false; // to detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (_entities != null)
{
_entities.Dispose();
}
}
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
namespace EMMS.ViewModels.Interfaces
{
public interface IGenericRepository<T> where T : class
{
IQueryable<T> GetAll();
IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
bool ValueInUse(System.Linq.Expressions.Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Edit(T entity);
void Save();
void Dispose();
}
}