C# 处理大量的物品

C# 处理大量的物品,c#,asp.net-mvc,collections,C#,Asp.net Mvc,Collections,在我的一种应用程序方法中,我处理了大量必须同时保存的条目: foreach (CategoryType category in apiCall.CategoryList) { EBAY_CATEGORY itemToAdd = new EBAY_CATEGORY { CATEGORY_ID = int.Parse(category.CategoryID), CATEGORY_LEVEL = category.Category

在我的一种应用程序方法中,我处理了大量必须同时保存的条目:

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();
}
(是的,我目前正在处理易趣)。当这个循环开始时,我在一个复杂的项目集合中下载了大约20000个项目

您可以看到,我启动了一个
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方法:

私有静态MyContext AddToContext(MyContext上下文, 易趣\要添加的类别项目,整数计数,整数佣金计数

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;
}

这发生在大量的2000个数据条目之后,或者有时是在几次的100个数据条目之后。我不明白是怎么回事。

您可以批量更新数据库以提高速度。我不确定您在这里使用的是哪一个数据库,但大多数都允许相当大的批量。

不要使用
DB.SaveChanges()
在循环内部使用db事务

如图所示,如果有太多未提交的更改,可能会出现OutOfMemory异常


因此,您必须使用模来
db.SaveChanges()
每x个条目。这取决于您的数据有多大,您是否需要它。

看到了吗?当然。它将允许框架批量插入数据,而不是为每个表条目向数据库发出一个又一个命令。因此,您建议我将所有内容都包含在整个事务中,并ll
db.SaveChanges()
在作用域完成后或之前?在中可以找到完美答案您是否尝试增加事务超时?
使用(TransactionScope作用域=新事务范围(TransactionScopeOption.Required,new System.TimeSpan(0,15,0))
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.