2010-03-05 10 views
5

Staramy się implementować Microsoft Sync Framework do naszej aplikacji, która utrzymuje swoją domenę za pomocą NHibernate.Microsoft Sync Framework koliduje z Nhibernate TooManyRowsAffectedexception

Jednym z problemów jest to, że mamy napotkanych po Sync Framework zmieniła swoją wstępną strukturę bazy danych (dodawanie tabel cieni i wyzwalaczy) NHibernate wydaje się denerwować przez rzucanie toomanyrowsaffectedexception podczas próby wstawienia obiektów do bazy danych.

Znalazłem ten artykuł, który ma rozwiązanie dodawania SET NOCOUNT ON i OFF wokół każdego oświadczenia aktualizacji, ale ponieważ struktura tabeli jest automatycznie generowana przez nhibernate, a wyzwalacze synchronizacji są automatycznie generowane przez Sync Framework, dostosowując wszystkie wyzwalacze ręcznie naprawdę nie jest to możliwe.

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

Próbowałem ustawienie serwera SQL 2008 na własność NOCOUNT jak opisano w tej kwestii: Where's the best place to SET NOCOUNT? ale spowodowało to StaleStateException (-1 wiersze dotknięte oczekuje 1).

Czy wiecie, że istnieje sposób na skonfigurowanie struktury synchronizacji do automatycznego ustawiania tych instrukcji NOCOUNT w swoich wyzwalaczach? A może jest jakiś sposób, aby powiedzieć NHibernate, aby oczekiwał, że więcej/mniej wierszy zostanie zmienionych? A może każdy z was ma zautomatyzowany skrypt, aby dodać te instrukcje NOCOUNT do wyzwalaczy struktury synchronizacji.

Thx z góry!

Odpowiedz

6

Myślę, że droga NOCOUNT jest drogą. Można to zrobić, ustawiając NOCOUNT dla wszystkich tabel używanych przez strukturę synchronizacji. Zobacz poniższy kod. Innym sposobem jest łatanie NHibernate i ignorowanie updatecount see (https://nhibernate.jira.com/browse/NH-1353).

KR,

Paul

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; 
    } 
} 
Powiązane problemy