使用多个线程SMO到Azure SQL

时间:2017-08-18 06:55:48

标签: c# azure smo

我有一个多线程服务,它使用SMO读取表名和列名,也可能改变数据库。我们目前正在研究Azure并继续在那里尝试代码。它已经使用SQL Server很长一段时间了。 在Azure SQL中,当只使用一个线程时,一切正常。当第二个线程在第一个线程仍在执行时开始读取时,会抛出异常:

   System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
   at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
   at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader()
   at Microsoft.SqlServer.Management.Common.ConnectionManager.ExecuteTSql(ExecuteTSqlAction action, Object execObject, DataSet fillDataSet, Boolean catchException)
   at Microsoft.SqlServer.Management.Common.ServerConnection.GetExecuteReader(SqlCommand command)
   at Microsoft.SqlServer.Management.Smo.ExecuteSql.GetDataReader(String query, SqlCommand& command)
   at Microsoft.SqlServer.Management.Smo.DataProvider.SetConnectionAndQuery(ExecuteSql execSql, String query)
   at Microsoft.SqlServer.Management.Smo.ExecuteSql.GetDataProvider(StringCollection query, Object con, StatementBuilder sb, RetriveMode rm)
   at Microsoft.SqlServer.Management.Smo.SqlObjectBase.FillData(ResultType resultType, StringCollection sql, Object connectionInfo, StatementBuilder sb)
   at Microsoft.SqlServer.Management.Smo.SqlObjectBase.FillDataWithUseFailure(SqlEnumResult sqlresult, ResultType resultType)
   at Microsoft.SqlServer.Management.Smo.SqlObjectBase.BuildResult(EnumResult result)
   at Microsoft.SqlServer.Management.Sdk.Sfc.Environment.GetData()
   at Microsoft.SqlServer.Management.Sdk.Sfc.Environment.GetData(Request req, Object ci)
   at Microsoft.SqlServer.Management.Sdk.Sfc.Enumerator.GetData(Object connectionInfo, Request request)
   at Microsoft.SqlServer.Management.Smo.ExecutionManager.GetEnumeratorDataReader(Request req)
   at Microsoft.SqlServer.Management.Smo.SqlSmoObject.GetInitDataReader(String[] fields, OrderBy[] orderby)
   at Microsoft.SqlServer.Management.Smo.SqlSmoObject.ImplInitialize(String[] fields, OrderBy[] orderby)
   at Microsoft.SqlServer.Management.Smo.SqlSmoObject.Initialize(Boolean allProperties)
   at Microsoft.SqlServer.Management.Smo.SmoCollectionBase.InitializeChildObject(ObjectKeyBase key)
   at Microsoft.SqlServer.Management.Smo.SmoCollectionBase.GetObjectByKey(ObjectKeyBase key)
   at Microsoft.SqlServer.Management.Smo.TableCollection.get_Item(String name)

激烈的谷歌搜索没有产生任何可行的东西,使用SMO应该没问题,如果你不在线程之间分享任何东西。我已经更新到微软新的官方SMO 2017 nuget包,它没有帮助。第一个线程完成后,第二个线程运行正常,因此只有一个线程可以读取数据库。 非常感谢所有帮助。

我用来读取数据库的代码如下:

  private Database GetDataBase()
    {
        //do not have to get this from DB every time on same thread.
        if (_db != null) return _db;
        //GetConnection just returns new SqlConnection
        using (var conn = _executor.GetConnection() as SqlConnection)
        {
            conn.Open();
            var sConn = new ServerConnection(conn);
            var server = new Server(sConn);
            _db = server.Databases[sConn.DatabaseName];
            _db.DefaultSchema = "dbo";

            //Problem with Azure:
            //Enumerate these to ensure immediate crash, when 2nd thread kicks in
            //and 1st thread is still executing.
            //Works fine with SQL Server
            foreach (Table t in _db.Tables)
            {
                foreach (Column c in t.Columns)
                {

                }
            }
        }
        return _db;
    }

0 个答案:

没有答案