我很想知道以下两个语句之间的区别是什么,为什么.ForEacHAsync不能用于创建新行,而for循环却可以呢?
这有效并添加了新的唱片产品
var recordProducts = context.RecordsProducts
.Where(i => i.RecordId == model.OldRecordId);
foreach (var rp in recordProducts)
{
var newRecordProduct = new RecordProduct
{
IsActive = true,
RecordId = model.RecordId,
ProductId = rp.ProductId,
DefendantId = rp.DefendantId,
Annotation = rp.Annotation
};
context.RecordsProducts.Add(newRecordProduct);
}
这不是
var recordProducts = context.RecordsProducts
.Where(i => i.RecordId == model.OldRecordId)
.ForEachAsync(a =>
{
var newRecordProduct = new RecordProduct
{
IsActive = true,
RecordId = model.RecordId,
ProductId = a.ProductId,
DefendantId = a.DefendantId,
Annotation = a.Annotation
};
context.RecordsProducts.Add(newRecordProduct);
}
);
答案 0 :(得分:5)
在第一个示例中,您的IQueryable<RecordProduct> recordProducts
将被同步评估,而不是异步评估,因此它将阻塞对IQueryable.GetEnumerator() ...MoveNext()
的(隐藏)调用中的线程。
在第二个示例中,.ForEachAsync
扩展方法将异步运行匿名函数,并且等效于此:
IQueryable<RecordProduct> list = await context.RecordsProducts
.Where(i => i.RecordId == model.OldRecordId);
using( DataReader rdr = await ExecuteQueryAsDataReader( list ) )
{
while( await rdr.ReadAsync() )
{
await ForEachAsyncBodyHere();
}
}
您的第二个示例不起作用,因为表达式的结果是Task
,它从未被await
编辑。如果您想使用ForEachAsync
,则需要将代码更改为此:
Task loadTask = context.RecordsProducts
.Where(i => i.RecordId == model.OldRecordId)
.ForEachAsync(a =>
{
var newRecordProduct = new RecordProduct
{
IsActive = true,
RecordId = model.RecordId,
ProductId = a.ProductId,
DefendantId = a.DefendantId,
Annotation = a.Annotation
};
context.RecordsProducts.Add(newRecordProduct);
}
);
await loadTask; // This will wait (actually, _yield_) until all of the `ForEachAsync` iterations are complete.
await context.SaveChangesAsync(); // This will actually save the new rows added to `context.RecordsProducts`
我认为任何一段代码都不一定很好-我认为最好的方法是使用ToListAsync
一次异步加载所有数据,然后使用普通的同步foreach
进行加载Add
每条记录,然后await SaveChangesAsync
:
List<RecordProduct> list = await context.RecordsProducts
.Where(i => i.RecordId == model.OldRecordId)
.ToListAsync();
foreach( RecordProduct rp in list )
{
context.RecordsProduct.Add( ... );
}
await context.SaveChangesAsync();