عملیات CRUD با استفاده از Dapper ORM در MVC

در این مقاله قصد داریم چگونگی پیاده سازی عملیات CRUD را با استفاده از Dapper ORM مورد بررسی قرار دهیم. Dapper یک ORM متن باز است که برای map کردن کلاس های NET. به بانک اطلاعاتی مورد استفاده قرار می گیرد.

عملیات CRUD با استفاده از Dapper ORM در MVC

پیش زمینه

تعداد بسیاری ORM متن باز برای map شدن به کلاس های بانک اطلاعاتی وجود دارد، که ما در این مقاله در مورد Dapper ORM صحبت خواهیم کرد. و می توانیم آن را  پادشاه  ORMها بنامیم. در این مقاله Dapper ORM را با استفاده از عملیات CRUD در MVC پیاده سازی می کنیم.

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

Dapper چیست؟

Dapper یک ORM منبع باز است که برای map کردن کلاس های مایکروسافت .NET به بانک اطلاعاتی مورد استفاده قرار می گیرد.

مرحله 1 : یک پروژه MVC بسازید.

از اینجا  قدم به قدم رویکرد ایجاد پروژه MVC را مانند زیر انجام دهید:

1. بعد از باز کردن نرم افزار Visual Studio گزینه File و سپس New و بعد Project را کلیک کرده و در آخر ASP.NET Web Application را انتخاب کنید.

2. سپس یک نام مناسب برای پروژه انتخاب کنید و OK را کلیک کنید. بعد از کلیک پنجرا زیر ظاهر خواهد شد:

 

3. همانطور که در تصویر نشان داده شد یک پروژه MVC  خالی ایجاد کنید و می بینید که قسمت Solution Explorer آن به صورت زیر خواهد شد:

 

مرحله 2: منابع Dapper ORM را طبق مراحل زیر به پروژه ایجاد شده اضافه کنید.

1. بر روی Solution  راست کلیک کرده و Manage NuGet Package manager را پیدا و بر روی آن کلیک کنید.

2. بعد از اینکه تصویر زیر ظاهر شد، در قسمت جستجو کلمه dapper  را بنویسید.

3. مانند شکل زیر dapper را انتخاب کنید.

4. نسخه کتابخانه dapper را انتخاب کرده و بر روی دکمه install کلیک کنید.

 

بعد از نصب کتابخانه dapper ، منابع(رفرنس های ) به solution explorer پروژه MVC  شما اضافه خواهد شد  مانند زیر:


 

مرحله  3: ایجاد مدل کلاس.

در این مرحله  بر روی فولدر model کلیک راست کرده و کلاس مدل را با نام EmpModel.cایجاد می کنیم، مانند زیر:

 

توجه: کلاس مدل لزوما نباید در پوشه Model باشد و این فقط برای نظم و خوانایی بیشتر در پروژه می باشد ،شما می توانید این کلاس را در هر جای دیگری از solution explorer بسازید. این یعنی کلاس می تواند در پوشه ای با نام دیگر و یا حتی بدون پوشه و در کتابخانه کلاس به صورت جداگانه ساخته شود.

قطعه کد کلاس EmpModel.cs :

public class EmpModel    
{    
      [Display(Name = "Id")]    
      public int Empid { get; set; }    
    
      [Required(ErrorMessage = "First name is required.")]    
      public string Name { get; set; }    
    
      [Required(ErrorMessage = "City is required.")]    
      public string City { get; set; }    
    
      [Required(ErrorMessage = "Address is required.")]    
      public string Address { get; set; }    
    
} 

 

در کلاس مدل بالا برخی اعتبار سنجی ها را با  کمک DataAnnotation ها اضافه کنید.

مرحله 4: ایجاد کنترلر.

در این مرحله ما یک کنترلر به شکل زیر در پروژه ایجاد می کنیم:

 

پس از کلیک کردن بر روی دکمه Add ، پنجره زیر نشان داده خواهد شد. حالا نام کنترلر خود را با عنوان Employee و با پسوند Controller تعیین کنید، مانند زیر:

 

 

توجه: نام کنترلر حتما باید پسوند Controller داشته باشد.

