2010-03-05 56 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; 
    } 
} 
相关问题