Microsoft Sync Framework与Nhibernate TooManyRowsAffectedexception冲突

我们正在尝试将Microsoft Sync Framework实现到我们的应用程序中,该应用程序使用NHibernate持久化它的域。

我们遇到的一个问题是,在Sync Framework更改了您的初始数据库结构(添加影子表和触发器)之后,当您尝试将对象插入数据库时​​,NHibernate似乎会因为抛出一个toomanyrowsaffectedexception而感到不安。

我发现这篇文章的解决方案是在每个更新语句周围添加SET NOCOUNT ON和OFF,但由于表结构由nhibernate自动生成,同步触发器由Sync Framework自动生成,因此手动调整所有触发器实际上不是一个选项。

NHibernate and TooManyRowsAffectedException

我尝试按照此问题中的描述设置sql server 2008属性NOCOUNT: 哪里是设置NOCOUNT的最佳位置? 但是这导致了StaleStateException(受影响的行数为-1,预期为1)。

您是否知道是否有办法配置同步框架以在其触发器中自动设置这些NOCOUNT语句? 或者有没有办法告诉NHibernate期望更多/更少的行被更改? 或者也许你们中的任何人都有一个自动脚本来将这些NOCOUNT语句添加到同步框架的触发器中。

Thx提前!

我认为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 GetTriggers(string tableName, SqlConnection conn, SqlTransaction transaction) { var resultList = new List(); 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; } }