SqlNotificationEvent уведомляет несколько раз даже для одной вставки в базу данных
SqlNotificationEvent
уведомить несколько раз даже для одной вставки в базу данных.
Даже для одиночной вставки / обновления / удаления в таблице событие уведомляют в течение нескольких раз с e.Type == SqlNotificationType.Change
Может кто-нибудь помочь, почему это происходит. Он должен уведомить только один раз об одном изменении в таблице.
static class Program
{
private static string mStarterConnectionString = "Data Source=localhost;Database=SqlDependencyTest;Persist Security Info=false;Integrated Security=false;User Id=startUser;Password=startUser";
private static string mSubscriberConnectionString = "Data Source=localhost;Database=SqlDependencyTest;Persist Security Info=false;Integrated Security=false;User Id=subscribeUser;Password=subscribeUser";
public const string CACHE_KEY = "APPCACHEKEY";
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Starting the listener infrastructure...
SqlDependency.Start(mStarterConnectionString);
// Registering for changes...
RegisterForChanges();
Application.Run(new SqlCache());
// Quitting...
SqlDependency.Stop(mStarterConnectionString);
}
public static DataTable RegisterForChanges()
{
DataTable dataTable = new DataTable();
// Connecting to the database using our subscriber connection string and
// waiting for changes...
SqlConnection oConnection = new SqlConnection(mSubscriberConnectionString);
oConnection.Open();
try
{
using (SqlCommand oCommand = new SqlCommand("dbo.GetUsers", oConnection))
//using (SqlCommand oCommand = new SqlCommand("SELECT ID, Name FROM dbo.Users", oConnection))
{
oCommand.CommandType = CommandType.StoredProcedure;
SqlDependency oDependency = new SqlDependency(oCommand);
oDependency.OnChange += new OnChangeEventHandler(OnNotificationChange);
using (SqlDataAdapter adapter = new SqlDataAdapter(oCommand))
adapter.Fill(dataTable);
}
AppMain.Cache.Insert(CACHE_KEY, dataTable, null, Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(60));
}
finally
{
oConnection.Close();
}
return dataTable;
}
public static void OnNotificationChange(object caller, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
RegisterForChanges();
}
2 ответа
Можно использовать объект SqlNotificationInfo объекта SqlNotificationEventArgs и проверить, является ли он Вставить, Обновить или Удалить, и игнорировать остальные.
public static void OnNotificationChange(object caller, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change && (e.Info == SqlNotificationInfo.Insert || e.Info == SqlNotificationInfo.Delete || e.Info == SqlNotificationInfo.Update))
{
SqlDependency dependency =(SqlDependency)sender;
dependency.OnChange -= OnNotificationChange;
RegisterForChanges();
}
}
У меня была такая же проблема, как описано в вопросе. Мне удалось точно определить, что проблема возникла в результате создания нескольких SqlCommand
экземпляры (аналогично тому, как у вас есть using (SqlCommand oCommand = new SqlCommand("dbo.GetUsers", oConnection))
внутри RegisterForChanges()
,
Я изменил код, чтобы объявить ссылки на экземпляры SqlCommand
а также SqlConnection
объекты и экземпляры только новые SqlDependency
случаи в RegisterForChanges()
метод.
void RegisterForChanges()
{
_sqlCommand.Notification = null;
_sqlConnection.Open();
SqlDependency dependency = new SqlDependency(_sqlCommand);
dependency.OnChange += dependency_OnChange;
_sqlCommand.ExecuteNonQuery(); // or ExecuteReader and parse the results, etc
_sqlConnection.Close();
}