Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 停止SQL Server/EF执行自动回滚_C#_Sql_Entity Framework - Fatal编程技术网

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

C# 停止SQL Server/EF执行自动回滚,c#,sql,entity-framework,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

因此,我使用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
}
使用(var dbTransaction=customDb.Database.BeginTransaction()){
//删除以前创建的tmp表。。。
customDb.Database.ExecuteSqlCommand(“如果对象ID('dbo.bbldkmember\U tmp','U')不是NULL,则删除表dbo.bbldkmember\U tmp”);
//创建一个tmp表以保留所有批量插入的记录
customDb.Database.ExecuteSqlCommand(“创建表bbldkmember_tmp(“+TableCreateGuts+”);
//将文件中的所有记录插入TMP表,完成后将文件移动到存档,如果文件失败,则出错。
foreach(filenamesToHandle中的var文件名){
试一试{
customDb.Database.ExecuteSqlCommand(
@“批量插入bbldkmember\u tmp从
“+fileName+@”
与(
字段终止符=';',
行终止符='\n',
代码页='ACP',
第一行=2
);");
//移动文件
File.Move(fileName,fileName.Insert(fileName.LastIndexOf(@“\”),@“\Archive”);
}捕获(异常错误){
//返回“文件中失败”+文件名;
//忽略但记录错误
retval+=“无法加载文件”+fileName+,错误为“+err.Message+”
”; File.Move(fileName,fileName.Insert(fileName.LastIndexOf(@“\”),@“\Error”); } } //开始用我们成功读取的记录做一些事情。 //添加一列,我们可以将GUID格式化为 customDb.Database.ExecuteSqlCommand(@“ALTER TABLE bbldkmember_tmp ADD col47 VARCHAR(255)”; //根据大量检查的结果提交或回滚 }
问题是在循环之后,EF对事务进行了回滚。ALTER TABLE失败,因为如果其中一个大容量插入失败,该列已经在表中

我要做的是读取所有文件,忽略其中有错误的文件,然后处理内容,如果出现故障,则执行回滚。这可能吗

编辑:这是一个SQL server profiler的屏幕截图,显示了正在发生的事情,显然有些事情我不明白。。。

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

为了进一步尝试和解决问题,我尝试了使用SQLServerTryCatch和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 />";
    }
}
//将文件中的所有记录插入TMP表,完成后将文件移动到存档,如果文件失败,则出错。
foreach(filenamesToHandle中的var文件名)
{
尝试
{
var c=customDb.Database.SqlQuery(
@“--批量插入:
不计数;
开始尝试
批量插入bbldkmember\u tmp从
“+fileName+@”
与(
字段终止符=';',
行终止符='\n',
代码页='ACP',
第一行=2
);
选择1
结束尝试
开始捕捉
选择0
端接
)。ToList();
//移动文件
retval++=“加载的文件”+文件名+”,并显示消息“+(c.First()==1?”“确定”:“失败”)+“
”; 如果(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”); } 捕获(异常错误) { //临界误差 返回“加载文件失败”+fileName+,错误为“+err.Message+”
”; } }
SQL Server已中止该事务。EF没有参与。您可以尝试使用
try…CATCH
。我不确定这是否会阻止事务中止。(您链接到了一个不适用于此处的问题,因为它是关于
XACT\u ABORT


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

您需要执行一个
dbTransaction.Commit()之前,请使用
块执行
。如果要处理一堆文件,该怎么办。所有“工作”,但最后一个抛出一个错误。您是否回滚整个事务?现在,您的归档文件中有不在数据库中的文件。这是预期的行为吗?是的,我正在根据更新是否有效执行commit()或rollback()。如果大容量插入失败,那么我的代码就出了问题,我将不得不重做所有文件,所以是的,这是预期的行为。编辑了更多的代码以显示它是如何失败的。我们在这里没有显示的代码中找不到错误。发布提交代码。您确定EF中止了传输吗?我对此表示怀疑。SQL Server有时也会这样做以响应错误(是的,这是可怕的遗留行为)catch(Exception err){dbTransaction.Rollback();}实际上,由于TRY-catch,EF隐藏了正确的错误消息。“ALTER TABLE”语句应失败,错误为“当前事务无法提交,并且不支持写入日志文件的操作”,但EF会自动启动新事务。我应该得到这个错误的原因在关于XACT_ABORT()的帖子中解释过,这就是SQLServer“隐藏”消息。当EF开始发挥作用时,它就消失了。至少