c# - 停止 SQL Server/EF 执行自动回滚

标签 c# sql entity-framework

因此,我正在使用 EF6 执行一些原始 SQL 查询,并且我希望在事务中使用它,因为我正在根据查询的结果移动文件。这是代码的简短版本:

using (var dbTransaction = customDb.Database.BeginTransaction()) {
    //Drop previously created tmp tables...
    customDb.Database.ExecuteSqlCommand("IF OBJECT_ID('dbo.bbldkmember_tmp', 'U') IS NOT NULL DROP TABLE dbo.bbldkmember_tmp");
    //Create a tmp table to keep all the bulk inserted records
    customDb.Database.ExecuteSqlCommand("CREATE TABLE bbldkmember_tmp ( " + TableCreateGuts + " )");

    //Insert all record from the files into the TMP table, move the files to the archive when done, error if the file fails. 
    foreach (var fileName in filenamesToHandle) {
        try {
            customDb.Database.ExecuteSqlCommand(
                @"BULK INSERT bbldkmember_tmp FROM 
                    '" + fileName + @"'
                    WITH (
                        FIELDTERMINATOR = ';',
                        ROWTERMINATOR = '\n',
                        CODEPAGE = 'ACP',
                        FIRSTROW = 2
                        );");
            //Move file
            File.Move(fileName, fileName.Insert(fileName.LastIndexOf(@"\"), @"\Archive"));
        } catch (Exception err){
            //return "Failed in file " + fileName;
            //ignore but log error 
            retval += "Failed to load file " + fileName + " with error " + err.Message + "<br />";
            File.Move(fileName, fileName.Insert(fileName.LastIndexOf(@"\"), @"\Error"));
        }
    }
    //Start doing stuff with the records that we succeeded reading.
    //Add a column that we can format a GUID into  
    customDb.Database.ExecuteSqlCommand(@"ALTER TABLE bbldkmember_tmp ADD col47 VARCHAR(255)");
    //commit or rollback based on the results of a lot of checks
}

问题是在循环之后,EF对事务做了回滚。如果其中一个批量插入失败,则 ALTER TABLE 将失败,因为该列已经在表中。

我想做的是读取所有文件,忽略其中有错误的文件,然后处理内容并在此处出现故障时进行回滚。这可能吗?

编辑:这是来自 SQL Server Profiler 的屏幕截图,显示了正在发生的事情,显然有一些我不明白的地方...... Strange transactions

编辑 #3:因此,我检查了文件中没有错误时会发生什么。如您所见,在批量插入之后没有启动第二个事务。 All ok

为了进一步尝试并制定解决方法,我尝试使用 SQL 服务器 TRY CATCH,使用 SqlQuery<>。结果是一样的:

//Insert all record from the files into the TMP table, move the files to the archive when done, error if the file fails. 
foreach (var fileName in filenamesToHandle)
{
    try
    {
        var c = customDb.Database.SqlQuery<int>(
            @"--Bulk insert: 
                SET NOCOUNT ON; 
                BEGIN TRY
                    BULK INSERT bbldkmember_tmp FROM 
                    '" + fileName + @"'
                    WITH (
                        FIELDTERMINATOR = ';',
                        ROWTERMINATOR = '\n',
                        CODEPAGE = 'ACP',
                        FIRSTROW = 2
                    );
                    SELECT 1
                END TRY
                BEGIN CATCH
                    SELECT 0 
                END CATCH                                 
        ").ToList();
        //Move file
        retval += "Loaded file " + fileName + " with message " + (c.First() == 1 ?"ok":"fail") + "<br />";
        if(File.Exists(fileName.Insert(fileName.LastIndexOf(@"\"), c.First() == 1 ? @"\Archive": @"\Error")))
            File.Delete(fileName.Insert(fileName.LastIndexOf(@"\"), c.First() == 1 ? @"\Archive" : @"\Error"));
        File.Move(fileName, fileName.Insert(fileName.LastIndexOf(@"\"), c.First() == 1 ? @"\Archive": @"\Error"));
    }
    catch (Exception err)
    {
        //Critical error
        return "Failed to load file " + fileName + " with error " + err.Message + "<br />";
    }
}

最佳答案

SQL Server 已中止事务。英孚没有参与。您可以尝试使用 TRY...CATCH。我不确定这是否会阻止交易中止。 (您链接到此处不适用的问题,因为它是关于 XACT_ABORT 的)。

一个潜在的解决方案是在主事务之外进行批量插入。

关于c# - 停止 SQL Server/EF 执行自动回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29645799/

相关文章:

c# - 使用 mvc4 View 处理嵌套集合到 Controller

c# - 如何使用主键合并两个数据表?

c# - 从 X509Certificate2 中删除私钥

c# - 为什么我从两个几乎相等的表达式中得到不同的结果以使用 Entity Framework 上下文从数据库中获取数据

javascript - 我的数据应该在 ASP.NET MVC 应用程序中的何处进行验证?

c# - sql 查询表达式中的语法错误(缺少运算符)

sql - 如何在SQL中查找不匹配记录的列表? (遇到一些麻烦)

mysql - 将选择转换为数组以进行 DELETE FROM

c# - 有条件地调用 Linq 扩展方法

c# - Entity Framework 运行转换代码时抛出异常