У мене більше однієї програми, яка отримує доступ до однієї і тієї ж БД, і мені потрібно отримувати сповіщення, якщо одна з цих програм щось змінює (оновлює, вставляє) у певній таблиці.
База даних та програми знаходяться не на одному сервері.
У мене більше однієї програми, яка отримує доступ до однієї і тієї ж БД, і мені потрібно отримувати сповіщення, якщо одна з цих програм щось змінює (оновлює, вставляє) у певній таблиці.
База даних та програми знаходяться не на одному сервері.
Відповіді:
Ви можете використовувати SqlDependency Class
. Призначений для використання в основному для сторінок ASP.NET (низька кількість сповіщень клієнта).
ALTER DATABASE UrDb SET ENABLE_BROKER
Реалізуйте OnChange
подію, щоб отримати сповіщення:
void OnChange(object sender, SqlNotificationEventArgs e)
І в коді:
SqlCommand cmd = ...
cmd.Notification = null;
SqlDependency dependency = new SqlDependency(cmd);
dependency.OnChange += OnChange;
Він використовує Service Broker
(комунікаційну платформу на основі повідомлень) для отримання повідомлень від механізму баз даних.
SqlSependency
так чи є кращий спосіб , ніж це , щоб отримувати повідомлення при зміні даних SQL Azure або коли нові дані вставляються?
В інтересах повноти є ще кілька рішень, які (на мій погляд) є більш ортодоксальними, ніж рішення, що покладаються на класи SqlDependency (і SqlTableDependency). Спочатку SqlDependency був розроблений, щоб полегшити оновлення кешів розподіленого веб-сервера, і тому був побудований до інших наборів вимог, ніж якби він був розроблений як виробник подій.
Є загалом чотири варіанти, деякі з яких тут вже не розглядались:
Відстеження змін
Відстеження змін - це полегшений механізм сповіщення на сервері SQL. В основному, номер версії для всієї бази даних збільшується при кожній зміні будь-яких даних. Потім номер версії записується до таблиць відстеження змін із бітовою маскою, що включає імена стовпців, які були змінені. Зверніть увагу, що фактичні зміни не зберігаються. Повідомлення містить лише інформацію про те, що певна сутність даних змінилася. Окрім того, оскільки версія таблиці змін є сукупною, сповіщення про зміни в окремих елементах не зберігаються і замінюються новими сповіщеннями. Це означає, що якщо сутність зміниться двічі, відстеження змін буде знати лише про останню зміну.
Для того, щоб зафіксувати ці зміни в c #, потрібно використовувати опитування. Таблиці відстеження змін можна опитувати, а кожну зміну перевіряти, чи цікавить. Якщо це цікавить, необхідно перейти безпосередньо до даних, щоб отримати поточний стан.
Змінити збір даних
Джерело: https://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx
Збір даних про зміни (CDC) є потужнішим, але найдорожчим, ніж відстеження змін. Збір даних про зміни буде відстежувати та повідомляти про зміни на основі моніторингу журналу бази даних. Через це CDC має доступ до фактичних даних, які були змінені, і веде облік усіх окремих змін.
Подібно до відстеження змін, щоб зафіксувати ці зміни в c #, потрібно використовувати опитування. Однак у випадку CDC, опитувана інформація міститиме деталі зміни, тому не потрібно строго повертатися до самих даних.
Тригери до черг
Джерело: https://code.msdn.microsoft.com/Service-Broker-Message-e81c4316
Цей прийом залежить від тригерів у таблицях, з яких вимагаються сповіщення. Кожна зміна запускатиме тригер, і тригер запише цю інформацію до черги брокера послуг. Потім чергу можна підключити через C # за допомогою процесора обміну повідомленнями брокера послуг (зразок за посиланням вище).
На відміну від відстеження змін або CDC, тригери до черг не покладаються на опитування і тим самим забезпечують події в реальному часі.
CLR
Це техніка, яку я бачив, використовувану, але я б не рекомендував її. Будь-яке рішення, яке покладається на CLR для зовнішнього спілкування, - це в кращому випадку хакерство. CLR був розроблений, щоб полегшити написання складного коду обробки даних, використовуючи C #. Він не був розроблений для підключення зовнішніх залежностей, таких як бібліотеки обміну повідомленнями. Крім того, операції, пов'язані з CLR, можуть непередбачувано розбиватися в кластерних середовищах.
Тим не менш, налаштування досить просто, оскільки все, що вам потрібно зробити, це зареєструвати збірку обміну повідомленнями в CLR, а потім ви можете зателефонувати за допомогою тригерів або завдань SQL.
Підсумовуючи ...
Мене завжди викликало подив для того, що Microsoft наполегливо відмовлялася вирішувати цю проблему. Перехід від бази даних до коду повинен бути вбудованою функцією продукту бази даних. Враховуючи, що Oracle Advanced Queuing у поєднанні з подією ODP.net MessageAvailable забезпечили надійну базу даних, що надходить до C # більше 10 років тому , це страшно від MS.
Результатом цього є те, що жодне з перелічених у цьому питанні рішень не є дуже приємним. Всі вони мають технічні недоліки та мають значну вартість налаштування. Корпорація Майкрософт, якщо ви слухаєте, будь ласка, розберіть цей жалюгідний стан справ.
Як правило, ви використовуєте брокер послуг
Тобто тригер -> черга -> програма (и)
Редагуйте, побачивши інші відповіді:
FYI: "Сповіщення про запит" побудовано на брокері послуг
Edit2:
Більше посилань
SqlSependency
так чи є кращий спосіб , ніж це , щоб отримувати повідомлення при зміні даних SQL Azure або коли нові дані вставляються?
Використовуйте SqlTableDependency. Це події підвищення компонентів змінного струму, коли запис змінюється. Інші деталі ви можете знайти за адресою: https://github.com/christiandelbianco/monitor-table-change-with-sqltabledependency
Це подібне до .NET SqlDependency, за винятком того, що SqlTableDependency викликає події, що містять змінені / видалені або оновлені значення таблиці бази даних:
string conString = "data source=.;initial catalog=myDB;integrated security=True";
using(var tableDependency = new SqlTableDependency<Customers>(conString))
{
tableDependency.OnChanged += TableDependency_Changed;
tableDependency.Start();
Console.WriteLine("Waiting for receiving notifications...");
Console.WriteLine("Press a key to stop");
Console.ReadKey();
}
...
...
void TableDependency_Changed(object sender, RecordChangedEventArgs<Customers> e)
{
if (e.ChangeType != ChangeType.None)
{
var changedEntity = e.Entity;
Console.WriteLine("DML operation: " + e.ChangeType);
Console.WriteLine("ID: " + changedEntity.Id);
Console.WriteLine("Name: " + changedEntity.Name);
Console.WriteLine("Surname: " + changedEntity.Surname);
}
}
Будьте обережні, використовуючи клас SqlDependency - він має проблеми з витоками пам'яті.
Просто використовуйте крос-платформне, сумісне з .NET 3.5, .NET Core рішення з відкритим кодом - SqlDependencyEx . Ви можете отримувати сповіщення, а також дані, які були змінені (ви можете отримати доступ до них через властивості в об’єкті події сповіщення). Ви також можете підключити операції DELETE \ UPDATE \ INSERT окремо або разом.
Ось приклад того, як просто використовувати SqlDependencyEx :
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);
Будь ласка, перейдіть за посиланнями для отримання детальної інформації. Цей компонент був перевірений у багатьох прикладних програмах на корпоративному рівні та продемонстрував свою надійність. Сподіваюся, це допомагає.
SqlDependency не переглядає базу даних, вона переглядає вказаний вами SqlCommand, тому, якщо ви намагаєтеся дозволити вкласти значення в базу даних у 1 проект і захопити цю подію в іншому проекті, це не буде працювати, оскільки подія була з SqlCommand з Проект 1º не є базою даних, тому що коли ви створюєте SqlDependency, ви пов'язуєте її з SqlCommand і лише тоді, коли використовується команда з цього проекту, він створює подію Change.
З SQL Server 2005 у вас є можливість використовувати сповіщення про запити , які можна використовувати ADO.NET, див. Http://msdn.microsoft.com/en-us/library/t9x04ed2.aspx
виглядає як погана архітектура на всьому шляху. також ви не вказали тип програми, про яку вам потрібно повідомити (веб-програма / консольна програма / winform / сервіс тощо тощо)
проте, щоб відповісти на ваше запитання, існує кілька способів вирішити це. Ви можете використовувати:
1) позначки часу, якщо вас просто цікавило забезпечення наступного набору оновлень з другої програми, не суперечить оновленням з першої програми
2) об'єкт залежності sql - див. Http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldependency.aspx для отримання додаткової інформації
3) спеціальна послуга push-сповіщень, на яку можуть підписатися та отримувати повідомлення про зміни декілька клієнтів (веб / winform / service)
коротше кажучи, вам потрібно використовувати найпростіше, найпростіше та найдешевше (з точки зору зусиль) рішення, виходячи зі того, наскільки складними є ваші вимоги до сповіщень і з якою метою їх потрібно використовувати. не намагайтеся побудувати надто складну систему сповіщень, якщо простою одночасністю даних є ваша єдина вимога (у такому випадку вибирайте просте рішення на основі мітки часу)
Іншим, дуже простим способом моніторингу таблиць є управління версіями таблиць. Доведено, що система працює в таких конструкціях, як синхронізація DNS. Щоб це працювало, ви створюєте таблицю, що містить імена та версії таблиць як decimal
абоbigint.
У кожній таблиці, яку потрібно контролювати, створіть тригер для вставки, оновлення та видалення, який збільшить відповідну версію таблиці в таблиці версій при виконанні. Якщо ви очікуєте, що будь-яка з відстежуваних таблиць буде часто змінюватися, вам потрібно забезпечити повторне використання версії. Нарешті, у вашій програмі, кожного разу, коли ви надсилаєте запит до відстежуваної таблиці, ви також запитуєте її версію та зберігаєте. Коли ви переходите до зміни відстежуваної таблиці з вашого додатка, ви спочатку ставите запит до його поточної версії та обробляєте зміни, лише якщо версія незмінна. Ви можете зберегти proc на сервері sql, який вам підходить. Це надзвичайно просте, але перевірене тверде рішення.
Це не зовсім сповіщення, але в заголовку ви кажете монітор, і це може відповідати цьому сценарію.
Використання стовпця часової позначки SQL Server дозволяє легко бачити будь-які зміни (які все ще зберігаються) між запитами.
На мій погляд, тип стовпця мітки часу SQL Server погано названий, оскільки він взагалі не пов’язаний з часом, це значення в масштабі бази даних, яке автоматично зростає при будь-якій вставці чи оновленні. Ви можете вибрати Макс. (Позначку часу) у таблиці, за якою ви шукаєте, або повернути позначку часу з рядка, який ви щойно вставили, а потім просто виберіть, де позначка часу> зберігаєтьсяМірка часу, це дасть вам усі результати, які були оновлені або вставлені між цими часами.
Оскільки це також значення для бази даних, ви можете використовувати свою збережену мітку часу, щоб перевірити, чи в будь-якій таблиці були записані дані з моменту останньої перевірки / оновлення збереженої мітки часу.