ably ably برای هدایت شدن به سایت جدید اینجا کلیک کنید

آموزش برنامه نویسی

آموزش برنامه نویسی وب، اندروید، ویندوز , اسکیوال و...
Tell: 0912 097 5516
| Email: Hello@EduOnline.ir

دوره آموزشی SignalR به زبان فارسی

بسم الله الرحمن الرحیم

دوره  آموزشی SignalR به زبان فارسی

ایجاد پروژه با SignalR و SQLDepedency در  ASP.NET MVC

بخش اول
بخش دوم

بخش سوم

بخش چهارم

بخش پنجم- شروع ایجاد پروژه SignalR

بخش ششم - مروری بر مفاهیم SignalR

بخش هفتم- ایجاد پروژه Chat با SignalR

بخش هشتم - ایجاد پروژه Chat با SignalR در ASP.NET MVC

بخش نهم- ساخت یک Timer سمت سرور با SignalR

بخش دهم - آموزش ساخت یک پروژه SignalR با SQLDepedency در ASP.NET MVC

در این آموزش می خواهیم هر تغییری که در پایگاه داده Sql Server ( توسط change notification مشخص می شوند) ایجاد شده است را توسط SignalR در یک پروژه ASP.NET نمایش دهیم.  این کار توسط یک query notification dependency مابین یک برنامه و یک نسخه از SQL Server انجام می شود، شیی که این وظیفه را انجام میدهد SqlDependency نام دارد.در نظر داشته باشید که پایگاه داده شما توسط windows service در background بروز رسانی  وsynchronized  (همزمان) با برنامه شما می شود و برنامه شما اطلاعات را به صورت real time نمایش می دهد.

SqlDependency


DB Settings
ما نیاز داریم Service Broker را بر روی پایگاه داده خود فعال کنیم، برای اینکار دستور زیر را اجرا کنید:
چک کردن سرویس:

SELECT name, is_broker_enabled FROM sys.databases


فعال کردن سرویس
ما باید در مجوزهای لازم را به IIS service account بدهیم تا query notification تایید شود:

ALTER DATABASE TechBrijDB SET ENABLE_BROKER
GO


در این مثال ما از جدول JobInfo استفاده می کنیم:

GRANT SUBSCRIBE QUERY NOTIFICATIONS TO “Domain\ASPNET”

آموزش SignalR

Setup SqlDependency

من از ASP.NET Web API استفاده می کنم اما تنظیمات یکه انجام میدهیم مشابه تنظیمات پروژه MVC ASP.NET است.
در ابتدا connection string را در web.config تنظیم کنید:

<connectionStrings>
    <add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLExpress;Initial Catalog=TechBrijDB;Integrated Security=SSPI;" />
</connectionStrings>

در Global.asax، listener را فعال کنید:

