InsertOrUpdate Generic Repository

时间:2014-05-13 03:46:49

标签: c# entity-framework

请告知我,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();
       }
   }

}
}

1 个答案:

答案 0 :(得分:0)

您遇到的问题是您的InsertOrUpdate()方法调用Update()方法。

  1. 您首先要求EF按ID定位您的实体,所以此时,在EF中,它正在跟踪该实体。

  2. 然后将T entity传递给Update(),其中Update()方法要求它将Attach()传递给EF。 现在EF已经在步骤1跟踪了同一个实体,你试图让它连接()相同的实体(两者都有) 在第2步,实体具有相同的主键,这就是它失败的原因。

  3. 因此,要解决您的问题,可能有两种方法(未经测试):

    1. 不要使用FindById()来确定InsertOrUpdate() - 如果id = 0则表示需要插入else更新。

    2. 在调用Update()之前,分离您的实体FindById() - this._ctx.Entry(entity).State = EntityState.Detached

    3. 虽然在本文(http://msdn.microsoft.com/en-us/data/jj592676.aspx)中,它并不是在谈论Generic存储库,但是可以在底部找到如何在EF中实现InsertOrUpdate方法的想法。