从服务器错误 C# 接收结果时发生传输级错误

A transport-level error has occurred when receiving results from the server Error C#

我试图从 excel 文件中读取信息并将其保存在 SQL 中。

当我 运行 本地代码时,它运行完美,但仅在 test 环境中抛出异常。

错误是:

A transport-level error has occurred when receiving results from the server. (provider: Session Provider, error: 19 - Physical connection is not usable)

我的代码如下所示:

public bool ExtractExcelToDB(int activityId, string tableName, string fileName)
{
    try
    {
        var path = GetPath(activityId);
        path = Path.Combine(path, fileName);

        using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            using (IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream))
            {
                DataSet result = excelReader.AsDataSet();
                DataTable dt = result.Tables["sheet"];
                DataTable newDt = dt.Select().Skip(1).Take(dt.Rows.Count).CopyToDataTable();

                using (SqlBulkCopy sqlBulk = new SqlBulkCopy(GetConnectionString()))
                {
                    sqlBulk.DestinationTableName = tableName;
                    sqlBulk.WriteToServer(newDt);
                }
            }

            return true;
        }
    }
}

我把异常写到数据库,这行代码失败了:

sqlBulk.WriteToServer(newDt);

我在服务器中的连接字符串如下所示:

<connectionStrings>
    <add name="xxx" 
         connectionString="metadata=res://*/DataModel.csdl|res://*/DataModel.ssdl|res://*/DataModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=xxx;initial catalog=xxx;persist security info=True;user id=xxx;password=xxx;multipleactiveresultsets=True;application name=EntityFramework&quot;" 
         providerName="System.Data.EntityClient" />
</connectionStrings>

我几乎尝试了所有看到的解决方案,但都没有成功。

编辑

I can save file with 50 rows but not with 2000.. (Problem only in test environment not in local)

您当前的连接字符串是 Entity Framework 连接字符串 - 使用相当旧的、不再真正支持的数据库优先方法和 .edmx 数据库型号。

对于 SqlBulkCopy,您需要 clean、原始 ADO.NET 连接字符串 - 尝试这样的操作:

<connectionStrings>
    <add name="BulkCopy" 
         connectionString="data source=xxx;initial catalog=xxx;persist security info=True;user id=xxx;password=xxx;multipleactiveresultsets=True;application name=EntityFramework" 
         providerName="System.Data.SqlClient" />
</connectionStrings>

将此连接字符串用于您的 SqlBulkCopy(将您的 GetConnectionString 方法调整为 return 此 "pure" ADO.NET 批量复制组件的连接字符串) ,

你应该从 msdn 看到这个页面...

https://social.msdn.microsoft.com/Forums/en-US/89d4a844-180a-40df-ba48-b3dade9b310c/error-a-transportlevel-error-has-occurred-when-receiving-results-from-the-server-provider?forum=adodotnetentityframework

2 天后我为我创建了这项工作(也使用@marc_s 回答)

我使用事务并且"save"每次只有10行

这是我的代码:

public bool ExtractExcelToDB(int activityId, string tableName, string fileName) {
  using(SqlConnection connection = new SqlConnection(GetConnectionStringBulk())) {
    SqlTransaction tran = null;
    try {
      connection.Open();
      tran = connection.BeginTransaction();

      var path = GetPath(activityId);
      path = Path.Combine(path, fileName);
      using(FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read)) {
        using(IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream)) {
          DataSet result = excelReader.AsDataSet();
          DataTable dt = result.Tables["sheet"];
          DataTable newDt = dt.Select().Skip(1).Take(dt.Rows.Count).CopyToDataTable();
          using(SqlBulkCopy sqlBulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, tran)) {
            sqlBulk.DestinationTableName = tableName;

            var bacth = newDt.Rows.Count / 10;
            for (int i = 0; i <= bacth; i++) {
              var rows = newDt.Select().Skip(i * 10).Take(10).ToArray();
              sqlBulk.WriteToServer(rows);
            }
          }

          tran.Commit();

        }
        return true;
      }


    } catch (Exception ex) {


      db.ExceptionErrors.Add(new ExceptionError {
        Value = ex.Message,
          Date = DateTime.Now
      });
      db.SaveChanges();

      if (tran != null) {
        tran.Rollback();
      }

      return false;
    }
  }
}