بعد از کلیک بر روی دکمه Add کنترلری ایجاد می شود که با کد های پیش فرض از عملیات CRUD پشتیبانی می کند و ما می توانیم آن را طبق نیازمندی های خود تغییر دهیم.

مرحله 5: ایجاد جدول و Stored procedure ها.

در اینجا قبل از اینکه View را بسازیم، جدولی با نام Employee طبق مدل در بانک اطلاعاتی خود برای ذخیره جزییات ایجاد می کنیم.

 

حالا stored procedure ها را مانند آنچه که در قطعه کد زیر آمده برای insert، update، view و delete جزییات ایجاد می کنیم.

برای وارد کردن رکوردها:

Create procedure [dbo].[AddNewEmpDetails]  
(  
   @Name varchar (50),  
   @City varchar (50),  
   @Address varchar (50)  
)  
as  
begin  
   Insert into Employee values(@Name,@City,@Address)  
End

 

برای مشاهده رکوردهای اضافه شده:

 

CREATE Procedure [dbo].[GetEmployees]    
as    
begin    
   select Id as Empid,Name,City,Address from Employee  
End


برای آپدیت کردن رکوردها:

Create procedure [dbo].[UpdateEmpDetails]  
(  
   @EmpId int,  
   @Name varchar (50),  
   @City varchar (50),  
   @Address varchar (50)  
)  
as  
begin  
   Update Employee  
   set Name=@Name,  
   City=@City,  
   Address=@Address  
   where Id=@EmpId  
End 

برای حذف رکوردها:

Create procedure [dbo].[DeleteEmpById]  
(  
   @EmpId int  
)  
as  
begin  
   Delete from Employee where Id=@EmpId  
End 

 

مرحله 6: ایجاد کلاس Repository.

در اینجا پوشه Repository را می سازیم و کلاس EmpRepository.cs را برای عملیات پایگاه داده مربوط اضافه می کنیم. بعد از اضافه کردن آن، solution explorer به صورت زیر خواهد شد:

 

اکنون متدهای زیر را در EmpRepository.cs ایجاد کنید تا بتوانید عملیات CRUD را مدیریت کنید، مانند قطعه کد زیر :

EmpRepository.cs
 

public class EmpRepository      
{      
    public SqlConnection con;      
    //To Handle connection related activities      
    private void connection()      
    {      
        string constr = ConfigurationManager.ConnectionStrings["SqlConn"].ToString();      
        con = new SqlConnection(constr);      
  
    }      
    //To Add Employee details      
    public void AddEmployee(EmpModel objEmp)      
    {      
  
        //Additing the employess      
        try      
        {      
            connection();      
            con.Open();      
            con.Execute("AddNewEmpDetails", objEmp, commandType: CommandType.StoredProcedure);      
            con.Close();      
        }      
        catch (Exception ex)      
        {      
  
            throw ex;      
        }      
  
    }      
    //To view employee details with generic list       
    public List<EmpModel> GetAllEmployees()      
    {      
        try      
        {      
            connection();      
            con.Open();      
            IList<EmpModel> EmpList = SqlMapper.Query<EmpModel>(      
                              con, "GetEmployees").ToList();      
            con.Close();      
            return EmpList.ToList();      
        }      
        catch (Exception)      
        {      
  
            throw;      
        }      
    }      
  
    //To Update Employee details      
    public void UpdateEmployee(EmpModel objUpdate)      
    {      
        try      
        {      
            connection();      
            con.Open();      
            con.Execute("UpdateEmpDetails", objUpdate, commandType: CommandType.StoredProcedure);      
            con.Close();      
        }      
        catch (Exception)      
        {      
  
            throw;      
        }      
  
    }      
    //To delete Employee details      
    public bool DeleteEmployee(int Id)      
    {      
        try      
        {      
            DynamicParameters param = new DynamicParameters();      
            param.Add("@EmpId", Id);      
            connection();      
            con.Open();      
            con.Execute("DeleteEmpById", param, commandType: CommandType.StoredProcedure);      
            con.Close();      
            return true;      
        }      
        catch (Exception ex)      
        {      
            //Log error as per your need       
            throw ex;      
        }      
    }      
}  

 

