none
EntiryFramework批量添加发生异常后如何重置context ? RRS feed

  • 问题

  • 问题由来:

    执行批量增加记录操作,发生了数据库异常,原因是主键值冲突,但不知道具体是哪条记录;于是,使用Catch捕获之后,想重新使用单条增加的模式,但是发现context 中已经保存了之前的批量数据(其中也包含了主键冲突的数据)。请问,应该如何清除之前已保存到context 中的数据呢?

    以下是伪代码:

    var List<entity> elist = new List<entity>(){ 
    	new entity(){ID=1,Name='a'},
    	new entity(){ID=2,Name='b'},
    	new entity(){ID=3,Name='c'},
    	new entity(){ID=4,Name='d'}
    };
    for (var i=0...) {
    	context.entity.addobject(elist[i]);
    };
    try{
    	context.savechange(); //这里执行时发生主键冲突异常
    }catch{
    	//以下是所期望的变更处理方式,但是context中已存在elist的所有记录
    	for(var i=0...){
    		try{
    			context.entity.addobject(elist[i]);
    			context.savechange();
    		}catch	{
    			..... //这里可以捕获到发生冲突的具体键值
    		}
    	}
    }
    

    或许以上的方法很笨,如果有更好的方式,请不吝赐教。

    2011年11月21日 17:09

答案

  • https://connect.microsoft.com/VisualStudio/feedback/details/513174/unable-to-refresh-some-items-in-the-objectcontext

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    • 已标记为答案 RomanYu 2011年12月8日 2:32
    2011年11月21日 18:35
    版主
  • https://connect.microsoft.com/VisualStudio/feedback/details/513174/unable-to-refresh-some-items-in-the-objectcontext

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP

    var List<entity> elist = new List<entity>(){ 
    	new entity(){ID=1,Name='a'},
    	new entity(){ID=2,Name='b'},
    	new entity(){ID=3,Name='c'},
    	new entity(){ID=4,Name='d'}
    };
    for (var i=0...) {
    	context.entity.addobject(elist[i]);
    };
    try{
    	context.savechange(); //这里执行时发生主键冲突异常
    }catch{
    	//<--新增
        foreach (var entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added))
        {
            if (entry.Entity != null)
                context.DeleteObject(entry.Entity);//这里遍历删除所有插入到context的对象
        }
    	//-->新增
    	for(var i=0...){
    		try{
    			context.entity.addobject(elist[i]);
    			context.savechange();
    		}catch	{
    			//<--新增
    			context.DeleteObject(elist[i])//这里删除刚刚savechange失败的对象
    			//-->新增
    		}
    	}
    }
    
    


    通过上述新增两个方法,已经解决问题!

    但效率方面,是否推荐使用这样操作呢?

    或者在addobject前使用context.entity.firstordefault(p=>p.id==...)查询来得更靠谱呢?

    • 已标记为答案 RomanYu 2011年12月8日 2:32
    2011年11月22日 6:01

全部回复

  • https://connect.microsoft.com/VisualStudio/feedback/details/513174/unable-to-refresh-some-items-in-the-objectcontext

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    • 已标记为答案 RomanYu 2011年12月8日 2:32
    2011年11月21日 18:35
    版主
  • 試試看下面這個方法。

    using (NorthwindEntities context = new NorthwindEntities())
    {
    	for (int i = 1; i <= 10; i++)
    	{
    		t4 t = new t4();
    		t.ProdID = i;
    		t.Amount = i * i;
    		context.AddTot4(t);
    	}
    	context.SaveChanges();
    }
    



    以上說明若有錯誤請指教,謝謝。
    http://www.dotblogs.com.tw/terrychuang/
    2011年11月21日 22:53
  • 試試看下面這個方法。

     

    using (NorthwindEntities context = new NorthwindEntities())
    {
    	for (int i = 1; i <= 10; i++)
    	{
    		t4 t = new t4();
    		t.ProdID = i;
    		t.Amount = i * i;
    		context.AddTot4(t);
    	}
    	context.SaveChanges();
    }
    


     


    以上說明若有錯誤請指教,謝謝。
    http://www.dotblogs.com.tw/terrychuang/


    您的方法有何特别之处吗?

    如果存在主键冲突,依然存在我前面发生的问题吧?

    2011年11月22日 1:46
  • https://connect.microsoft.com/VisualStudio/feedback/details/513174/unable-to-refresh-some-items-in-the-objectcontext

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP

    var List<entity> elist = new List<entity>(){ 
    	new entity(){ID=1,Name='a'},
    	new entity(){ID=2,Name='b'},
    	new entity(){ID=3,Name='c'},
    	new entity(){ID=4,Name='d'}
    };
    for (var i=0...) {
    	context.entity.addobject(elist[i]);
    };
    try{
    	context.savechange(); //这里执行时发生主键冲突异常
    }catch{
    	//<--新增
        foreach (var entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added))
        {
            if (entry.Entity != null)
                context.DeleteObject(entry.Entity);//这里遍历删除所有插入到context的对象
        }
    	//-->新增
    	for(var i=0...){
    		try{
    			context.entity.addobject(elist[i]);
    			context.savechange();
    		}catch	{
    			//<--新增
    			context.DeleteObject(elist[i])//这里删除刚刚savechange失败的对象
    			//-->新增
    		}
    	}
    }
    
    


    通过上述新增两个方法,已经解决问题!

    但效率方面,是否推荐使用这样操作呢?

    或者在addobject前使用context.entity.firstordefault(p=>p.id==...)查询来得更靠谱呢?

    • 已标记为答案 RomanYu 2011年12月8日 2:32
    2011年11月22日 6:01