Postgres 9.6事务未完成实体框架核心的预期

时间:2017-03-23 19:49:09

标签: c# entity-framework transactions entity-framework-core npgsql

几天前我问了一个模糊的问题,现在我想给出一个具体的例子。这是一个示例数据库,我要将项目插入到:

enter image description here

在执行开始时它是空的。这是我插入示例项的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发生在以下项目的事务中。因此,如果连续两个最终出现故障,则第一个不会将其错误记录在数据库中。

我的测试代码中也发生了同样的事情。以下是执行结束时我的数据库的结果:

enter image description here

enter image description here

如您所见 - 尽管导致异常,但日志表中缺少Item3。

我想知道 - 这是预期的行为还是错误?有没有办法在我catch的{​​{1}}块中进行日志记录,而不是在下一个事务中 - 所以我得到了预期的体验?

P.S。使用EF 1.1.0和PGSql 9.6

P.S.2:在回滚旁边添加SaveChanges()对我的原因没有帮助

0 个答案:

没有答案