protected void Application_Start()
{
        //...
        SqlDependency.Start(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
}


در متد زیر باید listener را متوقف کنید

protected void Application_End()
      {
          SqlDependency.Stop(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
      }


کلاس های JobInfo  و JobInfoRepository را اضافه کنید:

public class JobInfo {
  public int JobID { get; set; }
  public  string Name { get; set; }
  public  DateTime LastExecutionDate { get; set; }
  public  string Status { get; set; }
}
 
 public class JobInfoRepository {
 
    public IEnumerable<JobInfo> GetData()
    {
       
        using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
        {
            connection.Open();
            using (SqlCommand command = new SqlCommand(@"SELECT [JobID],[Name],[LastExecutionDate],[Status]
               FROM [dbo].[JobInfo]", connection))
            {
                // Make sure the command object does not already have
                // a notification object associated with it.
                command.Notification = null;
 
                SqlDependency dependency = new SqlDependency(command);
                dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
 
                if (connection.State == ConnectionState.Closed)
                    connection.Open();
 
                using (var reader = command.ExecuteReader())
                    return reader.Cast<IDataRecord>()
                        .Select(x => new JobInfo(){
                            JobID = x.GetInt32(0),
                            Name = x.GetString(1),
                            LastExecutionDate = x.GetDateTime(2),
                            Status  = x.GetString(3) }).ToList();                           
                 
 
 
            }
        }       
    }
    private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
    {           
        JobHub.Show();
    }
 
 
}


در کد بالا، در event مربوط به SqlDependency OnChange، ما متد JobHub را فراخوانی می کنیم تا اطلاعات درون grid بروز رسانی شود. در بخش بعد Hub خود را ایجاد خواهیم کرد.

SignalR

برای نصب کردن Microsoft ASP.NET SignalR باید از طریق Package Manager Console دستور زیر را اجرا کنید:

Install-Package Microsoft.AspNet.SignalR -Pre

حال در متد global.asax > Application_Start  کد زیر قبل از متد RouteConfig.RegisterRoutes اضافه کنید:

اگر نسخه ای که نصب می کنید SignalR 2 باشد نیازی به این کد نیست، با دستور بالا طبیعتا نسخه 2 نصب می شود.

RouteTable.Routes.MapHubs();


باید namespace زیر را اضافه کنید:

using Microsoft.AspNet.SignalR; 


بر روی پروژه راست کلیک کنید و گزینه Add new item > Select “SignalR Hub Class” را انتخاب و نام آن را JobHub انتخاب کنید. دستورات زیر را به کلاس ایجاد شده اضافه کنید:

using Microsoft.AspNet.SignalR.Hubs;
 
 public class JobHub : Hub
    {
        public static void Show()
        {
            IHubContext context = GlobalHost.ConnectionManager.GetHubContext<JobHub>();
            context.Clients.All.displayStatus();
        }
    }


در کنترلر پیش فرض (نام کنترلر ما valuecontroller است)، یک شی از JobInfoRepository ایجاد و درون اکشنGet ، متد GetData را فراخوانی کنید:

public class ValuesController : ApiController
   {
 
       JobInfoRepository objRepo = new JobInfoRepository();
 
 
       // GET api/values
       public IEnumerable<JobInfo> Get()
       {
           return objRepo.GetData();
       }
   }


برای سادگی، ما در همین برنامه خود web api را مقدار دهی می کنیم، یک action با نام Status در Home controller ایجاد کنید، حال یک View بدون layout برای آن ایجاد کنید:

@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>JobStatus</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")
    <script src="~/Scripts/jquery.signalR-1.0.0-rc1.min.js"></script>
    <script src="~/signalr/hubs" type="text/javascript"></script>
    <script type="text/javascript">
 
        $(function () {
 
            // Proxy created on the fly
            var job = $.connection.jobHub;
 
            // Declare a function on the job hub so the server can invoke it
            job.client.displayStatus = function () {
                getData();
            };
          
            // Start the connection
            $.connection.hub.start();
            getData();
        });
 
        function getData() {
            var $tbl = $('#tblJobInfo');
            $.ajax({
                url: '../api/values',
                type: 'GET',
                datatype: 'json',
                success: function (data) {
                    if (data.length > 0) {
                        $tbl.empty();
                        $tbl.append(' <tr><th>ID</th><th>Name</th><th>Last Executed Date</th><th>Status</th></tr>');
                        var rows = [];
                        for (var i = 0; i < data.length; i++) {
                            rows.push(' <tr><td>' + data[i].JobID + '</td><td>' + data[i].Name + '</td><td>' + data[i].LastExecutionDate.toString().substr(0,10) + '</td><td>' + data[i].Status + '</td></tr>');
                        }
                        $tbl.append(rows.join(''));
                    }
                }
            });
        }
    </script>
</head>
<body>
    <div>
        <table id="tblJobInfo" style="text-align:center;margin-left:10px">
        </table>
    </div>
</body>
</html>


URL زیر را Browse کنید و آن را تست کنید:

http://yourserver/app/home/status


در پایگاه داده اگر تغییری ایجاد شود، متد dependency_OnChange به صورت trigger عمل خواهد کرد و متد Show مربوط به signalR Hub را فراخوانی خواهد نمود. این اطلاع ساخت (notifies) و trigger متد displayStatus در سمت کلاینت برای بروزرسانی داده ها است.


اگر شما خطای Javascript، " TypeError: $.connection is undefined" را دریافت کردید، باید مسیر jquery.signalR را در script reference های خود چک کنید تا مطمئن شوید آدرس شما در صفحه HTML صحیح وارد شده است.
اگر شما خطای Javascript، " The connection to http://localhost … was interrupted while the page was loading " را دریفات کردید، شما باید jquery ajax url خود را در متد GetData چک کنید.

دانلود پروژه SignalR و SqlDepedency

دانلود دیتابیس پروژه SignalR و SqlDepedency

نظرات (۶)

با سلام و احترام
ممنون از مطلب مفیدتون
چندتا سوال در مورد SignalR داشتم

1) آیا می توانیم از SignalR به صورت یه سرویس که اطلاعات جداول را از بانک اطلاعاتی فراهم می نماید استفاده نماییم؟ یعنی مثلا اطلاعاتی که از جداول مورد نیاز برای بازه های زمانی یک دقیقه ای محاسبه می نماییم داخل متدهای مربوط به فراخوانی SignalR قرار بگیرد و دیگر لازم نباشد تا هر برای هر کلاینت در Session مربوط به خودش که ارتباط دارد این کوئری ها را بر روی سرور اجرا نماید و فقط یکبار برای همه کلاینت ها این کوئری اجرا شود؟
2) ماکسیمم تعداد کلاینتی که می توان با این روش پشتیبانی نمود چقدر است ؟ مثلا برای 1000000 کلاینت می توانیم باز هم از همین روش SignalR استفاده نماییم؟
پاسخ:
سلام
خواهش می کنم، لطف دارید


در خصوص سوال اول باید خدمتتان عرض کنم:
بنده در همین خصوص دو نوع راه حل را برای شما مثال زده ام یکی استفاده از Timer و ساخت یک Timer برای اجرای متوالی دستوراتی که شاید نیازی به اتصال و ارتباط با پایگاه داده ندارند.

در مثال بعدی که در مقاله "بخش دهم - آموزش ساخت یک پروژه SignalR با SQLDepedency در ASP.NET MVC" می توانید آن را مطالعه کنید، مثالی با این مضمون مطرح شده است که اگر اطلاعات جدیدی در دیتابیس ثبت شد یا به هر شکلی تغییری بر روی یک جدول خاص انجام شد این تغییر به شما اعلام شود تا شما اطلاعات خود را بروز کنید، این مثال دقیقا پیاده سازی صفحه نمایش ایمیل در سرویس های  Gmail و Yahoo است که با ارسال یک ایمیل جدید صفحه شما به صورت اتوماتیک Refresh می شود.

سوال دوم

باتوجه به مقاله های ابتدایی همین دوره آموزشی بنده توضیح دادم که محدودیتی در استفاده این سرویس در خصوص تعداد کلاینت ها وجود دارد اما طبیعتا وابسته به نوع سرویسی که شما پیاده سازی می کنید باید تدابیری را در نظر بگیرید.

اگر نکته خاصی است که در این جا امکان بیان آن وجود ندارد لطفا پیام خصوصی بدهد، در حد بضاعتم، خوشحال خواهم شد بتوانم کمکی انجام دهم
سلام
ممنون از راهنمایی
در مورد پروژه Timer،آنرا بررسی کردم و مثال نمونه را اجرا کردم و خروجی را گرفتم، باز هم چند سوال، البته ببخشید که وقتتان را گرفتم.

1) زمانی که مثلا سمت سرور اتفاقی پیش بیاید یا مثلا برای رفع مشکل مجبور باشیم موقتا سرویس را Stop نماییم، بعد از بالا آمدن سرویس، کلاینت ها اطلاعات آنها به روز نمی شود تا زمانی که یکبار صفحه مرورگرشان را به روز رسانی نکنند، آیا راهکاری از طرف SignalR برای اینکار وجود دارد؟ یا اینکه یک javascript Timer برای چک نمودن اینکه صفحه باید به روز شود بنویسیم.

2) مقاله های ابتدایی همین دوره آموزشی شما را مطالعه نمودم ولی در مورد محدودیت کلاینتها برای استفاده از سرویس مطلبی پیدا نکردم شاید متوجه نشدم. اگر امکان دارد مقاله ای که در مورد تعداد کلاینتها و استفاده از آنها در سرویس و باری که بر روی سرور می گذارند و اینکه برای چه تعداد کلاینت این سرویس به نحو احسن کار می نماید را برای اینجانب لینک آن مقاله را ارسال فرمایید.

