پیاده سازی CRUD با استفاده از SignalR و Entity Framework

دوشنبه 8 شهریور 1395

در این مقاله قصد داریم با استفاده از Entity Framework و SignalR در ASP.NET MVC حذف ، افزودن ، ویرایش را به صورت realtime انجام دهیم و از روش Code First استفاده می کنیم .

پیاده سازی CRUD با استفاده از SignalR و Entity Framework

مقدمه

SignalR تکنولوژی است که به ما قابلیت افزودن توابع real time را به وب سایت خود اضافه کنیم . این بدان معنا است که افزودن ، حذف ، ویرایش محتوا با داده ها بلافاصله انجام می شود.

Entity Framework  یک ORM است که  کار با داده های رابطه ای را با استفاده از شی هایی با دامنه خاص ، آسان تر می کند برای دسترسی به داده ها ما از روش Code First استفاده می کنیم.

ASP.NET MVC یک فریم ورک برای پیاده سازی scalable ، مبتنی بر استاندارد های برنامه کاربردی وب است .

شروع کار به صورت مرحله ای

مرحله اول : یک پروژه MVC ایجاد می کنیم و رفرنس EF را با پروژه اضافه می کنیم .

در این قسمت ویژوال استودیو را اجرا کرده و یک پروژه mvc ایجاد می کنیم و دستور زیر را در Package Manager Console وارد می کنیم تا EF به پروژه اضافه شود .

using System.ComponentModel.DataAnnotations;

namespace WebApplication1.Models
{
    public class Employee
    {
        [Key]
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
        public string EmailAdress { get; set; }
        public string MobileNumber { get; set; }
    }
}

مرحله سوم : حال کلاس Context  را ایجاد می کنیم .

در این قسمت کلاس EmployeeContext را ایجاد کرده ایم کد زیر را مشاهده کنید :

using System.Data.Entity;
using WebApplication1.Models;

namespace WebApplication1
{
    public class EmployeeContext : DbContext
    {
        public EmployeeContext() : base("dbConnectionString")
        {
            Database.SetInitializer<EmployeeContext>(new CreateDatabaseIfNotExists<EmployeeContext>());
        }
        public DbSet<Employee> Employees { get; set; }
    }
}

مرحله چهارم : یک Connection String به Web.config اضافه می کنیم .

<connectionStrings>
    <add name="dbConnectionString" connectionString="Data Source=yourdatasource;Initial Catalog=EmployeeDB;User ID=youdbuserid;Password=yourdbpassword;pooling=false; MultipleActiveResultSets=True;pooling=false;" providerName="System.Data.SqlClient" />
</connectionStrings>

مرحله 5 : نصب SignalR  با استفاده از Nuget

با وارد کردن  دستور زیر در Package Manager Console ، SignalR به پروژه اضافه می شود .

Install-Package Microsoft.AspNet.SignalR

در این قسمت ما نیاز به ایجاد Startup.cs  داریم که هدف از ایجاد این فایل اضافه کردن یک middleware به جریان OWIN است . برای افزودن این فایل بر روی پروژه راست کلیک و در قسمت Add  ، OWIN Startup class را انتخاب می کنیم .

نام آن را Startup قرار می دهیم .

تصویر زیر شامل کد های  فایل startup.cs است .

کد زیر  کلاس Startup را پیدا می کند .

[assembly: OwinStartup(typeof(WebApp.Startup))]

این نشان دهده این است که این کلاس تابع دریافت ، Microsoft.Owin.IowinContext  را اجرا می کند .

هنگامی که سرور درخواست HTTP را دریافت می کند ، OWIN pipeline فراخوانی می شود و middleware را درخواست می کند .

Middleware نوع محتوا را برای پاسخ و نوشتن پاسخ در body  ، تعیین می کند .

در حال حاظر در تابع  Configuration ما به map SignalR hubs نیاز داریم . برای اضافه کردن آن میتوان از روش زیر استفاده کرد .

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(WebApplication1.Startup))]

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

دراین قسمت نیاز به ایجاد یک Hub داریم . کلاس Hub با استفاده از communication  بین Client و Server یک اتصال ایجاد می کند .این عمل باعث می شود که Server , Client از راه دور به هم متصل شوند . برای پیاده سازی این عمل یک کلاس به نام EmployeeHub.cs    ایجاد می کنیم و کد های زیر را وارد می کنیم .

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;

namespace WebApplication1
{
    public class EmployeeHub : Hub
    {
        [HubMethodName("NotifyClients")]
        public static void NotifyCurrentEmployeeInformationToAllClients()
        {
            IHubContext context = GlobalHost.ConnectionManager.GetHubContext<EmployeeHub>();

            // the update client method will update the connected client about any recent changes in the server data
            context.Clients.All.updatedClients();
        }
    }
}

Hub  یک کلاس abstract است که متد های SignalR را ارجاع می دهد . و با ارتباط برقرار کردن با SignalR به Microsoft.AspNet.SignalR.Hub. متصل می شود .

IHubContext context = GlobalHost.ConnectionManager.GetHubContext<EmployeeHub>();

Context   ، Employee را دریافت می کند . متد updatedClients میخواهد  متد Client را بروزرسانی کند و تغییراتی که برروی داده های انجام شده بر روی سرور اعمال کند .

context.Clients.All.updatedClients();

قسمت SignalR client فراخوانی می شود و متد جاوا اسکریپتی updatedClients() اجرا می شود . Hub در ارسال پیام و داده بین Client و سرور بسیار مهم است .

مرحله ششم : ایجاد Controller

کد های  تشکیل دهنده   Controller  است .

using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web.Mvc;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        List<Employee> empList;

        //Fetch Employee Records
        public ActionResult Index()
        {
            return View();
        }
        [HttpGet]
        public ActionResult GetAllEmployeeRecords()
        {
            using (var context = new EmployeeContext())
            {
                empList = context
                .Employees
                .ToList();
            }          
            return PartialView("_EmployeeList", empList);
        }


        //Insert Employee Record
        public ActionResult Insert()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Insert(Employee employee)
        {  
                if (ModelState.IsValid)
                {
                    //Insert into Employee table 
                    using (var context = new EmployeeContext())
                    { 
                            context.Employees.Add(employee);
                            context.SaveChanges();                       
                    }                                       
                }
           
            //Once the record is inserted , then notify all the subscribers (Clients)
            EmployeeHub.NotifyCurrentEmployeeInformationToAllClients();
            return RedirectToAction("Index");
        }

        //Update Employee Record
        public ActionResult Update()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Update(Employee employee)
        {
            using (var context = new EmployeeContext())
            {
                var empRecord = context.Employees.Find(employee.EmployeeID);

                empRecord.EmployeeName = employee.EmployeeName;
                empRecord.EmailAdress = employee.EmailAdress;
                empRecord.MobileNumber = employee.MobileNumber;

                context.Employees.Add(empRecord);

                context.Entry(empRecord).State = EntityState.Modified;
                context.SaveChanges();
            }

            //Once the record is inserted , then notify all the subscribers (Clients)
            EmployeeHub.NotifyCurrentEmployeeInformationToAllClients();
            return RedirectToAction("Index");
        }

        //Delete Employee Record
        [HttpPost]
        public ActionResult Delete(Employee employee)
        {
            using (var context = new EmployeeContext())
            {
                var empRecord = context.Employees.Find(employee.EmployeeID); 
                context.Employees.Remove(empRecord);
                context.SaveChanges();
            }

            //Once the record is inserted , then notify all the subscribers (Clients)
            EmployeeHub.NotifyCurrentEmployeeInformationToAllClients();
            return RedirectToAction("Index");
        }
    }
}

مرحله هفتم : ایجاد View

در نهایت ، به طراحی UI و درخواست API های Controller و وارد کردن اطلاعات کاربران به صورت real time و بروزرسانی آنها میپردازیم . کد های زیر تشکیل دهنده فایل Index.cshtml است :

@model IList<SignalRSample.Models.Employee>
@{
 
}
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
 
<div>
    <table border="1">
        <tr>
            <td>
                <h1 style="color:blueviolet">برنامه نویسان</h1>
                <table border="1">
                    <tr>
                        <td>شماره</td>
                        <td><input id="txtEmployeeId" type="text" /></td>
                    </tr>
                    <tr>
                        <td>نام کاربری</td>
                        <td><input id="txtEmployeeName" type="text" /></td>
                    </tr>
                    <tr>
                        <td>ایمیل</td>
                        <td><input id="txtEmail" type="text" /></td>
                    </tr>
                    <tr>
                        <td>شماره موبایل</td>
                        <td><input id="txtMobile" type="text" /></td>
                    </tr>
                </table>
                <table border="1">
                    <tr>
                        <td><button id="btnPostEmployee" onclick="InsertEmployee()">افزودن</button></td>
                        <td>
                            <button id="btnPutEmployee" onclick="UpdateEmployee()">ویرایش</button>
                            <button id="btnDeleteEmployee" onclick="DeleteEmployee();return false;">حذف</button>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
    <br /><br />
    <div id="dataTable"></div>
</div>
 
@section Scripts{
 
    
    <script type="text/javascript">
        $(function () {
          
            // Create a proxy to signalr hub on web server. It reference the hub.
            var notificationFromHub = $.connection.employeeHub;
 
            // Connect to signalr hub
            $.connection.hub.start().done(function () {
                                FetchEmployees();

            });
 
            // Notify to client with the recent updates
            notificationFromHub.client.updatedClients = function () {
                FetchEmployees();
            };
        });
 
        function FetchEmployees() {
            var model = $('#dataTable');
            $.ajax({
                    url: '/home/GetAllEmployeeRecords',
                    contentType: 'application/html ; charset:utf-8',
                    type: 'GET',
                    dataType: 'html'
                })
                .success(function(result) { model.empty().append(result); });
        }
 
        // Insert Employee Record
        function InsertEmployee()
        {
 
                    var employee = {
                        EmployeeID: $('#txtEmployeeId').val(),
                        EmployeeName: $('#txtEmployeeName').val(),
                        EmailAdress: $('#txtEmail').val(),
                        MobileNumber: $('#txtMobile').val()
                    };
 
 
                    $.ajax({
                    url: '/home/Insert',
                    type: 'POST',
                    data: JSON.stringify(employee),
                    contentType: "application/json;charset=utf-8",
                    success: function (data) {
                        alert('Employee added Successfully');
                    },
                    error: function () {
                        alert('Employee not Added');
                    }
                    });
                  
 
        }
 
        // Update Employee Record
        function UpdateEmployee() {
 
            var employee = {
                EmployeeID: $('#txtEmployeeId').val(),
                EmployeeName: $('#txtEmployeeName').val(),
                EmailAdress: $('#txtEmail').val(),
                MobileNumber: $('#txtMobile').val()
            };
 
            $.ajax({
                url: '/home/Update',
                type: 'POST',
                data: JSON.stringify(employee),
                contentType: "application/json;charset=utf-8",
                success: function (data) {
                    alert('Employee updated Successfully');
                },
                error: function (e) {
                    alert('Employee could not be updated');
                }
            });
            
        }
 
        // Delete Employee Record
        function DeleteEmployee() {
 
            var employee = {
                EmployeeID: $('#txtEmployeeId').val()
            };
 
            $.ajax({
                url: '/home/Delete',
                type: 'POST',
                data: JSON.stringify(employee),
                contentType: "application/json;charset=utf-8",
                success: function (data) {
                    alert('Employee deleted Successfully');
                },
                error: function (x, y, z) {
                    alert(x + '\n' + y + '\n' + z);
                }
            });
        
        }
    </script>
}

قطعه کد

            // Create a proxy to signalr hub on web server. It reference the hub.
            var notificationFromHub = $.connection.employeeHub;
            
            // Connect to signalr hub
            $.connection.hub.start().done(function () {
                FetchEmployees();
            });

            // Notify to client with the recent updates
            notificationFromHub.client.updatedClients = function () {
                FetchEmployees();
            };
        });

در ابتدا یک Proxy در  SignalR Hub  روی وب سرور ایجاد کرده ایم . و پس از انجام شدن عملیات ما نیاز به اتصال به Hub داریم .سرور،  بروزرسانی رکورد ها را با استفاده از متد  updatedClients اطلاع رسانی می کند .

حال یکم Patial View به نام   _Employee.cshtml  برای نمایش سوابق کارمندها ایجاد می کنیم.

<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>شماره</th>
            <th>نام کاربری</th>
            <th>ایمیل</th>
            <th>شماره موبایل</th>
        </tr>
    </thead>
    <tbody>
        @if (Model != null)
            {
                foreach (var item in Model)
                {
 
                <tr>
                    <td>@item.EmployeeID</td>
                    <td>@item.EmployeeName</td>
                    <td>@item.EmailAdress</td>
                    <td>@item.MobileNumber</td>
                </tr>
            }
        }
 
    </tbody>
</table>

تمامی عملیاتی که انجام داده ایم میتوان در زیر مشاهده کنید .

مرحله هشتم : برنامه را اجرا می کنیم.

برنامه را با دو مرورگر مختلف اجرا می کنیم .

حال یک کارمند در هر دو مرورگر اضافه می کنیم .

میتوان مشاهده کنید که عملیات به صورت real time انجام می شود .

میتوان با استفاده از کد زیر  جدول های خود را تغییر دهید :

1. Enable-Migrations first,
                2. then add-migration
                3. followed by update-database commands from package manager console.

آموزش asp.net mvc

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید