2015-04-19 2 views
1

Я использую его в консольном проекте.
.NET Framework: 4.5SQLDependency Событие Onchange всегда срабатывает без изменения данных

В моем тестовом коде SQLDependency onChange всегда срабатывает, хотя в базе данных нет изменений данных.

class Program 
{ 
private static string _connStr; 

static void Main(string[] args) 
{ 
    _connStr = "data source=xxx.xxx.xx.xx;User Id=xxx;Password=xxx; Initial Catalog=xxx"; 
    SqlDependency.Start(_connStr); 
    UpdateGrid(); 
    Console.Read(); 
} 


private static void UpdateGrid() 
{ 
    using (SqlConnection connection = new SqlConnection(_connStr)) 
    { 
     using (SqlCommand command = new SqlCommand("select msgdtl,msgid From NotifyMsg", connection)) 
     { 
      command.CommandType = CommandType.Text; 
      connection.Open(); 
      SqlDependency dependency = new SqlDependency(command); 
      dependency.OnChange += new OnChangeEventHandler(dependency_OnChange); 

      SqlDataReader sdr = command.ExecuteReader(); 
      Console.WriteLine(); 
      while (sdr.Read()) 
      { 
       Console.WriteLine("msgdtl:{0}\t (msgid:{1})", sdr["msgdtl"].ToString(), sdr["msgid"].ToString()); 
      } 
      sdr.Close(); 
     } 
    } 
} 

private static void dependency_OnChange(object sender, SqlNotificationEventArgs e) 
{ 
    UpdateGrid(); 
} 

, когда я начинаю работать, onChange событие срабатывает и никогда не останавливаются. Но никаких изменений в моей базе данных нет.

ответ

1

Попробуйте проверить объект SqlNotificationEventArgs в методе dependency_OnChnage. Похоже, у вас там ошибка. У меня было одно и то же поведение SqlDependency один раз, и проблема была решена путем изменения select msgdtl,msgid From NotifyMsg на select msgdtl,msgid From dbo.NotifyMsg (добавлен оператор dbo).

Но я должен предупредить вас: будьте осторожны, используя класс SqlDependency - он имеет problems с утечками памяти. Hovewer, вы можете использовать реализацию с открытым исходным кодом класса SqlDependency - SqlDependencyEx. Он использует триггер базы данных и собственное уведомление Service Broker для получения событий о изменениях таблицы. Это пример использования:

int changesReceived = 0; 
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
      TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) 
{ 
    sqlDependency.TableChanged += (o, e) => changesReceived++; 
    sqlDependency.Start(); 

    // Make table changes. 
    MakeTableInsertDeleteChanges(changesCount); 

    // Wait a little bit to receive all changes. 
    Thread.Sleep(1000); 
} 

Assert.AreEqual(changesCount, changesReceived); 

С SqlDependecyEx вы в состоянии контролировать INSERT, DELETE, UPDATE отдельно и получить фактические измененные данные (xml) в случае объектно арг. Надеюсь, эта помощь.

+1

SqlDependecyEx более Userful, так как мне нужно контролировать только вставку! Спасибо за рекомендацию! – wtf512

+0

Добро пожаловать! – dyatchenko

0

существует обычай реализации SqlDependency, что сообщит вам измененные записи таблицы:

var _con= "data source=.; initial catalog=MyDB; integrated security=True"; 

    static void Main() 
    { 
     using (var dep = new SqlTableDependency<Customer>(_con, "Customer")) 
     { 
      dep.OnChanged += Changed; 
      dep.Start(); 

      Console.WriteLine("Press a key to exit"); 
      Console.ReadKey(); 

      dep.Stop(); 
     } 
    } 

    static void Changed(object sender, RecordChangedEventArgs<Customer> e) 
    { 
     if (e.ChangeType != ChangeType.None) 
     { 
      for (var index = 0; index < e.ChangedEntities.Count; index++) 
      { 
       var changedEntity = e.ChangedEntities[index]; 
       Console.WriteLine("DML operation: " + e.ChangeType); 
       Console.WriteLine("ID: " + changedEntity.Id); 
       Console.WriteLine("Name: " + changedEntity.Name); 
       Console.WriteLine("Surame: " + changedEntity.Surname); 
      } 
     } 
    } 

Вот ссылка: [https://tabledependency.codeplex.com]

Смежные вопросы