2010-03-05 55 views
5

我們正試圖在我們的應用程序中實現Microsoft Sync Framework,該應用程序使用NHibernate保留其域名。Microsoft Sync Framework與Nhibernate衝突TooManyRowsAffectedexception

我們遇到的一個問題是,在Sync Framework改變了您的初始數據庫結構(添加影子表和觸發器)之後,當您試圖將對象插入數據庫時​​,NHibernate似乎因拋出toomanyrowsaffectedexception而感到不安。

我發現這篇文章的解決方案是在每個更新語句周圍添加SET NOCOUNT ON和OFF,但由於表結構是由nhibernate自動生成的,同步觸發器是由Sync Framework自動生成的,因此手動調整所有觸發器不是一個真正的選擇。

http://www.codewrecks.com/blog/index.php/2009/03/25/nhibernate-and-toomanyrowsaffectedexception/

我試着設置在這個問題描述上的SQL Server 2008性能NOCOUNT:Where's the best place to SET NOCOUNT? 但是這導致了StaleStateException(-1影響行,預計1)。

你們是否知道是否有一種方法可以配置同步框架,以便在觸發器中自動設置這些NOCOUNT語句?或者,有沒有辦法告訴NHibernate期望更多/更少的行被更改? 或者,也許你們中的任何一個都有自動腳本來將這些NOCOUNT語句添加到同步框架的觸發器。

Thx提前!

回答

6

我認爲NOCOUNT的方式是要走的路。您可以通過爲同步框架使用的所有表設置NOCOUNT來完成此操作。請參閱下面的代碼。另一種方法是修補NHibernate並忽略updatecount參見(https://nhibernate.jira.com/browse/NH-1353)。

KR,

保羅

class SqlSyncTriggerHelper 
{ 
    private const string triggerSql = @"select sys.triggers.name from sys.triggers, sys.objects 
     where sys.objects.name='{0}' and sys.objects.type = 'U' and sys.triggers.parent_id = sys.objects.object_id"; 

    private DbSyncScopeDescription syncScopeDescription; 

    public SqlSyncTriggerHelper(DbSyncScopeDescription syncScopeDescription) 
    { 
     this.syncScopeDescription = syncScopeDescription; 
    } 

    public void Apply(SqlConnection conn) 
    { 
     SqlTransaction transaction = null; 
     try 
     { 
      if (conn.State == System.Data.ConnectionState.Closed) 
      { 
       conn.Open(); 
      } 
      transaction = conn.BeginTransaction(); 
      foreach (var table in syncScopeDescription.Tables) 
      { 
       foreach (string trigger in GetTriggers(table.UnquotedLocalName, conn, transaction)) 
       { 
        AlterTrigger(trigger, conn, transaction); 
       } 
      } 
      transaction.Commit(); 
     } 
     catch 
     { 
      if (transaction != null) 
      { 
       transaction.Rollback(); 
      } 
      throw; 
     } 
     finally 
     { 
      if (transaction != null) 
      { 
       transaction.Dispose(); 
      } 
      conn.Close(); 
     } 
    } 

    private void AlterTrigger(string trigger, SqlConnection conn, SqlTransaction transaction) 
    { 
     SqlCommand newCmd = new SqlCommand(string.Format("exec sp_helptext '{0}'", trigger), conn, transaction); 
     var triggerStringBuilder = new StringBuilder(); 
     using (var reader = newCmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       triggerStringBuilder.Append(reader.GetValue(0) as string); 
      } 
     } 
     var triggerString = triggerStringBuilder.ToString(); 
     triggerString = triggerString.Replace("CREATE TRIGGER", "ALTER TRIGGER").Replace(" AS\n", " AS\nSET NOCOUNT ON\n") + "\nSET NOCOUNT OFF"; 
     var alterTriggerCommand = new SqlCommand(triggerString, conn, transaction); 
     alterTriggerCommand.ExecuteNonQuery(); 
    } 

    private IEnumerable<string> GetTriggers(string tableName, SqlConnection conn, SqlTransaction transaction) 
    { 
     var resultList = new List<string>(); 
     var command = new SqlCommand(string.Format(triggerSql, tableName), conn, transaction); 
     using (var reader = command.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       resultList.Add(reader.GetString(0)); 
      } 
     } 
     return resultList; 
    } 
} 
相關問題