توجه: در کد بالا ما به طور دستی connection را باز و بسته می کنیم، با این حال شما می توانید connection string را به طور مستقیم و بدون باز کردن آن به Dapper پاس دهید. Dapper به طور اتوماتیک آن را مدیریت می کند.

مرحله 7: ایجاد متدها در فایل EmployeeController.cs

حالا EmployeeController.cs را وارد کرده و متدهای Action را به صورت زیر ایجاد کنید:

public class EmployeeController : Controller      
{      
   
    // GET: Employee/GetAllEmpDetails      
    public ActionResult GetAllEmpDetails()      
    {      
        EmpRepository EmpRepo = new EmpRepository();      
        return View(EmpRepo.GetAllEmployees());      
    }      
    // GET: Employee/AddEmployee      
    public ActionResult AddEmployee()      
    {      
        return View();      
    }      
   
    // POST: Employee/AddEmployee      
    [HttpPost]      
    public ActionResult AddEmployee(EmpModel Emp)      
    {      
        try      
        {      
            if (ModelState.IsValid)      
            {      
                EmpRepository EmpRepo = new EmpRepository();      
                EmpRepo.AddEmployee(Emp);      
   
                ViewBag.Message = "Records added successfully.";      
   
            }      
   
            return View();      
        }      
        catch      
        {      
            return View();      
        }      
    }      
   
    // GET: Bind controls to Update details      
    public ActionResult EditEmpDetails(int id)      
    {      
        EmpRepository EmpRepo = new EmpRepository();      
        return View(EmpRepo.GetAllEmployees().Find(Emp => Emp.Empid == id));      
   
    }      
   
    // POST:Update the details into database      
    [HttpPost]      
    public ActionResult EditEmpDetails(int id, EmpModel obj)      
    {      
        try      
        {      
            EmpRepository EmpRepo = new EmpRepository();      
   
            EmpRepo.UpdateEmployee(obj);      
   
            return RedirectToAction("GetAllEmpDetails");      
        }      
        catch      
        {      
            return View();      
        }      
    }      
   
    // GET: Delete  Employee details by id      
    public ActionResult DeleteEmp(int id)      
    {      
        try      
        {      
            EmpRepository EmpRepo = new EmpRepository();      
            if (EmpRepo.DeleteEmployee(id))      
            {      
                ViewBag.AlertMsg = "Employee details deleted successfully";      
   
            }      
            return RedirectToAction("GetAllEmpDetails");      
        }      
        catch      
        {      
            return RedirectToAction("GetAllEmpDetails");      
        }      
    }      
}

 

مرحله 8: ایجاد View ها.

یک Partial view برای اضافه کردن employees ایجاد کنید.

برای ایجاد Partial view و AddEmployee، بر روی متد ActionResult کلیک راست کرده و سپس بر روی View کلیک کنید. حالا نام View را مشخص کنید و مانند شکل زیر عمل کنید:

 

بعد کلیک بر روی دکمه Add آنگاه View  به صورت strongly typed ایجاد می شود که در کد زیر نیز آمده است:

AddEmployee.cshtml

@  
model CRUDUsingMVC.Models.EmpModel@ using(Html.BeginForm()) {@  
    Html.AntiForgeryToken()  
  
    < div class = "form-horizontal" >  
        < h4 > Add Employee < /h4>   < div > @Html.ActionLink("Back to Employee List", "GetAllEmpDetails") < /div>   < hr / > @Html.ValidationSummary(true, "", new {@  
            class = "text-danger"  
        })  
  
  
    < div class = "form-group" > @Html.LabelFor(model => model.Name, htmlAttributes: new {@  
        class = "control-label col-md-2"  
    }) < div class = "col-md-10" > @Html.EditorFor(model => model.Name, new {  
        htmlAttributes = new {@  
            class = "form-control"  
        }  
    })@ Html.ValidationMessageFor(model => model.Name, "", new {@  
        class = "text-danger"  
    }) < /div>   < /div>    
  
    < div class = "form-group" > @Html.LabelFor(model => model.City, htmlAttributes: new {@  
        class = "control-label col-md-2"  
    }) < div class = "col-md-10" > @Html.EditorFor(model => model.City, new {  
        htmlAttributes = new {@  
            class = "form-control"  
        }  
    })@ Html.ValidationMessageFor(model => model.City, "", new {@  
        class = "text-danger"  
    }) < /div>   < /div>    
  
    < div class = "form-group" > @Html.LabelFor(model => model.Address, htmlAttributes: new {@  
        class = "control-label col-md-2"  
    }) < div class = "col-md-10" > @Html.EditorFor(model => model.Address, new {  
        htmlAttributes = new {@  
            class = "form-control"  
        }  
    })@ Html.ValidationMessageFor(model => model.Address, "", new {@  
        class = "text-danger"  
    }) < /div>   < /div>    
  
    < div class = "form-group" >  
        < div class = "col-md-offset-2 col-md-10" >  
        < input type = "submit"  
    value = "Save"  
    class = "btn btn-default" / >  
        < /div>   < /div>   < div class = "form-group" >  
        < div class = "col-md-offset-2 col-md-10"  
    style = "color:green" > @ViewBag.Message  
  
        < /div>   < /div>   < /div>    
  
} < script src = "~/Scripts/jquery-1.10.2.min.js" > < /script>   < script src = "~/Scripts/jquery.validate.min.js" > < /script>   < script src = "~/Scripts/jquery.validate.unobtrusive.min.js" > < /script> 

 

