Мы пытаемся реализовать Microsoft Sync Framework в наше приложение, которое сохраняется, это - доменное использование NHibernate.
Одна из проблем, с которыми мы встретились, - то, что после того, как Синхронизирующая Платформа изменила Вашу начальную структуру базы данных (добавляющий теневые таблицы и триггеры), NHibernate, кажется, нарушается путем броска toomanyrowsaffectedexception, когда Вы пытаетесь вставить объекты в базу данных.
Я нашел эту статью, которая имеет решение добавления НАБОРА NOCOUNT НА и ПРОЧЬ вокруг каждого оператора обновления, но так как структура таблицы автоматически сгенерирована nhibernate, и синхронизирующие триггеры автоматически сгенерированы Синхронизирующей Платформой, корректирующей все триггеры, вручную не действительно опция.
http://www.codewrecks.com/blog/index.php/2009/03/25/nhibernate-and-toomanyrowsaffectedexception/
Я пытался установить свойство NOCOUNT SQL-сервера 2008 года на, как описано в этом вопросе: где лучшее место должно УСТАНОВИТЬ NOCOUNT? но это привело к StaleStateException (-1 затронутая строка, ожидаемая 1).
Вы парни знают, существует ли способ настроить синхронизирующую платформу для автоматической установки этих операторов NOCOUNT в, он - триггеры? Или возможно существует ли способ сказать NHibernate ожидать больше/меньше, что строки будут изменены? Или возможно у любого из Вас есть автоматизированный сценарий для добавления этих операторов NOCOUNT к триггерам синхронизирующей платформы.
Заранее спасибо!
Я думаю, что NOCOUNT путь - это путь. Вы можете сделать это, установив NOCOUNT для всех таблиц, используемых платформой синхронизации. См. Код ниже. Другой способ - исправить NHibernate и игнорировать счетчик обновлений, см. ( 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;
}
}