نوتیفیکیشن های Real Time با استفاده از SignalR و SQLDependency
Loading...
SignalR و SQLDependency

با مقاله بررسی SignalR و SQLDependency با شما هستم.در یکی از پروژه هایی که ما روی آن کار می کردیم، لازم بود که نوتیفیکیشن ها به صورت Real Time (بلادرنگ) به کاربر نمایش داده شوند. به نظر می رسید که SignalR مانند یک انتخاب فوری است چرا که فریمورکی را برای کد سمت سرور جهت push کردن بلادرنگ داده ها به کلاینت هایی که متصل هستند، فراهم می کند. اما نوتیفیکیشن ها می توانند به طور مستقیم از طریق سیستم های خارجی به دیتابیس ارسال شوند. در این مورد نیاز به دریافت رکوردهای جدید واردشده و ارسال آن به کلاینت متصل وجود دارد. این مقاله درباره نحوه اتصال همه این قسمت ها به یکدیگر و ساخت یک راه حل نوتیفیکیشن بلادرنگ بحث می کند.

پیش زمینه

معرفی اجمالی درباره SignalR

SignalR یک کتابخانه .NET است که فرایند اضافه کردن قابلیت بلادرنگ به اپلیکیشن های وب را ساده می کند. به جای اینکه سرور برای درخواست داده ها از سرور منتظر کلاینت باشد، برای ما فریمورکی را برای کد سمت سرور به منظور فراخوانی متد سمت کلاینت فراهم می کند.

برای ما یک API برای ایجاد سرور به کلاینت (RPC) ایجاد می کند که متدهای جاوا اسکریپت را از کد .NET سمت سرور فراخوانی می نماید. همچنین برای متدهایی برای اتصال، قطع اتصال، رویدادهای قطع اتصال، ارسال به همه کلاینت های متصل، ارسال به یک کلاینت مشخص و… را فراهم می کند.

برای اطلاعات بیشتر درباره SignalR می توانید به آدرس https://www.mspsoft.com/1396/01/05/started-signalr-in-asp-net مراجعه نمایید.

SQL Dependency

SQL Dependency یک کلاس تهیه شده توسط فریمورک .NET است که روی زیرساخت service broker تعبیه شده است که به اپلیکیشن این امکان را می دهد که زمانی که داده ها در دیتابیس (Microsoft SQL Server) تغییر کرد، مطلع شود. Microsoft SQL Server به اپلیکیشن های فریمورک .NET اجازه می دهد که به SQL Server دستور SQL ارسال کرده و اگر اجرای دستور نتیجه متفاوتی را تولید کرد، درخواست نوتیفیکشن نمایند.

SQL Server به اپلیکیشن های فریمورک .NET اجازه تنظیم دستورات SELECT و EXECUTE را می دهد.

شروع کار

SQL Server

کار را با ایجاد یک جدول در دیتابیس شروع می کنیم.

SignalR و SQLDependency

ستون User ID شامل شناسه کاربری برای کاربری است که نوتیفیکیشن باید ارسال شود. اسکریپت زیر را در دیتابیسی که جدول را در آن ایجاد کردیم، اجرا می کنیم، پس از آن SQL Server ارسال نوتیفیکیشن به اپلیکیشن .NET ای را که روی تغییرات جدول ALTER DATABASE [dbname] SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE مشترک شده است، آغاز می کند. این تنها چیزی است که از سمت SQL Server لازم است.

ASP.NET MVC Web Application

حالا اجازه دهید که یک اپلیکیشن وب ایجاد نماییم. یک اپلیکیشن ابتدایی ASP.NET MVC 4 ایجاد می کنیم.

SignalR و SQLDependency

با راست کلیک روی فولدر Controllers و انتخاب add new controller یک “HomeController” ایجاد می کنیم.

SignalR و SQLDependency

روی فولدر Views راست کلیک کرده و یک فولدر جدید به نام “Home” ایجاد می کنیم.

SignalR و SQLDependency

روی فولدر “Home” جدیدی که ایجاد کردیم، راست کلیک کرده و گزینه Add و سپس View را انتخاب کرده و سپس نام آن را “index” گذاشته و روی Add کلیک می کنیم. به Package Manager console رفته و دستور زیر را اجرا می کنیم که کتابخانه های ضروری و جاوا اسکریپت موردنیاز برای SignalR را می آورد..

PM> Install-Package Microsoft.AspNet.SignalR

به فایل Layout.cshtml رفته و تمامی “@scripts.render” را حذف کرده و با کدهای زیر در بخش Head جایگزین می کنیم.

<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>

 

