请告知我,generic
存储库与UOW
一起使用,我在测试InsertOrUpdate
方法时遇到此错误。(我'在c#和EF中都是新的
结果讯息:
测试方法UnitTestProject1.ManifestUOW.ManifestUOWTest抛出异常: System.InvalidOperationException:附加类型' DomainClasses.ManifestDetail'的实体。 失败,因为同一类型的另一个实体已具有相同的主键值。 使用'附加'方法或将实体的状态设置为“未更改”#39; 或者'修改'如果图中的任何实体具有冲突的键值。这可能是因为一些 实体是新的,尚未收到数据库生成的键值。在这种情况下,请使用'添加' 方法或“添加”#39;实体状态跟踪图形,然后将非新实体的状态设置为 '不变'或者'修改'酌情。
我的通用存储库
public T FindById(object id)
{
return _set.Find(id);
}
public void Add(T entity)
{
DbEntityEntry entry = this._ctx.Entry(entity);
if (entry.State != EntityState.Detached)
{
entry.State = EntityState.Added;
}
else
{
this._set.Add(entity);
}
}
public void Update(T entity)
{
DbEntityEntry entry = this._ctx.Entry(entity);
if (entry.State != EntityState.Detached)
{
this._set.Attach(entity);
}
entry.State = EntityState.Modified;
}
public void InsertOrUpdate(T entity, object id)
{
var _Record = FindById(id);
if (_Record != null)
{
Update(entity);
}
else
{
Add(entity);
}
}
我的测试实现
[TestMethod]
public void ManifestUOWTest()
{
ApplicationUOW appUOW = new ApplicationUOW();
ManifestDetail manD=new ManifestDetail();
for (var i = 20; i <= 22; i++)
{
manD = new ManifestDetail();
manD.ID = "kkke" + i;
manD.ManifestID = "kkke";
manD.ModifiedDate = DateTime.Now;
manD.PriorityID = 1;
manD.JobNo = "8888777";
manD.PartNo = "ppppp";
manD.OpSeq = "9000";
manD.QTY = 9;
manD.Comment = "";
manD.LitNO = "Lit no";
appUOW.ManifestDetails.InsertOrUpdate(manD, manD.ID);
}
var man = new Manifest();
man.ID = "kkke";
man.CreatedDate = DateTime.Now;
man.ManifestStateID = 2;
man.MFBldgID = 1;
man.MFDestBldgID = 2;
man.UserID = "X6344";
appUOW.Manifests.InsertOrUpdate(man, man.ID);
appUOW.SaveChanges();
}
我的UOW
namespace DataLayer
{
public class ApplicationUOW:IDisposable
{
private AuditorStationDB _context = new AuditorStationDB();
private IRepository<Manifest> _manifests = null;
public IRepository<Manifest> Manifests
{
get
{
if (this._manifests == null)
{
this._manifests = new GenericRepository<Manifest>(this._context);
}
return this._manifests;
}
}
private IRepository<ManifestDetail> _manifestDetails = null;
public IRepository<ManifestDetail> ManifestDetails
{
get
{
if (this._manifestDetails == null)
{
this._manifestDetails = new GenericRepository<ManifestDetail>(this._context);
}
return this._manifestDetails;
}
}
public void SaveChanges()
{
this._context.SaveChanges();
}
public void Dispose()
{
if (this._context != null)
{
this._context.Dispose();
}
}
}
}
答案 0 :(得分:0)
您遇到的问题是您的InsertOrUpdate()方法调用Update()方法。
您首先要求EF按ID定位您的实体,所以此时,在EF中,它正在跟踪该实体。
然后将T entity
传递给Update(),其中Update()方法要求它将Attach()传递给EF。
现在EF已经在步骤1跟踪了同一个实体,你试图让它连接()相同的实体(两者都有)
在第2步,实体具有相同的主键,这就是它失败的原因。
因此,要解决您的问题,可能有两种方法(未经测试):
不要使用FindById()来确定InsertOrUpdate() - 如果id = 0则表示需要插入else更新。
在调用Update()之前,分离您的实体FindById() - this._ctx.Entry(entity).State = EntityState.Detached
虽然在本文(http://msdn.microsoft.com/en-us/data/jj592676.aspx)中,它并不是在谈论Generic存储库,但是可以在底部找到如何在EF中实现InsertOrUpdate方法的想法。