如何一次发送有限数量的插页。 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
扩展方法 Skip
and Take
,您跳过 iteration * n
项,然后循环从列表中获取 n
项。
请注意,如果我们在每次迭代中将循环变量递增 n
,那么它将成为我们传递给 Skip
的值。此外,如果剩余的物品少于 n
,Take(n)
将 return 所有剩余的物品。
例如:
// 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
}
您可以使用扩展方法 Batch
of the library MoreLinq:将源序列分批放入大小不同的桶中。
如果你不想弄乱外部库,你可以使用下面的方法,它是 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 整除的剩余行。即使原始循环代码有效,它也可能留下未提交的行,这些行不会被正确提交.
我必须读取 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
扩展方法 Skip
and Take
,您跳过 iteration * n
项,然后循环从列表中获取 n
项。
请注意,如果我们在每次迭代中将循环变量递增 n
,那么它将成为我们传递给 Skip
的值。此外,如果剩余的物品少于 n
,Take(n)
将 return 所有剩余的物品。
例如:
// 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
}
您可以使用扩展方法 Batch
of the library MoreLinq:将源序列分批放入大小不同的桶中。
如果你不想弄乱外部库,你可以使用下面的方法,它是 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 整除的剩余行。即使原始循环代码有效,它也可能留下未提交的行,这些行不会被正确提交.