2010-03-05 17 views
5

Microsoft Sync Framework uygulamasını, uygulamamıza NHibernate kullanarak devam eden alan adı altında uygulamaya çalışıyoruz.Microsoft Sync Framework, Nhibernate TooManyRowsAffectedexception ile çakışıyor

Karşılaştığımız sorunlardan biri, Sync Framework'ün ilk veritabanı yapınızı değiştirdikten sonra (gölge tabloları ve tetikleyicileri ekleyerek) NHibernate, veritabanına nesneler eklemeye çalıştığınızda bir toomanyrowsaffectedexception atarak üzülüyor gibi görünüyor.

Her güncelleştirme bildirimi için SET NOCOUNT AÇIK ve KAPALI ekleme çözümüne sahip olan bu makaleyi buldum, ancak tablo yapısı otomatik olarak nhibernate tarafından oluşturulduğundan ve eşitleme tetikleyicileri otomatik olarak tüm tetikleyicileri el ile ayarlayan Senkronizasyon Çerçevesi tarafından oluşturulduğundan gerçekten bir seçenek değil. Where's the best place to SET NOCOUNT? ama bu (-1 satır etkilenen 1 beklenen) bir StaleStateException sonuçlandı:

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

Bu soru açıklandığı gibi üzerinde SQL Server 2008 özellik NOCOUNT ayarlama çalıştı.

Senkronizasyon çerçevesini, bu NOCOUNT deyimlerini tetikleyicilerinde otomatik olarak ayarlamak için yapılandırmanın bir yolu olup olmadığını biliyor musunuz? Ya da belki de NHibernate'in daha fazla/daha az satır değişmesini beklemenin bir yolu var mı? Ya da herhangi biriniz, bu NOCOUNT ifadelerini eşitleme çerçevesinin tetikleyicilerine eklemek için otomatik bir komut dosyanız var.

Thx önceden!

cevap

6

NOCOUNT yolunun gitmenin yolu olduğunu düşünüyorum. Bunu, senkronizasyon çerçevesi tarafından kullanılan tüm tablolar için NOCOUNT ayarlayarak yapabilirsiniz. Aşağıdaki kodlara bakın. Başka bir yol, NHibernate'in yamalanması ve güncelleme sayısını görmezden gelmektir (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; 
    } 
}