繁体   English   中英

如果事务提交与否,如何返回?

[英]How to return if a transaction is committed or not?

我想检查事务是否已提交并返回值。

我写了下面的代码,但我不确定如何返回它是否成功。

public Task Insert(List<PortfolioCompanyLinkModel> record, CancellationToken cancellationToken = default(CancellationToken))
{
    using (var transaction = _context.Database.BeginTransaction())
    {
        try
        {
            foreach (var item in record)
            {
                PortfolioCompanyLink portfolioCompanyLink = new PortfolioCompanyLink();
                portfolioCompanyLink.PortfolioCompanyId = item.PortfolioCompanyId;
                portfolioCompanyLink.URL = item.URL;
                portfolioCompanyLink.LinkId = item.LinkId;
                portfolioCompanyLink.CreatedBy = portfolioCompanyLink.ModifiedBy = _loggedInUser;
                portfolioCompanyLink.CreatedOn = portfolioCompanyLink.ModifiedOn = DateTime.UtcNow;
                _context.PortfolioCompanyLink.AddAsync(portfolioCompanyLink, cancellationToken);
            }
            transaction.Commit();

        }
        catch (Exception ex)
        {
            transaction.Rollback();
        }
    }
    //return _context.PortfolioCompanyLink.AddAsync(record, cancellationToken);
}

请帮我在这里写退货声明

如果您想返回一个指示“成功与否”的值,您应该将方法的返回类型更改为Task<bool>并返回一个bool

public async Task<bool> Insert(List<PortfolioCompanyLinkModel> record, CancellationToken cancellationToken = default(CancellationToken))
{
    using (var transaction = _context.Database.BeginTransaction())
    {
        try
        {
            foreach (var item in record)
            {
                PortfolioCompanyLink portfolioCompanyLink = new PortfolioCompanyLink();
                portfolioCompanyLink.PortfolioCompanyId = item.PortfolioCompanyId;
                portfolioCompanyLink.URL = item.URL;
                portfolioCompanyLink.LinkId = item.LinkId;
                portfolioCompanyLink.CreatedBy = portfolioCompanyLink.ModifiedBy = _loggedInUser;
                portfolioCompanyLink.CreatedOn = portfolioCompanyLink.ModifiedOn = DateTime.UtcNow;
                await _context.PortfolioCompanyLink.AddAsync(portfolioCompanyLink, cancellationToken);
            }
            transaction.Commit();
            return true;

        }
        catch (Exception ex)
        {
            transaction.Rollback();
            return false;
        }
    }
}

在上面的示例代码中,我还将该方法标记为async并等待AddAsync方法。

您可以使用以下内容:

Transaction.Current.TransactionInformation.Status

获取状态:

交易状态

它是一个枚举。 根据 MSDN:

中止 2
事务已回滚。

活动 0
交易的状态是未知的,因为某些参与者仍然必须被轮询。

承诺 1
事务已提交。

疑点3

您的代码可能如下所示:

public Task Insert(List<PortfolioCompanyLinkModel> record, CancellationToken cancellationToken = default(CancellationToken))
{
    using (var transaction = _context.Database.BeginTransaction())
    {
        try
        {
            foreach (var item in record)
            {
                PortfolioCompanyLink portfolioCompanyLink = new PortfolioCompanyLink();
                portfolioCompanyLink.PortfolioCompanyId = item.PortfolioCompanyId;
                portfolioCompanyLink.URL = item.URL;
                portfolioCompanyLink.LinkId = item.LinkId;
                portfolioCompanyLink.CreatedBy = portfolioCompanyLink.ModifiedBy = _loggedInUser;
                portfolioCompanyLink.CreatedOn = portfolioCompanyLink.ModifiedOn = DateTime.UtcNow;
                _context.PortfolioCompanyLink.AddAsync(portfolioCompanyLink, cancellationToken);
            }
            transaction.Commit();

        }
        catch (Exception ex)
        {
            transaction.Rollback();
        }

       finally
       {
           var status = transaction.TransactionInformation.Status;
           if (status.Committed)
               return true;

           return false;  
       }
    }


    //return _context.PortfolioCompanyLink.AddAsync(record, cancellationToken);
}

mm8 的回答解释了如果代码成功与否,如何返回真/假。 没有理由检查事务的状态,因为调用 Commit 或 Rollback 的是代码本身。 即使Commit抛出, catch块也会执行 - 并再次抛出,因为事务已经回滚。

不过,EF/EF Core 中不需要此类代码。 DbContext 缓存所有更改,并且在调用SaveChanges时将它们保存到数据库中。 基本保存教程中的单个 SaveChanges中的多个操作部分解释了:

对于大多数数据库提供程序,SaveChanges 是事务性的。 这意味着所有操作要么成功要么失败,并且这些操作永远不会被部分应用。

将多个对象保存到数据库所需的一切是:

foreach (var item in record)
{
    PortfolioCompanyLink portfolioCompanyLink = new PortfolioCompanyLink();
    .....
   //In-memory operation only. Doesn't need awaiting. Doesn't change the database
   //This only modifies the in-memory entities tracked by the context
   _context.PortfolioCompanyLink.Add(portfolioCompanyLink);
}
//Writes *all* changes to the database in a single transaction
await _context.SaveChangesAsync(cancellationToken);

不需要显式事务。 SaveChangesAsync将回滚任何更改并在出现任何问题时抛出。

事实上,尝试在每一步都按照自定义AddAsync方法的方式调用SaveChangesAsync会产生意想不到的后果。 SaveChangesAsync保存所有更改,而不仅仅是最后一个。 如果该上下文有待删除的更新,则对AddAsync的第一次调用可能最终会删除或更新记录。

显式长时间运行的事务的另一个问题是它们严重损害了可扩展性,即使对于小型应用程序也是如此。 一个事务不断更新它所接触的行和表,阻止其他事务。 无缘无故地保持事务活动会导致阻塞甚至死锁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM