دوره آموزشی 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 نمایش می دهد.
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”
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
نظرات (۶)
سلام
خواهش می کنم، لطف دارید
در خصوص سوال اول باید خدمتتان عرض کنم:
بنده در همین خصوص دو نوع راه حل را برای شما مثال زده ام یکی استفاده از 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 را می پسندم اما این جوابم کلی است شما باید وابسته به جزئیات، حجم پروژه و.... تصمیم بگیرید.
ممنون
موفق باشید
با تشکر فراوان از شما
با عرض سلام
شما وقتی Broker را فعال می کنید دیتابیسی را که میخواهید مانیتور شود مشخص می نمایید، حال باید درون کد خود اطلاعات یک Table خاص را واکشی Fetch کنید.
sql dependency بسیار راه حل بهتری است زیرا sql dependency خود یک Timer است که توسط SQL مدیریت می شود اما هیچ وقت نمی توان 100% گفت چه راه حلی برای چه مسئلی بهتر است زیرا صورت مسئله مشخص می کند شما باید چه راه حلی را انتخاب کنید.
داریم. در صورتی که بازای هر + باید یک بار - باید بشه. اگر - نشه یعنی اشیاء در حافظه باقی می مانند
با عرض سلام
ممنون از اینکه این مطلب را دقیقا بررسی کرده اید.
طبیعتا شما می توانید با کمک گرفتن از این مطلب برای ساخت پروژه های تجاری استفاده نمایید، ما از این تکنولوژی در چندین پروژه استفاده کرده ایم که همه ی آنها در مقیاس های بزرگ و با تراکنش های سنگین روبرو بوده اند که اگر بتوانید موارد را رعیات کنید مشکلی نخواهید داشت و می توانیدبا کارایی بسیار بالا از این تکنولوژی استفاده کنید.
همانطور که در ابتدای آموزش عرض کردم، از این تکنولوژی در ساخت صنعت Game های آنلاین استفاده شده است که نمونه ای از آن را برای شما معرفی کردم در نتیجه اگر به خوبی از این تکنولوژی استفاده کنید نباید نگران کارایی باشید.
با تشکر
با عرض سلام
در قسمت Application Pool مربوط به IIS شما می توانید Mode های مختلفی را برای دسترسی وب سایت خود تنظیم کنید پیشنهاد می کنم آن را بر روی Local system قرار داده و مجددا تست کنید
باتشکر
ممنون از مطلب مفیدتون
چندتا سوال در مورد SignalR داشتم
1) آیا می توانیم از SignalR به صورت یه سرویس که اطلاعات جداول را از بانک اطلاعاتی فراهم می نماید استفاده نماییم؟ یعنی مثلا اطلاعاتی که از جداول مورد نیاز برای بازه های زمانی یک دقیقه ای محاسبه می نماییم داخل متدهای مربوط به فراخوانی SignalR قرار بگیرد و دیگر لازم نباشد تا هر برای هر کلاینت در Session مربوط به خودش که ارتباط دارد این کوئری ها را بر روی سرور اجرا نماید و فقط یکبار برای همه کلاینت ها این کوئری اجرا شود؟
2) ماکسیمم تعداد کلاینتی که می توان با این روش پشتیبانی نمود چقدر است ؟ مثلا برای 1000000 کلاینت می توانیم باز هم از همین روش SignalR استفاده نماییم؟