以下程序是从两个表(直接从excel中导入的)中把相应的记录导入其它两张表。
因为C_BookIndex中的记录是通过ParentId组织的树型结构,为了不想重新写一个递归,所以就用了堆栈,这个应该没问题,因为导入一两万条记录时很正确。
下面的代码在C_PageIndex表记录大概有5万条左右,导入时间大概5分钟时,导入记录时不到2万条时会报标题所示的错误,报错位置如下代码中有标示,请各位帮忙解决?
var user = "xxxxxx"; var date = DateTime.Now; var bookCategoryId = 51; var indexCounter = 0; var pageCounter = 0; var dbContext = new ContentManagementEntities(); var books = (from book in dbContext.C_BookList join bookIndex in dbContext.C_BookIndex on book.BookID equals bookIndex.bookId select book).Distinct().ToList(); foreach (var book in books) dbContext.C_BookList.Detach(book); foreach (var book in books) { using (var ts = new TransactionScope()) { //insert book var cmBook = new CM_Book { BookName = book.BookName, CategoryID = bookCategoryId, ContentType = 1, AutoGeneratePinYin = true, Description = "", CreateUser = user, CreateDate = date, LastEditUser = user, LastEditDate = date }; dbContext.AddToCM_Book(cmBook); dbContext.SaveChanges(); //insert bookindex var indexStack = new Stack<C_BookIndex>(); foreach (var bookIndex in dbContext.C_BookIndex .Where(bi => bi.bookId == book.BookID && bi.ParentID == 0) .OrderByDescending(bi => bi.TransactionID)) { dbContext.C_BookIndex.Detach(bookIndex); bookIndex.ParentID = 0; indexStack.Push(bookIndex); } while (indexStack.Count > 0) { var index = indexStack.Pop(); var cmBookIndex = new CM_BookPage { BookID = cmBook.BookID, ParentPageID = index.ParentID ?? 0, Title = index.Title, OrderID = 0, CreateUser = user, CreateDate = date, LastEditUser = user, LastEditDate = date }; dbContext.CM_BookPage.AddObject(cmBookIndex); dbContext.SaveChanges(); indexCounter++; //insert page detail var detail = dbContext.C_BookPage.FirstOrDefault(bp => bp.BookId == book.BookID && bp.Id == (index.ContentId ?? -1)); var cmPageDetail = new CM_BookPageDetail { BookPageId = cmBookIndex.PageID, Content = (detail == null ? string.Empty : detail.Content), CreateUser = user, CreateDate = date, LastEditUser = user, LastEditDate = date }; dbContext.CM_BookPageDetail.AddObject(cmPageDetail); dbContext.SaveChanges();//这句报错 pageCounter++; //push to stack foreach (var bookIndex in dbContext.C_BookIndex .Where(bi => bi.bookId == book.BookID && bi.ParentID == index.ID) .OrderByDescending(bi => bi.TransactionID)) { dbContext.C_BookIndex.Detach(bookIndex); bookIndex.ParentID = cmBookIndex.PageID; indexStack.Push(bookIndex); } } //dbContext.Attach(book); //dbContext.ObjectStateManager.ChangeObjectState(book, EntityState.Deleted); //dbContext.DeleteObject(book); //dbContext.SaveChanges(); Debug.Print("Total added index:{0}", indexCounter); Debug.Print("Total added page:{0}", pageCounter); //ts.Complete(); } }
把 using (var ts = new TransactionScope()) 注释掉。
但我担心导入到一半的时候报错了,数据就不完整了,也太好清理那些脏数据。所以想用它同步下。
@沧海一杰: 你的担心是有必要的,但是,我们现在要做的事情是找出发生错误的原因,所以请你注释掉不必要的代码,并给出详细的错误信息。
@Launcher: 去掉了你说的那句,但是居然执行成功了。有点搞不懂,我试了不下十次,为什么加了TransactionScope会中途报错呢?
@沧海一杰: 其实你可以把具体的异常的详细信息给描述出来,包括堆栈信息。另外,是否考虑过 TransactionScope 的 Timeout ?
@Launcher: Timeout倒没有考虑,我设置下试试看。
是的,你这异常应该是有内部异常的,你看下内部异常是什么
去掉 using (var ts = new TransactionScope()) 试试
不知道楼主问题解决了没有,我现在也碰到相关问题了,我用了时间标记,TransactionScope(TransactionScopeOption.Required,new TimeSpan(0,5,0))
5分钟后,标记时间过了,链接就关闭了,所以会导致这个问题。
当然不能让它无限期执行下去,设定一个超时时间,然后在SaveChanges前判断时间是否超时,如果超时,手动rollback
楼主, 这问题有解决么 我也碰到这棘手的问题
请看最佳答案