簡體   English   中英

如何一次發送有限數量的插入。 C# System.Data.SQLite

[英]How to send a limited amount of inserts at a time. C# System.Data.SQLite

我必須讀取 CSV 文件(這不是問題)並一次執行 10 次插入。 我不知道 CSV 文件會有多少行。 我試着做一個循環,每個 MOD 10 都會發送一個提交,但是在兩三次之后程序給出了錯誤。 我不知道如何解決這個問題。

編輯:

對不起,我使用我的手機,我的代碼是:


using (var connection = new SqliteConnection("conn-string"))
{
    connection.Open();
    using (var transaction = connection.BeginTransaction())
    {
        for (int i = 0; i < listCode.Count; i++)
        {
            string sql = $"insert into table1 (code) values ({listCode[i]})";

            using (var command = new SqliteCommand(sql, connection))
            {
                command.ExecuteNonQuery();

                if ( i % 10 == 9)
                {
                    transaction.Commit();
                 }

            }
        }
    }
}

通常,如果要處理IEnumerable<T>中的n個項目,則可以使用IEnumerable擴展方法SkipTake ,其中跳過iteration * n項目,然后從列表中取出n項目一個循環。

請注意,如果我們在每次迭代中將循環變量增加n ,那么它就會成為我們傳遞給Skip的值。 此外,如果剩余的項目少於n個, Take(n)將返回所有剩余的項目。

例如:

// items would be the list of results from reading your csv file. Pseudocode:
List<SomeType> items = GetCSVItems(csvFilePath);

// Set this to the number of items we want to process in each batch
int batchCount = 10;

// To process a batch of 'batchCount' number of items, we first Skip(iteration * batchCount) 
// items in our list, and then we Take(batchCount) items from the list for our next batch
for (int i = 0; i < items.Count; i += batchCount)
{
    List<SomeType> itemBatch = items.Skip(i).Take(batchCount).ToList();

    // Process itemBatch here
}

您可以使用庫MoreLinq的擴展方法Batch將源序列Batch處理到大小的桶中。

如果你不想弄亂外部庫,你可以使用下面的方法,它是Batch的輕量級版本。

public static IEnumerable<IEnumerable<TSource>> BatchForward<TSource>(
    this IEnumerable<TSource> source, int size)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size));
    var counter = 0;
    var batchVersion = 0;
    using (var enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            counter++;
            batchVersion++;
            if ((counter - 1) % size == 0)
                yield return GetInnerEnumerable(enumerator, batchVersion);
        }
        batchVersion++;
    }
    IEnumerable<TSource> GetInnerEnumerable(IEnumerator<TSource> enumerator, int version)
    {
        while (true)
        {
            if (version != batchVersion)
                throw new InvalidOperationException("Enumeration out of order.");
            yield return enumerator.Current;
            if (counter % size == 0) break;
            if (!enumerator.MoveNext()) break;
            counter++;
        };
    }
}

用法示例:

foreach (var batch in Enumerable.Range(1, 22).BatchForward(5))
{
    Console.WriteLine($"{String.Join(", ", batch)}");
}

輸出:

1、2、3、4、5
6、7、8、9、10
11、12、13、14、15
16、17、18、19、20
21、22

我想這個問題現在已經過時了,因為作業可能已經過去了。

但是,從代碼中可以明顯看出,第一次transaction.Commit(); 被調用,交易將完成。 但是循環中沒有新的事務開始,所以下次該transaction.Commit(); 被調用會發生錯誤,因為將不再有活動事務!

此外,循環后沒有代碼來處理任何不能被 10 整除的剩余行。即使原始循環代碼有效,它也可能留下未提交的行,而這些行不會被正確提交。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM