آموزش ASP.NET MVC5 – فصل۸

آموزش ASP.NET MVC5 – فصل۸

مشخصات مقاله

آموزش ASP.NET MVC5 – فصل۸

 آموزش ASP.NET MVC5 – فصل8 

 

در جلسه قبل نحوه نوشتن Attribute ها و استفاده از ActionFilter ها را یاد گرفتیم:

»»» مطالعه مقاله جلسه هفتم از سری آموزشی ASP.NET-MVC5

 

آموزش Entity Framework در ASP.NET-MVC

 

مبحث Entity Framework یا بطور خلاصه EF به سه بخش تقسیم می شود : Model First , Database First , Code First

آموزش EF-CodeFirst بخش اول

 

ما در این مقاله بخش سوم یعنی Code First را آموزش می دهیم. برای یادگیری سایر بخشها می توانید به وب سایت asp.net مراجعه کنید .

 

نصب نوگت Entity Framework:

برای شروع کار ، باید نوگت Entity Framework را نصب کنیم . بنابراین در گوگل سرچ میکنیم : Entity Framework Nuget و اولین لینکی که یافت می شود را کلیک کرده و وارد سایت www.nuget.org می شویم و دستور زیر را کپی کرده و در کنسول Nuget پیست میکنیم و Enter را می زنیم :

Install-Package EntityFramework

با اجرای این دستور ، آخرین ورژن Entity Framework نصب میشود .

یادآوری :

  • در ADO.NET سنتی ، به جمع DataTable ها DataSet میگفتند .
  • در Entity Framework ، از مجموعه Model یا Entity ها ، مفهوم DatabaseContext ایجاد می شود .

 

افزودن کلاس Person به فولدر Models:

روی فولدر Models راست کلیک کرده و add–>class را انتخاب میکنیم . نام کلاس را Person میگذاریم که مطابق شکل زیر دارای 4 فیلد است :

کلاس Person

تعریف کلاس DatabaseContext :

کلاس مهمی بنام DatabaseContext باید ایجاد کنیم که اطلاعات مدل های ایجاد شده در پروژه در آن قرار میگیرد . مانند شکل زیر این کلاس را تعریف میکنیم :

کلاس DatabaseContext

 

همانطور که می بینیم ، این کلاس باید از کلاس DbContext ارث بری کند :

public class DatabaseContext : System.Data.Entity.DbContext

تعریف مدل‌ها در کلاس DatabaseContext:

مدلهایی که مانند Person ایجاد کرده ایم را باید بصورت زیر در کلاس DatabaseContext تعریف کنیم :

public System.Data.Entity.DbSet<Person> People { get; set; }

یعنی به ازای هر مدل ، یک property در کلاس DatabaseContext تعریف میکنیم که از نوع کلاس DbSet می باشند و نام این property را معمولا اسم جمع همان مدل انتخاب میکنیم . مثلا برای Person –>People و برای User –>Users و …..

 

تعریف رشته اتصال (ConnectionString) به دیتابیس:

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

نحوه تعریف ConnectionString :

در فایل web.config تگ ConnectionString باید دقیقا بعد از تگ ConfigSections تعریف شود و به سه صورت زیر تعریف می شود :

<connectionstrings>
        <add name="DatabaseContext"
             connectionstring="Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=LEARNING_ADO_NET;Data Source=.\SQLExpress"
             providername="System.Data.SqlClient" />
        <add name="DatabaseContext" connectionstring="Password=1234512345;Persist Security Info=True;User ID=SA;Initial Catalog=LEARNING_ADO_NET;Data Source=.\SQLExpress" providername="System.Data.SqlClient" />
        <add name="DatabaseContext"
             connectionstring="Data Source=|DataDirectory|\MyDatabase.sdf"
             providername="System.Data.SqlServerCe.4.0" />
</connectionstrings>

 

  • روش اول : رشته اتصالی است به sqlServer به روش Windows Authentication
  • روش دوم : رشته اتصالی است به sqlServer به روش sqlServer Authentication
  • روش سوم : رشته اتصالی است برای وصل شدن به sqlServer Compact .

 

نکته مهم : نام رشته اتصال باید با نام کلاس DatabaseContext یکی باشد .

 

ایجاد دیتابیس در روش Code First :

در EntityFramework Code First ، دیتابیس بصورت زیر ایجاد می شود :

ایجاد دیتابیس

 

کد بالا در Windows Form Application نوشته شده است ولی در وب اپلیکیشن ها نیز مانند همین روش باید اجرا شود (در اکشن مربوطه) تا دیتابیس ایجاد شود و در نهایت شئ ایجاد شده را dispose میکنیم یعنی از حافظه دور می اندازیم تا به مرور زمان ، برنامه را دچار سنگینی نکند .

توضیح : همانطور که در تصویر فوق میبینیم ، ابتدا باید از هر دوی Person و DatabaseContext یک شئ بسازیم و سپس شئ person را مقداردهی کنیم و به شئ databaseContext نسبت دهیم . در این مرحله db ایجاد شده و جدول people نیز ساخته می شود .

طراحی جدول people:

جدول people بصورت زیر ایجاد شده است :

ایجاد جدول people

 

توضیح : فیلد Id بطور اتوماتیک ایجاد شده است و Primary Key و Auto Increment می باشد . فیلد Age بدلیل اینکه int است نمیتواند null باشد و fullname را nullable تعریف کرده است و isSupervisor نیز چون bit است نمیتواند null باشد .

بعد از اجرای دستور saveChanges ، رکورد مورد نظر در جدول people درج می شود .

به منظور تمرین بیشتر و تست معلومات خود درباره موضوع مهم EntityFramework میتوانید به وب سایت EntityframeworkTutorial مراجعه کنید .

 

ایجاد کلاس BaseEntity :

روی فولدر Models راست کلیک کرده و کلاسی اضافه میکنیم بنام BaseEntity.cs . این کلاس فیلدی بنام Id از جنس Guid دارد که در سازنده کلاس آنرا new میکنیم :

namespace Models { 
 public abstract class BaseEntity : System.Object { 
  public BaseEntity() { Id = System.Guid.NewGuid(); } 
  public System.Guid Id { get; set; } 
 } 
}

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

 

ایجاد جداول Role و User با رابطه یک به چند:

فرض کنید میخواهیم دو جدول بنامهای Role و User بسازیم که باهم رابطه یک به چند دارند . بدین معنی که هر Role میتواند یک یا چند User داشته باشد ولی هر User فقط میتواند یک Role داشته باشد .

ایجاد جدول Role :

فیلدهای جدول Role عبارتند از : نام role و لیستی از user ها (فیلد Id نیز در تمام جداول وجود دارد) .

اجباری کردن فیلد Name:

همانطور که میدانید نوع داده ای رشته (String) میتواند null باشد . ما میتوانیم توسط attribute ها ، فیلد Name را required کنیم (در واقع تیک nullable بودن را از فیلد نام برداریم) :

[System.ComponentModel.DataAnnotations.Required
(AllowEmptyStrings = false)]

اتریبیوت AllowEmptyStrings نیز null string بودن Name را چک میکند .

تعیین حداقل-حداکثر طول رشته توسط attribute:

همچنین میتوان طول رشته (حداقل-حداکثر) را توسط attribute ها تعیین کرد :

[System.ComponentModel.DataAnnotations.StringLength
(maximumLength: 50)]

بنابراین کلاس Role بصورت زیر می باشد :

namespace Models {
 public class Role : BaseEntity {
  public Role(){}

  [System.ComponentModel.DataAnnotations.Required
  (AllowEmptyStrings = false)]

  [System.ComponentModel.DataAnnotations.StringLength
  (maximumLength: 50)]
  public string Name { get; set; }
  
  public virtual System.Collections.Generic.IList<user> Users { get; set; }
 }
}

 

با دستور public class Role : BaseEntity میگوییم کلاس Role از کلاس BaseEntity که قبلا نوشتیم ارث ببرد .

 

ایجاد جدول User :

