gpt4 book ai didi

c# transaction scope 与 yield

转载 作者:行者123 更新时间:2023-11-30 20:35:19 26 4
gpt4 key购买 nike

我的要求是处理多个成本文件,其中有数百万条记录。处理和验证后,我必须将这些记录添加到数据库中。

为了获得更好的性能,我在 foreach 循环中使用“yield”并一次返回一条记录,处理该记录并立即将该记录添加到数据库中并附上文件号。在此文件读取过程中,如果我遇到任何数据验证错误,我将抛出 InvalidRecordException。

我的要求是从与该文件相关的表中删除所有记录。简而言之,即使一条记录无效,我也想将该文件标记为无效文件,甚至不将该文件的一条记录添加到数据库中。

任何人都可以在这里帮助我,我如何在这里使用 TransactionScope。

 public class CostFiles
{
public IEnumerable<string> FinancialRecords
{
get
{
//logic to get list of DataRecords
foreach (var dataRecord in DataRecords)
{
//some processing... which can throw InvalidRecord exception
yield return dataRecord;
}
yield break;
}
}
}


public void ProcessFileRecords(CostFiles costFile, int ImportFileNumber)
{

Database db = new Database();

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
try
{
foreach (var record in costFile.FinancialRecords)
{
db.Add(record, ImportFileNumber);

}
}
catch(InvalidRecordException ex)
{
//here i want to delete all the records from the table where import file number is same as input paramter ImportFileNumber
}
}
}

最佳答案

事务范围的目的是创建一个“全有或全无”的场景,因此要么提交整个事务,要么什么都不提交。看起来您已经有了正确的想法(至少就 TransactionScope 而言。在您调用 TransactionScope.Complete() 之前,范围实际上不会将记录提交到数据库。如果未调用 Complete(),则记录当您离开事务范围时,它们将被丢弃。您可以轻松地执行以下操作:

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
bool errorsEncountered = false;

try
{
foreach (var record in costFile.FinancialRecords)
{
db.Add(record, ImportFileNumber);

}
}
catch(InvalidRecordException ex)
{
//here i want to delete all the records from the table where import file number is same as input paramter ImportFileNumber
errorsEncountered = true;
}

if (!errorsEncountered)
{
scope.Complete();
}
}

或者您可以让 Add 抛出异常并在事务范围之外处理它,因为异常会导致 Complete()不被调用,因此没有添加记录。这种方法还有一个额外的好处,即当我们已经知道它不会做任何事情时,它会停止处理额外的记录。

try
{
using (var scope = new TransactionScope(TransactionScopeOptions.Required))
{
foreach(var record in costFile.FinancialRecords)
{
db.Add(record, ImportFileNumber);
}

// if an exception is thrown during db.Add(), then Complete is never called

scope.Complete()
}
catch(Exception ex)
{
// handle your exception here
}
}

编辑 如果您不希望您的事务提升为分布式事务(这可能有额外的安全/网络要求),请确保您为事务中的每个数据库调用重用相同的 SqlConnection 对象范围。

using (var conn = new SqlConnection("myConnectionString"))
{
conn.Open();

using (var scope = new TransactionScope(...))
{
foreach(var foo in foos)
{
db.Add(foo, conn);
}

scope.Complete();
}
}

关于c# transaction scope 与 yield,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38226124/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com