حالا فایل index.cshtml درون فولدر Home را که ایجاده کرده ایم، باز می کنیم و سپس کد زیر را که پروکسی ایجاد شده توسط سرور برای فراخوانی کلاینت خواهد بود، اضافه می کنیم.

<!--Reference the autogenerated SignalR hub script. -->

<script src="~/signalr/hubs"></script>

HTML موردنیاز برای نمایش لیست نوتیفیکیشن، تعداد و فرمی برای ارسال نوتیفیکیشن ها را ایجاد می نماییم. کد زیر را در index.cshtml اضافه شده ،در فولدر Home درون View اضافه می کنیم.

<div style="width: 70%; padding: 20px">
    <div class="panel panel-primary">
        <div class="panel-heading">

    <! – To show notification count-->
            <div style="float: left" class="panel-title">Notifications</div>
            <div style="float: right" class="badge" id="cntNotifications"></div>
            <div style="clear: both"></div>


        </div>
        <div class="panel-body">
      <! – To show All the notifications-->
            <table class="table table-striped table-hover ">
                <thead>
                    <tr>
                        <th>#</th>
                        <th>Text</th>
                        <th>Created Date</th>
                    </tr>
                </thead>

                <tbody id="notificationTab">

                </tbody>
            </table>
        </div>
    </div>

    <! – Add panel notification to send notification, Make sure that user enters the user id of the domain they are logged into --> 
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">Create Notifications</h3>
        </div>
        <div class="panel-body">
            <div class="form-group">
                <label class="control-label" for="focusedInput">Notification Text</label>
                <input class="form-control" id="text" type="text" value="">
            </div>
            <div class="form-group">
                <label class="control-label" for="focusedInput">Send To</label>
                <input class="form-control" id="userName" type="text" value="">
            </div>
            <a id="btnSend" style="cursor: pointer" class="btn btn-primary">Send Notification</a>
        </div>
    </div>
</div

 

حالا بیایید به کد سرور برگردیم و کدهایی برای واکشی نوتیفیکیشن ها از دیتابیس و اضافه کردن نوتیفیکیشن ها به دیتابیس ایجاد کنیم. روی فایل پروژه راست کلیک کرده و یک فولدر جدید “Repository” و یک کلاس “NotificationRepository.cs” اضافه می کنیم. لازم است که کد زیر را در فایل قرار دهیم. یک new item اضافه کرده و Data> ADO.NET Entity Data Model را انتخاب کرده و نامی برای آن انتخاب می کنیم.

SignalR و SQLDependency

در بخش بعدی “Generate from the database” را انتخاب می کنیم.

SignalR و SQLDependency

نام سرور، نام دیتابیس را به آن داده و Wizard را کامل می کنیم. “NotificationEntities” را با نامی که به entity داده ایم عوض می کنیم.

public void AddNotification(string Text, string UserName)
{
    using (NotificationEntities ent = new NotificationEntities())
    {
        NotificationList obj = new NotificationList();
        obj.Text = Text;
        obj.UserID = UserName;
        obj.CreatedDate = DateTime.Now.ToUniversalTime();
        ent.NotificationLists.Add(obj);
        ent.SaveChanges();
    }
}

public List GetNotifications(string userName)
{

    using (NotificationEntities ent = new NotificationEntities())
    {
        return ent.NotificationLists.Where(e => e.UserID == userName).ToList();
    }
}

public List GetLatestNotifications(DateTime dt)
{

    using (NotificationEntities ent = new NotificationEntities())
    {
        if (dt == DateTime.MinValue)
        {
            return ent.NotificationLists.ToList();
        }
        else
        {
            DateTime dtUTC = dt.ToUniversalTime();
            return ent.NotificationLists.Where(e => e.CreatedDate > dtUTC).ToList();
        }
    }
}




کد بالا تا حدود زیادی قابل فهم است. خب ما سه متد ایجاد کردیم. AddNotification برای اضافه کردن نوتیفیکیشن به دیتابیس، GetNotifications(username) برای دریافت نوتیفیکیشن ها برای نام کاربری مشخص شده.

درنهایت، متد GetLatestNotification(date time) که لیستی از نوتیفیکیشن ها را از آخرین اجرا انتخاب می کند تا رکوردهای اضافه شده بعد از هر اجرا را دریافت نماید، که در رویداد SQL dependency فراخوانی خواهد شد.

حالا، یک SignalR Hub می سازیم که کد سمت سرور می باشد که متد جاوا اسکریپت سمت کلاینت را برای نمایش نوتیفیکیشن فراخوانی می نماید.

روی فایل پروژه راست کلیک کرده و یک فولدر جدید با نام “Hubs” اضافه می کنیم. یک کلاس به نام “Notification.cs” ایجاد می کنیم. این کلاس حتما باید از کلاس Hub ارث بری نماید.