جدول User دارای فیلدهای متعددی است که بصورت زیر می باشد :

  • IsActive از نوع boolean
  • Age از نوع int که محدوده سنی بین 25 تا 35 را فقط شامل می شود .
  • Username از نوع string که فیلد ضروریست و طولش بین 6 تا 20 کاراکتر است .
  • Password از نوع string که فیلد اجباریست و طولش بین 8 تا 20 کاراکتر است .
  • FullName از نوع string که طول رشته اش بین 3 تا 50 کاراکتر و اجباریست .
  • Description از نوع string که نوشتن آن اجباری نیست و میتواند تگ html داشته باشد (Rich Text) .

 

سورس کد کلاس User:

کد کامل کلاس User بصورت زیر می باشد :

namespace Models
{
    public class User : BaseEntity
    {
        public User()
        {
        }
        public virtual Role Role { get; set; }
        public System.Guid RoleId { get; set; }
        // **********
        public bool IsActive { get; set; }
        // **********
        // **********
        [System.ComponentModel.DataAnnotations.Range
            (type: typeof(int), minimum: "25", maximum: "35")]
        public int Age { get; set; }
        // **********
        [System.ComponentModel.DataAnnotations.Required
            (AllowEmptyStrings = false)]
        [System.ComponentModel.DataAnnotations.StringLength
            (maximumLength: 20, MinimumLength = 6)]
        public string Username { get; set; }
        // **********
        [System.ComponentModel.DataAnnotations.Required
            (AllowEmptyStrings = false)]
        [System.ComponentModel.DataAnnotations.StringLength
            (maximumLength: 20, MinimumLength = 8)]
        [System.ComponentModel.DataAnnotations.DataType
            (System.ComponentModel.DataAnnotations.DataType.Password)]
        public string Password { get; set; }
        // **********
        [System.ComponentModel.DataAnnotations.Required
            (AllowEmptyStrings = false)]
        [System.ComponentModel.DataAnnotations.StringLength
            (maximumLength: 50, MinimumLength = 3)]
        public string FullName { get; set; }
        // **********
        [System.Web.Mvc.AllowHtml]
        [System.ComponentModel.DataAnnotations.DataType
            (System.ComponentModel.DataAnnotations.DataType.MultilineText)]
        public string Description { get; set; }
        // **********
    }
}

دو فیلد Role و RoleId که در ابتدای کلاس تعریف شده اند بدین خاطر می باشند که رابطه یک به چند بین جداول Role و User را پیاده سازی کنند .

کلاس مهم دیگری که باقی می ماند DatabaseContext می باشد . این کلاس باید از DbContext ارث ببرد و دو property برای جداول user , role نیز داشته باشد :

public System.Data.Entity.DbSet<role> Roles { get; set; }
public System.Data.Entity.DbSet<user> Users { get; set; }

ایجاد کلاس DatabaseContext :

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

static DatabaseContext()
{
 // فقط به درد برنامه نویسان آن هم در زمان پیاده سازی می خورد
 System.Data.Entity.Database.SetInitializer
 (new System.Data.Entity.DropCreateDatabaseIfModelChanges<databasecontext>());
 // برای تحویل به مشتری مناسب است
 //System.Data.Entity.Database.SetInitializer
 //    (new System.Data.Entity.CreateDatabaseIfNotExists<databasecontext>());
}

 

  • روش اول میگوید اگر مدلی از دیتابیس تغییر کرد (و یا مدلی حذف یا اضافه شد) دیتابیس را پاک میکند و بعد از اعمال تغییرات دوباره می سازد .
  • روش دوم بدین معنیست که اگر دیتابیس وجود نداشت آنرا میسازد وگرنه کاری به دیتابیس ندارد (برای تحویل پروزه به کلاینت مناسب است) .

 

برای یادگیری و تمرین بیشتر به وب سایت asp.net مراجعه شود .

 

ایجاد View های لازم جهت 4 عمل اصلی CRUD:

در این بخش میخواهیم view های لازم برای 4 عمل اصلی CRUD را بطور اتوماتیک ایجاد کنیم . برای اینکار روی فولدر Controllers راست کلیک کرده و Add–>Controller را انتخاب میکنیم . در این مرحله با تصویر زیر مواجه می شویم :

