实体框架核心嵌套事务或更新saveChanges()

时间:2018-05-30 15:31:52

标签: entity-framework linq entity-framework-core ef-core-2.0

我有这个API删除并将不同的用户添加到数据库中。编写此API的方式如下:

/* Assuming 'users' is an array of users to delete (if users[x].toDelete == true),
    or to add otherwise */
using (var db = new myContext())
{
    using (var dbTransaction = db.Database.BeginTransaction())
    {
        try
        {
            /* Performing deletion of Users in DB */
            SaveChanges();

            /* Performing add of Users in DB */
            foreach(user in users)
                if (!user.toDelete) {
                    db.users.add(..);
                    db.SaveChanges();
                }

            dbTransaction.Commit();
        }
        catch (ValidationException ex)
        {
            dbTransaction.Rollback();
        }
    }
}

我使用事务的原因是我有一些应该在新数据上运行的验证。例如,我不能添加两个用户使用相同的电子邮件!

所有验证服务器端都使用Data-Annotations和MetaData类完成,因此我创建了属性唯一性,它与UserMetaData类的属性电子邮件相关联。

所以,问题在于,在Uniqueness Attribute中我需要再次检查数据库以搜索具有相同电子邮件的其他用户:

public class IsUnique : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        ...
        using (var db = new myContext()) {
            /* Here I perform a select on the DB looking for records
                with the same email, all using Reflection. */
            if (recordFound > 0)
                return new ValidationResult("email already exists");

            return ValidationResult.Success;
        }
    }
}

所以,正如你所看到的,在验证中我使用new myContext(),问题出在哪里:让我假装我有一个空数据库,并在同一个查询中添加两个用户使用相同的电子邮件。

正如您所看到的,我在添加每个用户后调用db.SaveChanges(),因此我认为,当要添加的第二个用户已经过验证时,我的验证会知道添加了第一个用户并且第二个具有相同的电子邮件,因此将抛出验证异常并调用dbTransaction.Rollback()

问题是在验证器内部我调用了new myContext()并且在那个上下文中我认为那些因为db.SaveChanges()而没有的变化,我认为这是因为所有变更在交易中。

Sooo ..到目前为止我认为的解决方案有两个:

  • 嵌套事务:在API中我有一个外部事务,它在开始时保存数据库的状态,然后每次调用db.SaveChanges()时都会运行一些内部事务。执行此操作,验证确实会看到更改,但问题是,如果在我调用outerTransaction.rollback()的catch中,内部事务所做的更改不会回滚;
  • 某些方法来检索我在API中使用的上下文,即使在验证中..但在那里我只有这两个参数,所以我不知道它是否可能;

0 个答案:

没有答案