在执行开始时它是空的。这是我插入示例项的C#代码:
public static void Main(string[] args)
{
var insertables = GenerateItems();
var context = new TestDbContext();
foreach (var item in insertables)
{
Insert(item, context);
}
}
public static void Insert(Table1 t, TestDbContext context)
{
SimpleLog lg = null;
using (var transaction = context.Database.BeginTransaction())
{
try
{
//force an error on purpose
if (t.Name == "Item3" || t.Name == "Item4" || t.Name == "Item7")
{
t.Id = 1;
};
context.Table1.Add(t);
context.SaveChanges();
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
//clean the context so the error above does not persist
context.ChangeTracker.Entries()
.Where(e => e.Entity != null).ToList()
.ForEach(e => e.State = EntityState.Detached);
lg = new SimpleLog
{
Log = t.Name,
};
}
}
//my miserable attempt to log the erroneous item name
if (lg != null)
{
context = new TestDbContext();
context.SimpleLog.Add(lg);
context.SaveChanges();
}
}
private static List<Table1> GenerateItems()
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
return numbers.Select(n => new Table1
{
Name = $"Item{n}",
}).ToList();
}
我故意通过使用现有的项目ID为Item3,Item 4和Item7引发例外。
在我的真实场景中,我有数十万个txt文件,应该从文件系统中读取并作为不同表中的大量表行插入到数据库中。由于我的某些txt文件是错误的(让我们说约0.01%),我想在交易中处理这些错误。
我的真实代码是&#34;继承&#34;而且我不想从头开始,但它包含大量代码和大约50次SaveChanges()
调用。例如,如果第十次调用失败,我希望还原前9 - 即交易。
基本上发生在我的&#34;真实&#34;数据库是一切看起来都很完美,直到我注意到有时一个错误的项会导致异常,但没有在DB中记录它的名字。我打开了postgres日志,发现我的SimpleLog表的INSERTS发生在以下项目的事务中。因此,如果连续两个最终出现故障,则第一个不会将其错误记录在数据库中。
我的测试代码中也发生了同样的事情。以下是执行结束时我的数据库的结果:
如您所见 - 尽管导致异常,但日志表中缺少Item3。
我想知道 - 这是预期的行为还是错误?有没有办法在我catch
的{{1}}块中进行日志记录,而不是在下一个事务中 - 所以我得到了预期的体验?
P.S。使用EF 1.1.0和PGSql 9.6
P.S.2:在回滚旁边添加SaveChanges()
对我的原因没有帮助