【问题标题】:How to write a transaction to cover Moving a file and Inserting record in database?如何编写事务以涵盖移动文件和在数据库中插入记录?
【发布时间】:2011-10-29 13:59:09
【问题描述】:

我想要一个复制文件然后在数据库中插入记录的事务。 类似于下面的语句,但事务不包括复制文件。 解决办法是什么?

using (TransactionScope scope1 = new TransactionScope())
{
    // Copy a file
    fileMgr.Move(srcFileName, destFileName);

    // Insert a database record
    dbMgr.ExecuteNonQuery(insertSql);

    scope1.Complete();
}

【问题讨论】:

  • 你的问题是可以理解的。你更怕 File.Move 还是 insert 失败?

标签: c# asp.net


【解决方案1】:

尝试使用.NET Transactional File Manager

此库允许您将文件系统操作包装在事务中,如下所示:

// Wrap a file copy and a database insert in the same transaction
TxFileManager fileMgr = new TxFileManager();
using (TransactionScope scope1 = new TransactionScope())
{
    // Copy a file
    fileMgr.Copy(srcFileName, destFileName);

    // Insert a database record
    dbMgr.ExecuteNonQuery(insertSql);

    scope1.Complete();
} 

【讨论】:

  • 此库不是事务性 NTFS 的包装器。它只是实现IEnlistmentNotification 并允许手动标准文件操作与TransactionScope 一起工作。例如,要启用对现有文件的写入操作的回滚,它首先创建将要写入的文件的备份,然后写入备份的文件,最后如果事务将初始文件替换为备份/修改的文件提交,或者如果事务回滚则删除备份文件。这与事务性 NTFS无关
  • 另外请注意,lib 的作者对此非常清楚。我想在 .Net 中使用 Transactional NTFS,请参阅archive.msdn.microsoft.com/txfmanaged
  • 我对此很警惕,因为更新很少,但是看到 TxF 不在菜单上(请参阅我对 xanatos 的评论),这似乎是最好的解决方案(对我来说)。
  • 如何使用该库创建新文件?我只有 byte[] 并且需要在事务中创建该文件。
  • 谢谢,@Damith。我也对一个欺骗问题的答案发表了这条评论:Tx 文件管理器库的 github 和 nuget 版本是不同的:github 包含 File.WriteAllBytes 而 nuget 不包含。你可以在这里获取 github 版本:github.com/rsevil/Transactions
【解决方案2】:

较新版本的 Windows 具有可以使用的称为 TxF(事务性 NTFS)的东西。这里有一个代码示例:WINDOWS VISTA - INTRODUCING TXF IN C# (PART 2) - USING SYSTEM.TRANSACTIONS AND THE DTC(我很抱歉大写锁定,但页面的标题是:-))

您必须使用MoveFileTransacted 而不是DeleteFileTransactioned。进入 DTC 后,您的 SQL 连接应该被注册到其中,因此一切都应该是一个大事务。

【讨论】:

【解决方案3】:

在使用transactional NTFS 或任何其他建议之前请阅读本文:https://docs.microsoft.com/nl-nl/windows/desktop/FileIO/deprecation-of-txf

TxF 是一组复杂而细微的 API,第 3 方应用程序不常用这些 API。由于这些 API 在未来版本的 Windows 中可能不可用,并且存在更简单的替代方法来实现 TxF 开发的许多场景这一事实,Microsoft 强烈建议开发人员研究这些替代方法,而不是创建一个在他们的应用程序中依赖 TxF。

实现ACID的更好方法是使用Filestream storage

【讨论】:

    【解决方案4】:

    您可以手动滚动自己的文件事务,如果提交失败,请将文件移回原来的位置

    using (TransactionScope scope1 = new TransactionScope())
    {
        // Copy a file
        fileMgr.Move(srcFileName, destFileName);
    
        try
        {
            // Insert a database record
            dbMgr.ExecuteNonQuery(insertSql);
    
            scope1.Complete();
        } catch (Exception) {
            fileMgr.Move(destFileName, srcFileName);
        }
    }
    

    我不是 100% 确定在提交事务时是否发生错误的语法,但我认为这说明了这个概念

    【讨论】:

    • 您应该将ExeuteNonQuery 移动到try
    • 这不能保证在失败时恢复初始状态。例如,destFileName 可以由另一个文件填充。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 2023-03-16
    • 2012-12-06
    • 1970-01-01
    • 2018-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多