3) آیا این سرویس قابل اعتماد می باشد، منظورم از نظر موارد Security و همچنین اینکه در مواقعی که Service Broker را بخواهیم بر روی بانک اطلاعاتی فعال نماییم؟ آیا باز هم قابل اعتماد است؟ آیا در طولانی مدت که سرویس فعال می باشد، امکان این وجود دارد که سرویس خود بخود غیر فعال شود؟

4) آیا Node.js هم مانند SignalR عمل می کند؟ چون آن هم از WebSocket استفاده می کند. به نظر شما برای پروژه های مونیتورینگ کدوم تکنولوژی بهتره؟ Nodejs یا SignalR؟

با تشکر فراوان از سایت خوبتون


پاسخ:
با عرض سلام

خواهش می کنم، خوشحال می شوم اگر بتوانم کمکی انجام دهم هدف ما در اینجا وقت صرف کردن برای کمک به یکدیگر است، پس وقت کسی گرفته نمی شود :)

1) روشهای زیادی برای حل این مشکل وجود دارد، شخصا زیاد با سایت stackoverflow کار می کنم مدت پیش کل وب سایت اصلی و سرور ها را تغییر دادند این تغییر در 20 دقیقه صورت گرفت که بسیاری از کاربران حتی متوجه آن نشدن، اگر شما همان موقع به سایت مراجعه می کردید پیامی زیبا را دریافت می کردید اما پس از تغییر مجددا صفحه درخواستی شما به صورت خودکار Refresh و نمایش داده می شد.
کمی سرچ کنید روش های متفاوتی وجود دارد اگر مورد مناسبی یافت نکردید مطرح کنید تا یک مطلب در مورد آن بنویسیم تا سایر دوستان نیز از این امکان استفاده کنند.

2)خاطر نیستم، فکر کنم در مطلب دوم یا سوم بود. اما محدودیتی وجود ندارد دقیقا همین جمله را قید کردم که از لحاظ پشتیبانی تعداد کاربران هیچ مشکلی نیست.

3)Service Broker هیچ تداخلی و هیچ مشکل امنیتی برای شما ایجاد نخواهد کرد اما من شخصا SQL Server را چیزی شبیه یک نرم افزار قدرتمند می بینم و شما خیلی موارد را می توانید توسط خود این نرم افزار انجام دهید حال چه مباحث امنیتی چه مباحث DB اما متاسفانه به دلیل تخصصی کار نکردن در کشور همه فقط با این ابزار برای نگهداری اطلاعات کار می کنیم. نه اینطور نیست که خود به خود غیرفعال شود اصلا این مورد اگر باشد غیرمنطقی خواهد بود.

4) این متن تعریف کتابخانه Node.js است:

Node.js® is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications

کاربرد این کتابخانه با SignalR متفاوت است و نکته مهمتر و تنها دلیلم برای نوشتن تعریف این کتابخانه برای شما این است که SignalR توسط مایکروسافت حمایت می شود و این کتابخانه non-Microsoft، این دلیل بر بد بودن Node.js نیست، به هیچ وجه، اما شاید سازگاری و مهمتر از آن رشد برای SignalR بیشتر باشد مثال ساده آن MVC، یک framework مربوط به Ruby on Rails  که بعدها در PHP نیز مورد استفاده قرار گرفت و آخر از همه مایکروسافت به فکر آن افتاد، حال رشد را این تکنولوژی ها را هم در نظر بگیرید، نه تنها در ایران، در همین وبلاگ مطلبی را برای میزان استفاده از زبان های مختلف قرار دادم که بیان گر این موضوع است که شاید مایکروسافت با کپی برداری ایده های OpenSource و سرمایه گذاری بر روی آن ها چیزیهایی توسط آنها تولید می کند که خلاق اولیه نیز به آن فکر نکرده، دلیلش مشخص است کاربران زیاد و حمایت مالی، که در Open source این دو اینقدر توان ندارند.

