等待在可枚举上使用
Await using on enumerable
我有一段代码,我想将 using
语句应用于 commands
可枚举中的每个命令。这个的 C# 语法是什么?
await using var transaction = await conn.BeginTransactionAsync(cancel);
IEnumerable<DbCommand> commands = BuildSnowflakeCommands(conn, tenantId);
var commandTasks = new List<Task>();
foreach (var command in commands)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
commandTasks.Add(command.ExecuteNonQueryAsync(cancel));
}
try
{
await Task.WhenAll(commandTasks);
}
catch (SnowflakeDbException)
{
await transaction.RollbackAsync(cancel);
return;
}
await transaction.CommitAsync(cancel);
编辑:Rider / ReSharper 似乎认为这两者是等价的,或者至少我得到了将 for
转换为 foreach
的提示(这显然是 错误的):
for (var i = 0; i < commands.Count; i++)
{
await using var command = commands[i];
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
commandTasks.Add(command.ExecuteNonQueryAsync(cancel));
}
和
foreach (var command in commands)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
commandTasks.Add(command.ExecuteNonQueryAsync(cancel));
}
编辑 2:经过一些讨论和一些有用的回答,这就是我要处理的内容:
var transaction = await conn.BeginTransactionAsync(cancel);
var commands = BuildSnowflakeCommands(conn, tenantId);
var commandTasks = commands.Select(async command =>
{
await using (command)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
await command.ExecuteNonQueryAsync(cancel);
}
});
try
{
await Task.WhenAll(commandTasks);
await transaction.CommitAsync(cancel);
}
catch (SnowflakeDbException)
{
await transaction.RollbackAsync(cancel);
}
finally
{
await transaction.DisposeAsync();
}
您不能单独使用语言语法调用 Dispose
或 DisposeAsync
一组 IDisposable
或 IAsyncDisposable
。
您可以迭代每一个并调用适当的方法。在重新枚举之前,我会将所有命令缓存为数组或只读集合。
我会避免按照您的 JetBrains 工具的建议在您的循环中进行处理。该命令的寿命必须不止于此。
就我个人而言,我会这样做:
var commands = BuildSnowflakeCommands(conn, tenantId).ToArray();
var commandTasks = new List<Task>(commands.Length);
foreach (var command in commands)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
commandTasks.Add(command.ExecuteNonQueryAsync(cancel));
}
/// later...
foreach (var command in commands)
{
command.Dispose();
}
您可以使用 LINQ:
var commandTasks = commands.Select(async command =>
{
using (command)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
await command.ExecuteNonQueryAsync(cancel);
}
});
该命令将在退出作用域后立即处理。
完整代码:
await using var transaction = await conn.BeginTransactionAsync(cancel);
IEnumerable<DbCommand> commands = BuildSnowflakeCommands(conn, tenantId);
var commandTasks = commands.Select(async command =>
{
using (command)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
await command.ExecuteNonQueryAsync(cancel);
}
});
try
{
await Task.WhenAll(commandTasks);
}
catch (SnowflakeDbException)
{
await transaction.RollbackAsync(cancel);
return;
}
await transaction.CommitAsync(cancel);
绝对不要使用for
循环示例; await
将导致每个命令连续发生,因为在启动下一个查询之前必须等待每个查询的完成。
我有一段代码,我想将 using
语句应用于 commands
可枚举中的每个命令。这个的 C# 语法是什么?
await using var transaction = await conn.BeginTransactionAsync(cancel);
IEnumerable<DbCommand> commands = BuildSnowflakeCommands(conn, tenantId);
var commandTasks = new List<Task>();
foreach (var command in commands)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
commandTasks.Add(command.ExecuteNonQueryAsync(cancel));
}
try
{
await Task.WhenAll(commandTasks);
}
catch (SnowflakeDbException)
{
await transaction.RollbackAsync(cancel);
return;
}
await transaction.CommitAsync(cancel);
编辑:Rider / ReSharper 似乎认为这两者是等价的,或者至少我得到了将 for
转换为 foreach
的提示(这显然是 错误的):
for (var i = 0; i < commands.Count; i++)
{
await using var command = commands[i];
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
commandTasks.Add(command.ExecuteNonQueryAsync(cancel));
}
和
foreach (var command in commands)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
commandTasks.Add(command.ExecuteNonQueryAsync(cancel));
}
编辑 2:经过一些讨论和一些有用的回答,这就是我要处理的内容:
var transaction = await conn.BeginTransactionAsync(cancel);
var commands = BuildSnowflakeCommands(conn, tenantId);
var commandTasks = commands.Select(async command =>
{
await using (command)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
await command.ExecuteNonQueryAsync(cancel);
}
});
try
{
await Task.WhenAll(commandTasks);
await transaction.CommitAsync(cancel);
}
catch (SnowflakeDbException)
{
await transaction.RollbackAsync(cancel);
}
finally
{
await transaction.DisposeAsync();
}
您不能单独使用语言语法调用 Dispose
或 DisposeAsync
一组 IDisposable
或 IAsyncDisposable
。
您可以迭代每一个并调用适当的方法。在重新枚举之前,我会将所有命令缓存为数组或只读集合。
我会避免按照您的 JetBrains 工具的建议在您的循环中进行处理。该命令的寿命必须不止于此。
就我个人而言,我会这样做:
var commands = BuildSnowflakeCommands(conn, tenantId).ToArray();
var commandTasks = new List<Task>(commands.Length);
foreach (var command in commands)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
commandTasks.Add(command.ExecuteNonQueryAsync(cancel));
}
/// later...
foreach (var command in commands)
{
command.Dispose();
}
您可以使用 LINQ:
var commandTasks = commands.Select(async command =>
{
using (command)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
await command.ExecuteNonQueryAsync(cancel);
}
});
该命令将在退出作用域后立即处理。
完整代码:
await using var transaction = await conn.BeginTransactionAsync(cancel);
IEnumerable<DbCommand> commands = BuildSnowflakeCommands(conn, tenantId);
var commandTasks = commands.Select(async command =>
{
using (command)
{
command.CommandTimeout = commandTimeout;
command.Transaction = transaction;
await command.ExecuteNonQueryAsync(cancel);
}
});
try
{
await Task.WhenAll(commandTasks);
}
catch (SnowflakeDbException)
{
await transaction.RollbackAsync(cancel);
return;
}
await transaction.CommitAsync(cancel);
绝对不要使用for
循环示例; await
将导致每个命令连续发生,因为在启动下一个查询之前必须等待每个查询的完成。