MVC5-Views-Using EF

 

ایجاد کنترلر RoleController:

مطابق شکل ، گزینه MVC5 Controller with views Using EntityFramework را انتخاب میکنیم و در مرحله بعد ، مطابق تصویر زیر ، Model Class را Role انتخاب میکنیم و Data Context Class را برابر DatabaseContext قرار میدهیم و تیک Generate views , use layout را میزنیم و در نهایت نام کنترولر را RoleController تایپ میکنیم و Add را می زنیم :

تولید view بطور خودکار

 

ایجاد View های Index , Edit , Delete , Create , Detail:

با زدن دکمه Add ، کنترولر Role با تمام view های Index , Edit , Delete , Create , Detail و اکشن های مرتبط ، اتوماتیک ایجاد می شوند .

در view های تولید شده با توجه به مدل Role که قبلا تعریف کردیم به Textbox ها validation اختصاص داده می شود ، مثلا اگر فیلدی required باشد هنگام اجرای Create و زدن دکمه Create با پیغام the field is required مواجه می شویم :

Create View

 

نکته : با اینکه کدهای اکشن های مختلف کنترولر RoleController بدرستی کار میکنند و همچنین View های ایجاد شده توسط مایکروسافت بدون خطا کار میکنند ولی ما میخواهیم View های زیباتری داشته باشیم و نیز کدهای cSharp , Linq که در اکشن های مختلف نوشته شده اند هوشمندانه تر شوند یک سری مراحلی باید طی کنیم .

مثال برای View : در View مربوط به create role ، دکمه درج در دیتابیس استایل خاصی ندارد . ما میخواهیم مثلا استایل btn-primary به آن بدهیم .

مثال برای Action : در اکشن مربوط به Index که لیستی از Role ها را نمایش میدهد ، کد موجود به صورت زیر است :

return View(db.Roles.ToList());

ولی آنچه که ما میخواهیم ، مرتب شده رول ها بر اساس نام آنها می باشد .

نکته : برای تمرین بیشتر و مشاهده مثالهای پیشرفته تر به وب سایت codeProject مراجعه شود.

در بخش بعد قصد داریم عملیات مرتب سازی و هوشمندسازی کد ها را شروع کنیم . همراه ما باشید …

در بخش قبل با نحوه تولید اتوماتیک view ها و اکشن های مربوط به یک مدل آشنا شدیم . در این بخش قصد داریم کدهای تولید شده را زیباتر و هوشمندانه تر کنیم .

 

تعریف کلاس BaseController:

ابتدا یک کلاس بنام BaseController تعریف میکنیم تا از این به بعد تمام کنترولرهای ما از آن ارث ببرند . برای اینکار روی فولدر Infrastructure راست کلیک کرده و add > class را انتخاب میکنیم . نام کلاس را BaseController قرار میدهیم :

namespace Infrastructure { 
 public class BaseController : System.Web.Mvc.Controller { 
  public BaseController() { } 
  private Models.DatabaseContext _databaseContext; 
  protected Models.DatabaseContext DatabaseContext { 
   get {
    if (_databaseContext == null) { 
    _databaseContext = new Models.DatabaseContext(); 
    } 
    return (_databaseContext); 
   } 
  } 
  protected override void Dispose(bool disposing) { 
    if (disposing) { 
     if (_databaseContext != null) { 
      _databaseContext.Dispose();
       _databaseContext = null; 
      } 
    } base.Dispose(disposing); 
  } 
 } 
}

 

توضیح کلاس BaseController: ابتدا متغیر private از نوع مدل DatabaseContext تعریف میکنیم و سپس یک property با همان نوع DatabaseContext تعریف میکنیم که readOnly می باشد یعنی فقط متد get دارد . شرط if در property می گوید اگر متغیر null بود آنرا new کن وگرنه همان را return کن .

بنابراین با ایجاد این کلاس ، تمام کنترولرهای ایجاد شده را بصورت زیر از کلاس BaseController ارث بری میکنیم :

public partial class RoleController : BaseController

عملیات CRUD

اکشن Index کنترولر RoleController :

کد اکشن فوق بطور پیش فرض بصورت است :

