在我的一种申请方法中,我处理了很多我必须同时保存的条目:
foreach (CategoryType category in apiCall.CategoryList)
{
EBAY_CATEGORY itemToAdd = new EBAY_CATEGORY
{
CATEGORY_ID = int.Parse(category.CategoryID),
CATEGORY_LEVEL = category.CategoryLevel,
NAME = category.CategoryName,
LEAF = category.LeafCategory,
EXPIRED = category.Expired,
VIRTUAL = category.Virtual
};
int? parentId = Int32.Parse(category.CategoryParentID[0]);
if (parentId != null)
{
itemToAdd.PARENTID = parentId;
}
db.EBAY_CATEGORY.Add(itemToAdd);
db.Entry(itemToAdd).State = EntityState.Added;
db.SaveChanges();
}
(是的,我目前正在与eBay打交道)。当这个循环开始时,我已经在一系列复杂项目中下载了大约20 000个项目。
所以你看到我发起了foreach
以确保我保存了数据库中的每个条目,但由于它进行了大量操作,因此也需要花费很多时间。处理这些物品的最佳方法是什么?
编辑因此,根据下面的一些非常有用的建议,这是我的新代码!
using (TransactionScope scope = new TransactionScope())
{
MyContext db = null;
try
{
db = new MyContext();
db.Database.Connection.Open();
db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.ValidateOnSaveEnabled = false;
int count = 0;
ApiContext context = GeteBayApiContext();
GetCategoriesCall apiCall = new GetCategoriesCall(context)
{
EnableCompression = true,
ViewAllNodes = true
};
apiCall.DetailLevelList.Add(DetailLevelCodeType.ReturnAll);
apiCall.GetCategories();
foreach (CategoryType category in apiCall.CategoryList)
{
EBAY_CATEGORY itemToAdd = new EBAY_CATEGORY
{
CATEGORY_ID = int.Parse(category.CategoryID),
CATEGORY_LEVEL = category.CategoryLevel,
NAME = category.CategoryName,
LEAF = category.LeafCategory,
EXPIRED = category.Expired,
VIRTUAL = category.Virtual
};
int? parentId = Int32.Parse(category.CategoryParentID[0]);
if (parentId != null)
{
itemToAdd.PARENTID = parentId;
}
count++;
db = AddToContext(db, itemToAdd, count, 2000, true);
}
db.SaveChanges();
}
finally
{
if (db != null)
{
db.Dispose();
}
}
scope.Complete();
}
AddToContext方法:
private static MyContext AddToContext(MyContext context, EBAY_CATEGORY itemToAdd,int count,int commitCount,
bool recreateContext)
{
context.Set<EBAY_CATEGORY>().Add(itemToAdd);
if (count%commitCount == 0)
{
context.SaveChanges();
if (recreateContext)
{
context.Dispose();
context = new MyContext();
context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;
}
}
return context;
}
它运行良好且速度更快,但每次插入大量数据后调用Savechanges
方法时,都会出现以下错误:
The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements.
这发生在大量2000个数据条目之后,或者有时在几次100个数据条目之后。我不明白什么是错的。
答案 0 :(得分:2)
不要在循环中使用db.SaveChanges()
并使用数据库事务。
如果您有太多未提交的更改,则可能会收到OutOfMemory异常,如此处所示Fastest Way of Inserting in Entity Framework
所以你必须使用modulo来db.SaveChanges()
每个x条目。取决于您的数据有多大,无论您是否需要它。
答案 1 :(得分:0)
您可以批量执行数据库更新以提高速度。我不确定你在这里使用哪个数据库,但大多数允许相当大的批次。