برای مشاهده جزییات employee  یک partial view با نام GetAllEmpDetails می سازیم:

 

حالا بر روی دکمه Add کلیک کنید، این یک strongly typed view با نام GetAllEmpDetails.cshtml می سازد که کد آن در زیر آمده است:

 

GetAllEmpDetails.CsHtml

 

@model IEnumerable < CRUDUsingMVC.Models.EmpModel >  
  
    < p > @Html.ActionLink("Add New Employee", "AddEmployee") < /p>    
  
< table class = "table" >  
    < tr >  
  
    < th > @Html.DisplayNameFor(model => model.Name) < /th>   < th > @Html.DisplayNameFor(model => model.City) < /th>     
    < th > @Html.DisplayNameFor(model => model.Address) < /th>   < th > < /th>   < /tr>    
  
    @foreach(var item in Model)   
    {  
        @Html.HiddenFor(model => item.Empid)   
        < tr >  
  
            < td > @Html.DisplayFor(modelItem => item.Name) < /td>     
            < td > @Html.DisplayFor(modelItem => item.City) < /td>     
            < td > @Html.DisplayFor(modelItem => item.Address) < /td>     
            < td > @Html.ActionLink("Edit", "EditEmpDetails", new {  
                    id = item.Empid  
                }) | @Html.ActionLink("Delete", "DeleteEmp", new {  
                    id = item.Empid  
                 }, new {  
                 onclick = "return confirm('Are sure wants to delete?');"  
                })   
            < /td>     
        < /tr>    
  
    }  
  
< /table> 

به روز رسانی کارمندان اضافه شده

همان مراحل مشابه را استفاه کرده و یک View با نام EditEmpDetails برای ویرایش بسازید. بعد از ایجاد View کد به صورت زیر خواهد بود:

EditEmpDetails.cshtml

@model CRUDUsingMVC.Models.EmpModel  
  
  
@ using(Html.BeginForm()) {@  
    Html.AntiForgeryToken()  
  
    < div class = "form-horizontal" >  
        < h4 > Update Employee Details < /h4>   < hr / >  
        < div > @Html.ActionLink("Back to Details", "GetAllEmployees") < /div>   < hr / > @Html.ValidationSummary(true, "", new {@  
            class = "text-danger"  
        })@ Html.HiddenFor(model => model.Empid)  
  
    < div class = "form-group" > @Html.LabelFor(model => model.Name, htmlAttributes: new {@  
        class = "control-label col-md-2"  
    }) < div class = "col-md-10" > @Html.EditorFor(model => model.Name, new {  
        htmlAttributes = new {@  
            class = "form-control"  
        }  
    })@ Html.ValidationMessageFor(model => model.Name, "", new {@  
        class = "text-danger"  
    }) < /div>   < /div>    
  
    < div class = "form-group" > @Html.LabelFor(model => model.City, htmlAttributes: new {@  
        class = "control-label col-md-2"  
    }) < div class = "col-md-10" > @Html.EditorFor(model => model.City, new {  
        htmlAttributes = new {@  
            class = "form-control"  
        }  
    })@ Html.ValidationMessageFor(model => model.City, "", new {@  
        class = "text-danger"  
    }) < /div>   < /div>    
  
    < div class = "form-group" > @Html.LabelFor(model => model.Address, htmlAttributes: new {@  
        class = "control-label col-md-2"  
    }) < div class = "col-md-10" > @Html.EditorFor(model => model.Address, new {  
        htmlAttributes = new {@  
            class = "form-control"  
        }  
    })@ Html.ValidationMessageFor(model => model.Address, "", new {@  
        class = "text-danger"  
    }) < /div>   < /div>    
  
    < div class = "form-group" >  
        < div class = "col-md-offset-2 col-md-10" >  
        < input type = "submit"  
    value = "Update"  
    class = "btn btn-default" / >  
        < /div>   < /div>   < /div>    
} < script src = "~/Scripts/jquery-1.10.2.min.js" > < /script>   < script src = "~/Scripts/jquery.validate.min.js" > < /script>   < script src = "~/Scripts/jquery.validate.unobtrusive.min.js" > < /script>