public ActionResult Index() { 
 return View(db.Roles.ToList()); 
}

و کد بهینه سازی شده و هوشمندانه بدین صورت :

public ActionResult Index() { 
 var varRoles = DatabaseContext.Roles .OrderBy(current => current.Name) .ToList(); 
 return (View(model: varRoles)); 
}

همانطور که میبینیم روش دوم قدرت مانور بیشتری نسبت به اولی دارد (می توان از دستورات Where , Orderby در آن استفاده کرد)

سفارشی سازی Index View :

ویوی تولید شده پیش فرض برای اکشن Index (نمایش لیست رول ها) بصورت زیر است :

@model IEnumerable<models.role>
@{ViewBag.Title = "Index";}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")</p>
    @foreach (var item in Model) {
}
<table class="table">
 <tbody>
  <th>
   @Html.DisplayNameFor(model => model.Name)
  </th>
 <tr>
  <td>
   @Html.DisplayFor(modelItem => item.Name)
  </td>
  <td>
   @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
   @Html.ActionLink("Details", "Details", new { id=item.Id }) |
   @Html.ActionLink("Delete", "Delete", new { id=item.Id })
  </td>
 </tr>
 </tbody>
</table>

 

همانطور که قبلا گفتیم این کد نیز بدرستی کار میکند ولی ما قصد داریم ویوی زیباتری داشته باشیم . پس ویوی فوق را بصورت زیر تغییر میدهیم (که در آن به جدول موجود ، استایل بوت استرپی دادیم واز نوگت T4MVC استفاده کردیم که نام اکشن را StronglyTyped میکند) :

@model IEnumerable<models.role>
@{string strTitle = "Roles List";ViewBag.Title = strTitle;}
<h2>@strTitle</h2>
<div class="links">
@Html.ActionLink("Create New Role", MVC.Role.Create())</div>
<div class="table-responsive">
@foreach (Models.Role oCurrentRole in Model)
{<table class="table table-bordered table-condensed table-hover table-striped">
<tbody><tr><td> </td></tr></tbody><tbody><tr><td> </td><th> </th><td> </td><th>
@Html.DisplayNameFor(model => model.Name)</th><td> </td></tr><tr><td> </td><td>
@Html.ActionLink("Details", MVC.Role.Details(oCurrentRole.Id)) |
@Html.ActionLink("Edit", MVC.Role.Edit(oCurrentRole.Id)) |
@Html.ActionLink("Delete", MVC.Role.Delete(oCurrentRole.Id))</td><td> </td><td>
@Html.DisplayFor(modelItem => oCurrentRole.Name)</td><td> </td></tr></tbody></table></div>

 

توضیح دستور زیر :

 @Html.DisplayNameFor(model => model.Name)

برای نمایش نام اختصاص داده شده در مدل بکار میرود . اگر نامی برای این فیلد تعریف نکرده باشیم همان Name را نمایش میدهد . نحوه تعریف کردن نام نمایشی دلخواه برای یک فیلد ، بصورت Attribute در مدل می باشد :

[System.ComponentModel.DataAnnotations.Display (Name="Role Name")] 
public string Name { get; set; }

تا بدین جا ، اکشن Index بهمراه View متناظرش را سفارشی سازی کردیم . به همین ترتیب می توان اکشن های Delete , Edit , Insert را بهمراه ویوهای آنها ، مرتب و بهینه سازی کنیم . برای تمرین بیشتر ، به وب سایت asp.net مراجعه کنید .

جلسه هشتم (آموزش Linq to EF code first) در اینجا به پایان میرسد . دوستان عزیز لطفا دیدگاه های خود را درباره این مقالات اعلام نمایید .

در جلسه بعد با Validation ها آشنا می شویم . همراه ما باشید …

0/5 (0 نظر)

اطلاعات مقاله

آموزش ASP.NET MVC5 – فصل۸

فرم ارسال دیدگاه درباره

آموزش ASP.NET MVC5 – فصل۸

دیدگاه کاربران درباره

آموزش ASP.NET MVC5 – فصل۸

دیدگاهی وجود ندارد