درنهایت من SignalR را می پسندم اما این جوابم کلی است شما باید وابسته به جزئیات، حجم پروژه و.... تصمیم بگیرید.

ممنون
موفق باشید

برای asp webform چجوری هست؟
من میخوام  هر تغییری که توی sql رخ میده رو متوجه بشم ؟


جای Domain\ASPNET چی باید بنویسیم من نفهمیدم اینو؟
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO Domain\ASPNET


با سلام و احترام
دو تا سوال داشتم، ممنون میشم جوابمو بدید:
1: وقتی سرویس بروکر تو sql رو run میکنیم ، کجای کار بهش میگیم که مثلا فلان جدول رو بررسی بکن اگه تغییری رخ داد به اپ نوتیف بفرست? معرفی کردن جدول خاص کجا انجام میشه؟

2: بنظر شما از لحاظ performance استفاده از تایمر جهت گرفتن نوتیف های جدید بهتره یا استفاده از sql dependency
 با تشکر فراوان از شما
پاسخ:
با عرض سلام

شما وقتی Broker را فعال می کنید دیتابیسی را که میخواهید مانیتور شود مشخص می نمایید، حال باید درون کد خود اطلاعات یک Table خاص را واکشی Fetch کنید.

sql dependency بسیار راه حل بهتری است زیرا sql dependency خود یک Timer است که توسط SQL مدیریت می شود اما هیچ وقت نمی توان 100% گفت چه راه حلی برای چه مسئلی بهتر است زیرا صورت مسئله مشخص می کند شما باید چه راه حلی را انتخاب کنید.
با سلام 
ممنون از مطلب خوبتون
اما این پروژه مشکل نشتی حافظه داره ، و برای یه پروژه واقعی کارا نیست ،  
به ازای هر درخواست یک dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
داریم. در صورتی که  بازای هر + باید یک بار -  باید بشه. اگر - نشه یعنی  اشیاء در حافظه باقی می مانند
پاسخ:
با عرض سلام

ممنون از اینکه این مطلب را دقیقا بررسی کرده اید.
طبیعتا شما می توانید با کمک گرفتن از این مطلب برای ساخت پروژه های تجاری استفاده نمایید، ما از این تکنولوژی در چندین پروژه استفاده کرده ایم که همه ی آنها در مقیاس های بزرگ و با تراکنش های سنگین روبرو بوده اند که اگر بتوانید موارد را رعیات کنید مشکلی نخواهید داشت و می توانیدبا کارایی بسیار بالا از این تکنولوژی استفاده کنید.
همانطور که در ابتدای آموزش عرض کردم، از این تکنولوژی در ساخت صنعت Game های آنلاین استفاده شده است که نمونه ای از آن را برای شما معرفی کردم در نتیجه اگر به خوبی از این تکنولوژی استفاده کنید نباید نگران کارایی باشید.




با سلام
پروژه رو اجرا کردم ، کامل ران شد و بدون مشکل کار میکنه، اما همین پروژه رو پابلیش کردم و رو iis گذاشتم ، sql dependency کار نمیکنه با اینکه GRANT SUBSCRIBE QUERY NOTIFICATIONS TO  هم انجام دادم اما همچنان مشکل داره، برای مطمئن شدن از موضوع ، یه تب از مرورگر لوکال رو ران کردم و یه تب دیگه اونیکه تو iis گذاشتم جالبه وقتی تغییری تو دیتابیس میکنه رو لوکال اعمال میشه اما رو iis خیر
اینجور که معلوم مشکل از کد نمیتونه بهیچ وجه باشه یه مشکلیه بین iis , sql 
بنظر شما دیگه چی رو باید ست کنم که رو iis مشکل پیش نیاد

با تشکر
پاسخ:
با عرض سلام

در قسمت Application Pool مربوط به IIS شما می توانید Mode های مختلفی را برای دسترسی وب سایت خود تنظیم کنید پیشنهاد می کنم آن را بر روی Local system قرار داده و مجددا تست کنید

باتشکر
ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی
up
ما را در گوگل محبوب کنید