سلام جناب فاتحی
عرض شود به حضور شما که ، برای فعال کردن ServiceBroker باید ابتدا دیتا بیس رو در حالت Single User قرار بدید تا کوئری بدون مشکل اجرا بشه (اسم دیتابیس فرضی SampleDB هست و جدول فرضی myTable)
ALTER DATABASE SampleDB SET SINGLE_USER;
ALTER DATABASE SampleDB SET ENABLE_BROKER;
ALTER DATABASE SampleDB SET MULTI_USER;
ساخت Service و Queue هم با کوئری های زیر بدون مشکل انجام میشه ، البته لازم به ذکره که بدون ساختن این موارد هم ظاهرا کلاس Sql Dependency خودش این موارد رو مدیریت میکنه
CREATE QUEUE myTableMessages;
CREATE SERVICE myTableNotifications
ON QUEUE myTableMessages
([http://schemas.microsoft.com/SQL/Not...otification]);
تا اینجا تنظیمات سمت SqlServer تمومه ، حالا میریم سراغ کد نویسی کلاینت
این کلاس رو برای ساخت آبجکت SqlDependency و تولید رویدادهای مورد نیاز نوشتم.
using System;
using System.Data;
using System.Data.SqlClient;
namespace NotifyService
{
public class SqlNotifier : IDisposable
{
public SqlCommand SqlCmd { get; set; }
public SqlConnection SqlCon { get; set; }
public void StartMonitoring()
{
SqlDependency.Start(this.SqlCon.ConnectionString);
RegisterDependency();
}
private event EventHandler<SqlNotificationEventArgs> _NewNotification;
public event EventHandler<SqlNotificationEventArgs> NewNotification
{
add { this._NewNotification += value; }
remove { this._NewNotification -= value; }
}
public virtual void OnNewNotification(SqlNotificationEventArgs notification)
{
if (this._NewNotification != null)
this._NewNotification(this, notification);
}
public void RegisterDependency()
{
this.SqlCmd = new SqlCommand(SqlCmd.CommandText,this.SqlCon);
this.SqlCmd.Notification = null;
SqlDependency dependency = new SqlDependency(this.SqlCmd);
dependency.OnChange += this.Dependency_OnChange;
if (this.SqlCon.State == ConnectionState.Closed)
this.SqlCon.Open();
this.SqlCmd.ExecuteReader();
this.SqlCon.Close();
}
private void Dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency dependency = (SqlDependency)sender;
dependency.OnChange -= new OnChangeEventHandler(Dependency_OnChange);
this.OnNewNotification(e);
RegisterDependency();
}
public void Dispose()
{
SqlDependency.Stop(this.SqlCon.ConnectionString);
}
}
}
و اما نحوه استفاده از این کلاس
طبیعتا باید در هر فرمی که میخواید این قابلیت رو داشته باشید باید فضای نام NotifyService رو که مربوط به کلاس بالا هست اضافه کنید.
using NotifyService;
از کلاس بالا ، با دسترسی در سطح فرم یک نمونه بسازید.
private SqlNotifier NS = new SqlNotifier();
در متد سازنده فرمتون این کدها رو بنویسید
- خط اول که کانکشن استرینگ رو به کلاس پاس میدید.
- خط دوم هم مشخصه (شما تغییرات مربوط به جدولی که در این کوئری مشخص شده رو دریافت خواهید کرد - نکته مهم اینه که حتما و حتما اسم جدول باید به صورت دو بخشی نوشته بشه یعنی dbo.myTable )
- خط بعد سرویس رو اجرا میکنه
- نهایتا در خط چهارم event handler به نام NewNotification رو در کلاس فوق الذکر به متدی به نام DependencyEventHandler که در فرم می نویسیم و و به اون اشاره خواهم کرد رو به هم متصل میکنه.
NS.SqlCon = new SqlConnection(@"Data Source=127.0.0.1;Initial Catalog=SampleDB;Persist Security Info=True;User ID=sa;Password=***");
NS.SqlCmd = new SqlCommand("SELECT id, name FROM dbo.mytable");
NS.StartMonitoring();
NS.NewNotification += new EventHandler<SqlNotificationEventArgs>(DependencyE ventHandler);
در واقع در متد DependencyEventHandler ، هر اتفاقی که مد نظرتون هست که در هنگام تغییرات در دیتابیس باید ایجاد بشه رو مینویسید (اینجا من در این متد ، متد LoadData رو فراخوانی کردم که با هربار تغییرات جدول مورد نظر ، محتویات دیتاگرید رو آپدیت میکنه.)
شکل متد DependencyEventHandler
private void DependencyEventHandler(object s, SqlNotificationEventArgs e)
{
LoadData();
}
متد LoadData که با هربار تغییرات جدول مورد نظر محتویات دیتاگرید رو آپدیت میکنه (کلاس DataAccess ، کلاسی هست که خودم نوشتم برای ارتباط با دیتابیس ، شما میتونید از همون آبجکت های ADO.Net مستقیم استفاده کنید.)
private delegate void _LoadData();
private void LoadData()
{
if (this.InvokeRequired)
{
this.Invoke(new _LoadData(LoadData));
return;
}
var da = new DataAccess();
var dt = new DataTable();
da.conOpen();
dataGridView1.DataSource = da.execReader("SELECT * FROM myTable");
da.conClose();
}
و در آخر باید در رویداد FormClosed ، نمونه ای رو که از کلاس بالا ساختید Dispose کنید.
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
NS.Dispose();
}
* کانکشن استرینگ و کوئری ها رو بنا بر سیستم خودتون اصلاح بفرمائید.
فکر نمیکنم نکته مبهمی باقی مونده باشه دوست عزیزم.
موفق باشید.