مرحله 9:

Action Link را برای Edit و delete رکوردها پیکربندی کنید، مانند زیر:

 

ActionLink بالا را به GetAllEmpDetails.CsHtml مربوط بهview اضافه کردیم، چرا که خود لینک گزینه مورد نظر را  حدف کرده و رکوردها را به روز رسانی می کند.

مرحله 10:

RouteConfig.cs را به مجموعه ای از action ها پیش فرض تنظیم کنید، مانند قطعه کد زیر:

public class RouteConfig  
{  
   public static void RegisterRoutes(RouteCollection routes)  
   {  
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  
      routes.MapRoute(  
         name: "Default",  
         url: "{controller}/{action}/{id}",  
         defaults: new { controller = "Employee", action = "AddEmployee", id = UrlParameter.Optional }  
      );  
   }  
}  

 

از action پیش فرض  RouteConfig.cs بالا AddEmployee را تنظیم کرده ایم. این بدان معناست که بعد از اجرای برنامه AddEmployee مربوط بهview اول اجرا خواهد شد.

حالا بعد از اضافه کردن تمام مدل ها، view ها و controller در solution explorer به صورت شکل زیر خواهد شد:

مرحله 11: اجرای برنامه

حالا برنامه را اجرا کنید، AddEmployeمربوط به view به صورت شکل زیر نمایان می شود:

 

بر روی دکمه ذخیره کلیک کنید، اعتبار سنجی model state انجام می شود(به صورت زیر). برای هر اعتبار سنجی باید کلاس EmpModel.cs را تنظیم کنیم:

 

 

 

حالا جزییات را وارد کرده و بر روی ذخیره کلیک کنید.

 

رکوردها به پایگاه داده اضافه شده و صفحه زیر نمایان می شود:

 

می توانید مانند بالا رکوردهای دیگری نیز اضافه کنید.

اکنون بر روی کلید Edit یکی از رکوردها کلیک کرده و سپس به  مربوط به view ویرایش برگردانده خواهد شد، مانند شکل زیر:

 

 

حالا بر روی دکمه ذخیره کلیک کرده و رکوردها در بانک اطلاعاتی به روز خواهند شد.

بر روی لینک  بازگشت به جزییات"" کلیک کنید سپس به لیست جدول کارمندان بازگردانده خواهد شد که در آن رکوردها مانند زیر update شده اند:

 

 

حالا بر روی دکمه delete یکی از رکوردها کلیک کرده و بعد پنجره تایید زیر باز خواهد شد( ما این پیکر بندی را در ActionLink تنظیم کرده بودیم).

 

 

حالا بر روی دکمه OK کلیک کرده و سپس جدول لیست آپدیت شده کارمندان ایجاد خواهد شد.

 

توجه: اتصال پایگاه داده خود را در فایل web.config بسته به محل سرور پایگاه داده خود تنظیم کنید.

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

در کد Repository، به طور دستی connection را باز و بسته کردیم، هرچند که می توان به طور مستقیم connection string را به dapper بدون باز کردن آن پاس داد، زیرا dapper آن را به طور خودکار حساب خواهد کرد.

 

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