public class NotificationHub: Hub
{
   // Code 

}


یک متد “SendNotification” ایجاد می کنیم که کلاینت ها برای ایجاد نوتیفیکیشن در دیتابیس آن را فراخوانی می کنند. کلاینت ها باید دو متغیر را ارسال نمایند، username برای اینکه نوتیفیکیشن باید به چه کسی ارسال شود.

public class NotificationHub: Hub
{
   
        public void SendNotification(string message, string user)
        {
	//Create an instance of the Repository class
            NotificationRepository objRepository = new NotificationRepository();

	//Invoke the Add Notification method that we created in the repository to add the notification to the database 
            objRepository.AddNotification(message, user);          
        }

}


حالا متد onConnected را برای دریافت نوتیفیکیشن ها برای ورود کاربر و ارسال پاسخ override می نماییم.

public class NotificationHub: Hub
{
   
        public void SendNotification(string message, string user)
        {
	//Create an instance of the Repository class
            NotificationRepository objRepository = new NotificationRepository();

	//Invoke the Add Notification method that we created in the repository to add the notification to the database 
            objRepository.AddNotification(message, user);          
        }

        public override System.Threading.Tasks.Task OnConnected()
        {
	//Create an instance of the Repository class
            NotificationRepository objRepository = new NotificationRepository();
     
	//refreshNotification is the client side method which will be writing in the future section. GetLogin() is a static extensions extract just the login name scrapping the domain name 
            Clients.User(Context.User.Identity.Name).refreshNotification(objRepository.GetNotifications(Context.User.Identity.GetLogin()));

            return base.OnConnected();

        }


}

public static class Extensions
    {
        public static string GetDomain(this IIdentity identity)
        {
            string s = identity.Name;
            int stop = s.IndexOf("\\");
            return (stop > -1) ? s.Substring(0, stop) : string.Empty;
        }

        public static string GetLogin(this IIdentity identity)
        {
            string s = identity.Name;
            int stop = s.IndexOf("\\");
            return (stop > -1) ? s.Substring(stop + 1, s.Length - stop - 1) : string.Empty;
        }
    }

 

حالا ما باید جدول را با تغییر SQL Dependency مرتبط کرده و SignalR hub را مقداردهی اولیه نماییم. فایل Global.asax.cs را باز می کنیم. نکته غم انگیز درباره SQL Dependency این است که فقط رویدادی را اعلام می کند و می گوید که تغییری در جدول رخ داد اما درباره اینکه چه رکوردی اضافه یا تغییر داده شد اطلاعاتی نمی دهد. ما باید دوباره به دیتابیس کوئری زده و تغییر ایجاد شده را دریافت کنیم.

یک متد void با نام “RegisterNotification” در فایل global.asax ایجاد می کنیم و آن را در متد application_start فراخوانی می نماییم.

private void RegisterNotification()
        {
	//Get the connection string from the Web.Config file. Make sure that the key exists and it is the connection string for the Notification Database and the NotificationList Table that we created

            string connectionString = ConfigurationManager.ConnectionStrings["NotificationConnection"].ConnectionString;

	//We have selected the entire table as the command, so SQL Server executes this script and sees if there is a change in the result, raise the event
            string commandText = @"
                                    Select
                                        dbo.NotificationList.ID,
                                        dbo.NotificationList.Text,
                                        dbo.NotificationList.UserID,
                                        dbo.NotificationList.CreatedDate                                      
                                    From
                                        dbo.NotificationList                                     
                                    ";

	//Start the SQL Dependency
            SqlDependency.Start(connectionString);
            using (SqlConnection connection = new SqlConnection(connectionString))
            {

                using (SqlCommand command = new SqlCommand(commandText, connection))
                {
                    connection.Open();
                    var sqlDependency = new SqlDependency(command);


                    sqlDependency.OnChange += new OnChangeEventHandler(sqlDependency_OnChange);

                    // NOTE: You have to execute the command, or the notification will never fire.
                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                    }
                }
            }
        }



حالا رویداد OnChange را مدیریت می کنیم. بررسی می کنیم که اگر نوع رویداد “Insert” باشد، آخرین رکورد را دریافت کرده و آن را به کلاینت متصل ارسال می نماییم.

DateTime LastRun;
     private void sqlDependency_OnChange(object sender, SqlNotificationEventArgs e)
     {

         if (e.Info == SqlNotificationInfo.Insert)
         {
 //This is how signalrHub can be accessed outside the SignalR Hub Notification.cs file
             var context = GlobalHost.ConnectionManager.GetHubContext();


             NotificationRepository objRepos = new NotificationRepository();

             List objList = objRepos.GetLatestNotifications(LastRun);

             LastRun = DateTime.Now.ToUniversalTime();


             foreach (var item in objList)
             {
      //replace domain name with your own domain name
                 context.Clients.User("" + item.UserID).addLatestNotification(item);
             }

         }
       //Call the RegisterNotification method again
         RegisterNotification();
     }



برای معرفی کردن کلاس SignalR Hub به عنوان یک شی در این پروژه ما باید یک کلاس اضافه نماییم. این کلاس می تواند در همان فایل global.asax.cs اضافه شود.

public class Startup
 {
     public void Configuration(IAppBuilder app)
     {
         app.MapSignalR();
     }
 }


در فایل web.config یک کلید برای “owin:AppStartup” اضافه کرده و یک مقدار نام کامل قابل قبول از کلاس Startup را که در بخش قبلی ساختیم، اضافه می کنیم.

<appSettings>
	…
   
    <add key="owin:AppStartup" value="Notifications.Signalr.Startup" />
  </appSettings>

 

درنهایت، برای سمت کلاینت، ایجاد آن دو متدی که سرور برای نمایش لیستی از نوتیفیکیشن ها و ارسال آخرین مورد اضافه شده آن ها فراخوانی می کند.

<script>
    $(function () {

        // Reference the auto-generated proxy for the hub.  

        var notification = $.connection.notificationHub;

 // Client side method for receiving the list of notifications on the connected event from the server
        notification.client.refreshNotification = function (data) {
            $("#notificationTab").empty();
            $("#cntNotifications").text(data.length);
            for (var i = 0; i < data.length; i++) {
                $("#notificationTab").append("<tr> <td> " + data[i].ID + "</td> <td>" + data[i].Text + "</td> <td>" + data[i].CreatedDate + "</td></tr>");
            }
        }
     
//Client side method which will be invoked from the Global.asax.cs file. 
        notification.client.addLatestNotification = function (data) {
            $("#cntNotifications").text($("#cntNotifications").text() + 1);
            $("#notificationTab").append("<tr> <td> " + data.ID + "</td> <td>" + data.Text + "</td> <td>" + data.CreatedDate + "</td></tr>");
        }

        // Start the connection.
        $.connection.hub.start().done(function () {

	//When the send button is clicked get the text and user name and send it to server. 
            $("#btnSend").click(function () {
                notification.server.sendNotification($("#text").val(), $("#userName").val());
            });

        });
    });
</script>

 

در اینجا کدنویسی ما به پایان رسید.

تصاویر زیر چیزهایی را که در راه حل سطح بالا اتفاق می افتد، نشان می دهد.

SignalR و SQLDependency

مرحله اول – مقداردهی اولیه (کلاینت ها متصل می شوند)

SignalR و SQLDependency

کلاینت ۱ نوتیفیکیشنی به کلاینت متصل ۳ ارسال می کند – سناریوی ۱

SignalR و SQLDependency

سرویس خارجی یک نوتیفیکیشن به کلاینت ۲ ارسال می کند – سناریوی ۲



avatar فاطمه زکایی

فاطمه زکایی هستم. فارغ التحصیل کارشناسی مهندسی نرم افزار، مدت سه سال هست که در زمینه توسعه اپلیکیشن های تحت وب و اندروید و همچنین تولید محتوای تخصصی برنامه نویسی تحت وب و اندروید در مجموعه mspsoft در خدمت شما هستم.

آخرین مطالب و تخفیفات در کانال تلگرام :) کانال تلگرام ام اس پی سافت
مطالب مرتبط
ديدگاه خود را ارسال کنيد


۰ دیدگاه رو شما می توانید ببینید
  1. سلام اصل پروژه رو نمیذارید برای دانلود ؟
    ممنون

محبوب ترين ويدئو هاي انلاين
دوره برنامه نویسی فروشگاه اینترنتی
  • تعداد اعضا 80k
  • قيمت دوره۱۰۰,۰۰۰ تومان
  • امتيازدهي
    1 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 5( 5٫00 از 1 رای )
    Loading...
دوره آموزشی سیستم ثبت سفارش آنلاین
  • تعداد اعضا 80k
  • قيمت دوره۵۰,۰۰۰ تومان
  • امتيازدهي
    1 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 5( 5٫00 از 1 رای )
    Loading...
دوره طراحی سیستم مدیریت مشتریان
  • تعداد اعضا 80k
  • قيمت دوره۵۰,۰۰۰ تومان
  • امتيازدهي
    1 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 51 vote, average: 5٫00 out of 5( 5٫00 از 1 رای )
    Loading...