در مقاله ی حاضر پروژه ی یک وب سایت ساده متعلق به دانشگاه ساختگی Contoso را مورد بررسی قرار می دهیم.
در این برنامه ی تحت وب، کاربران می توانند دانشجویان، دوره های آموزشی و اطلاعات اساتید را مشاهده و بروز رسانی کنند.
در نوشتن سبک رابط کاربری (UI Style) این برنامه سعی شده، آن را تا حد امکان شبیه به خروجی قالب های درون ساخته (آنچه توسط Built-in template ها ایجاد می شود) نگه داریم تا بتوان تمرکز را بیشتر بر روی نحوه ی استفاده از تکنولوژی EFگذاشت.
ساخت یک برنامه ی تحت وب MVC
Visual Studio را راه اندازی کرده و یک تحت پروژه ی وب C# به نام "ContosoUniversity" ایجاد کنید.
در پنجره ی محاوره ی New ASP.NET Project، قالب MVC را انتخاب نمایید.
اگر چک باکس Host in the cloud در قسمت Microsoft Azure از قبل انتخاب شده، تیک آن را بردارید.
Change Authentication را انتخاب کنید.
در پنجره ی محاوره ی Change Authentication، No Authentication را انتخاب نمایید و سپس OK را کلیک کنید. برای برنامه ی که آموزش ساخت آن را در مقاله ی آموزشی حاضر می آموزیم، کاربر را ایجاب به ثبت ورود (login) نخواهیم کرد و دسترسی را بر اساس اینکه کدام کاربر وارد شده محدود نخواهیم ساخت.
در پنجره ی محاوره ی New ASP.NET Project، OK را کلیک کرده تا پروژه مورد نیاز ایجاد گردد.
تنظیم استایل سایت
با اعمال چندین تغییر ساده می توان منو، layout (طرح) و صفحه ی اصلی سایت را راه اندازی کرد.
فایل Views\Shared\_Layout.cshtml را باز کرده و تغییرات زیر را اعمال کنید:
1. هر یک از نمونه های "My ASP.NET Application" و "Application name" را به "Contoso University" تغییر دهید.
2. آیتم های لازم را برای هر یک از ورودی های Students، Courses، Instructors و Departments در منو اضافه نموده، سپس ورودی Contact را حذف نمایید.
همان طور که مشاهده می کنید، تغییرات در زیر رنگی شده اند:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Contoso University</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Contoso University", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
<div class="nav-collapse collapse">
<ul class="nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Students", "Index", "Student")</li>
<li>@Html.ActionLink("Courses", "Index", "Course")</li>
<li>@Html.ActionLink("Instructors", "Index", "Instructor")</li>
<li>@Html.ActionLink("Departments", "Index", "Department")</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - Contoso University</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>
در فایل Views\Home\Index.cshtml، محتویات صفحه را با کد زیر جایگزین کرده تا بتوان متن درباره ی ASP.NET و MVC را با متن درباره ی این برنامه جایگزین کرد:
@{
ViewBag.Title = "Home Page";
}
<div class="jumbotron">
<h1>Contoso University</h1>
</div>
<div class="row">
<div class="col-md-4">
<h2>Welcome to Contoso University</h2>
<p>
Contoso University is a sample application that
demonstrates how to use Entity Framework 6 in an
ASP.NET MVC 5 web application.
</p>
</div>
<div class="col-md-4">
<h2>Build it from scratch</h2>
<p>You can build the application by following the steps in the tutorial series on the ASP.NET site.</p>
<p><a class="btn btn-default" href="http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/">See the tutorial »</a></p>
</div>
<div class="col-md-4">
<h2>Download it</h2>
<p>You can download the completed project from the Microsoft Code Gallery.</p>
<p><a class="btn btn-default" href="http://code.msdn.microsoft.com/ASPNET-MVC-Application-b01a9fe8">Download»</a></p>
</div>
</div>
کلیدهای CTRL+F5 را همزمان فشار داده تا سایت اجرا شود. صفحه ی اصلی (home page) را به همراه منوی اصلی مشاهده می کنید:
نصب Entity Framework 6
از منو Tools، NuGet Package Manager را انتخاب کرده، سپس Package Manager Console را کلیک نمایید.
در پنجره ی Package Manager Console، دستور زیر را وارد نمایید:
Install-Package EntityFramework
تصویر فوق ویرایش EF 6 را در حال نصب نمایش می دهد. سرویس NuGet آخرین ویرایش EF (به استثنای نسخه نهایی) را نصب می کند که از زمان آخرین بروز رسانی این آموزش 6.1.1 می باشد.
این گام از آموزش، یکی از بخش هاست که به صورت دستی نحوه ی نصب EF را به شما آموزش می دهد. این گام توسط قابلیت scaffolding ASP.NET MVC به صورت خودکار نیز انجام می پذیرد. بخش حاضر را به این خاطر به صورت دستی انجام می دهیم تا شما بتوانید مراحل لازم برای استفاده از EF را مشاهده کرده و بیاموزید. در فصل های بعدی، controller و viewهای MVC را با استفاده از قابلیت scaffolding ایجاد خواهیم کرد.
یا به روشی دیگر می توانید به scaffolding اجازه دهید، پکیج EF NuGet را به صورت خودکار نصب، کلاس database contextرا ایجاد کرده و connection string را بسازد. در صورت تمایل به استفاده از روش دوم ، تنها کاری که باید انجام دهید این است که تمامی مراحل لازم برای نصب دستی را نادیده گرفته و بلافاصله کلاس های entity خود را ایجاد کنید.
ایجاد Data Model
حال به ایجاد کلاس های entity برای برنامه ی Contoso University خواهیم پرداخت. کار خود را با سه ورودی زیر آغاز می کنیم:
بین entity های (موجودیت) Student و Enrollment و همچنین بین Course و Enrollment یک رابطه ی یک به چند وجود دارد. به عبارتی دیگر، یک دانشجو (student) می تواند در چند دوره ی آموزشی (course) ثبت نام کند و نیز یک دوره ی آموزشی می تواند تعدادی دانشجو داشته باشد که در آن ثبت کرده اند.
در بخش های زیر به ازای هر یک از entity ها یک کلاس ایجاد می کنیم.
توجه: چنانچه پیش از اینکه تمامی کلاس های entity را ایجاد کرده باشید، اقدام به کامپایل پروژه بکنید، با خطاهایی مربوط به compiler مواجه می شوید.
در پوشه ی Models، یک class file به نام Student.cs ایجاد کرده و کد template را با کد زیر جایگزین نمایید:
using System;
using System.Collections.Generic;
namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
خاصیت ID ستون کلید اصلی (primary key column) جدول پایگاه داده خواهد بود که با این کلاس متناظر می باشد. به صورت پیش فرض، EF خاصیتی (propery) که ID یا classnameID نام گذاری شده را به عنوان کلید اصلی شناخته و تفسیر می کند.
خاصیت Enrollments، درواقع یک navigation property است. navigation property ها موجودیت های دیگر را نگه می دارند که به این entity مربوط می باشند. در این نمونه، خاصیت Enrollments موجودیت Student ، تمامی موجودیت هایEnrollments که مربوط به Student هستند را نگه می دارد. به عبارتی دیگر، اگر یک سطر به خصوص از موجودیت Student در پایگاه داده ی مورد نظر دارای دو سطر مربوطه ی Enrollments باشد (سطرهایی که دربردارنده ی مقدار کلید اصلی (primary key value) student در ستون کلید خارجی StudentID (foreign key column) هستند)، Enrollments navigation propertyموجودیت آن Student، دربردارنده ی آن دو موجودیت Enrollment خواهد بود.
Navigation property ها معمولا با کلیدواژه ی virtual تعریف می شوند، تا بدین وسیله بتوانند از برخی از قابلیت های EFهمچون lazy loading (بارگذاری با تاخیر) بهره بگیرند.
اگر یک navigation property بتواند به طور همزمان چندین entity را نگه دارد (مانند آنچه در رابطه ی چند به چند یا یک به چند اتفاق می افتد)، در آن صورت، navigation property بایستی از نوع لیست باشد تا بتوان ورودی هایی را به آن اضافه، بروز رسانی کرد یا در صورت لزوم حذف نمود مانند ICollection.
در پوشه ی Models، فایل Enrollment.cs را ایجاد کرده و کد موجود را با کد زیر جایگزین نمایید:
namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}
public class Enrollment
{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }
public virtual Course Course { get; set; }
public virtual Student Student { get; set; }
}
}
خاصیت EnrollmentID کلید اصلی (primary key) خواهد بود؛ این entity بجای ID به تنهایی، از الگوی classnameIDاستفاده می کند، همان طور که در موجودیت Student مشاهده گر آن بودید. به طور معمول یک الگو را انتخاب می کنیم و آن را در کل data model خود بکار می بریم. در اینجا، تغییر کوچکی که مشاهده کردید، نشانگر این است که می توان از هر دو الگو استفاده کرد.
خاصیت Grade ورودی از نوع شمارشی (enum) می پذیرد. علامت سوال پس از تعریف نوع Grade، بر این قضیه اشاره دارد که خاصیت Grade، nullable می باشد. لازم به ذکر است یک نمره (grade) که null یا تهی می باشد، از نمره ی صفر کاملا متفاوت است – null بیانگر این است که آن grade تعریف نشده یا هنوز مقداری به آن تخصیص نیافته است.
خاصیت StudentID یک کلید خارجی است و navigation property متناظر با آن Student می باشد. یک entity یا موجودیتEnrollment به یک Student مربوط می باشد، بنابراین خاصیت مورد نظر تنها می تواند یک موجودیت Student را نگه دارد (بر خلاف Student.Enrollments navigation property که کمی پیشتر مشاهده کردید که قادر است چندین موجودیتEnrollment نگه دارد.)
خاصیت CourseID یک کلید خارجی است و navigation property مربوط با آن نیز Course می باشد. یک موجودیتEnrollment تنها به یک موجودیت Course مربوط یا متصل می باشد.
EF، در صورتی که خاصیتی <navigation property name><primary key property name> نام گذاری شده باشد، آن خاصیت را به عنوان یک خاصیت کلید خارجی (foreign key property) تفسیر می کند (به عنوان مثال، StudentID برایStudent navigation property زیرا که کلید اصلی موجودیت Student، ID می باشد). همین کار را می توان برای خاصیت های کلید خارجی (Foreign key properties) نیز انجام داد، <primary key property name> (به عنوان مثال، CourseID زیرا که کلید اصلی موجودیتCourse ، CourseIDمی باشد ).
در پوشه ی Models، Course.cs را ایجاد کرده و کد template را با کد زیر جایگزین کنید:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
خاصیت Enrollments یک navigation property می باشد. یک موجودیت Course ممکن است به چندین موجودیتEnrollment مربوط باشد.
بعده ها درباره ی خصیصه ی DatabaseGenerated بیشتر بحث خواهیم کرد. خصیصه ی نام برده اساسا به شما اجازه می دهد بجای اینکه کاری کنید پایگاه داده کلید اصلی را خود بسازد آن را برای course مورد نظر وارد نمایید.
ایجاد Database Context
کلاس اصلی که قابلیت EF را برای یک data model معین هماهنگ سازی می کند، کلاس database context است. کلاس ذکر شده را با ارث بری از کلاس System.Data.Entity.DbContext ایجاد می کنیم. در کد خود مشخص می کنیم کدام entity ها درdata model گنجانده شوند، حتی می توانید برخی از رفتارهای EF را سفارشی تنظیم کنید. در این پروژه اسم کلاس راSchoolContext انتخاب می کنیم.
به منظور ایجاد یک پوشه در پروژه ی ContosoUniversity، بر روی پروژه در پنجره ی Solution Explorer راست کلیک کرده وAdd را کلیک کنید. سپس بر روی New Folder کلیک نمایید. پوشه ی جدید را DAL (Data Access Layer) نام گذاری کنید. در آن پوشه یک فایل کلاس جدید به نام SchoolContext.cs ایجاد کرده و کد template را با کد زیر جایگزین کنید:
using ContosoUniversity.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace ContosoUniversity.DAL
{
public class SchoolContext : DbContext
{
public SchoolContext()
: base("SchoolContext")
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Course> Courses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
تعریف entity set ها (مجموعه ای از جداول)
این کد یک خاصیت DbSet ویژه ی هر entity set ایجاد می کند. در EF منظور از entity set همان جدول در پایگاه داده و entityنیز یک سطر یا ردیف از جدول است.
اگر دستورهای DbSet < Enrollment>و DbSet<Course> را هم حذف کنید باز در روند اجرا هیچ تغییر اتفاق نمی افتاد. EF آن ها را به صورت ضمنی مورد ارجاع قرار می داد (اضافه می کرد)، به این ترتیب که موجودیت Student به موجودیتEnrollment اشاره می کند و موجودیت Enrollment نیز به موجودیت Course اشاره می کند.
تعریف connection string
اسم connection string (که بعدا آن را به فایل Web.config اضافه خواهیم کرد) به constructor ارسال می شود.
public SchoolContext() : base("SchoolContext")
{
}
همچنین می توانستید بجای اسم connection string که در فایل Web.config ذخیره می شود، خود connection string را بهconstructor ارسال نمایید.
اگر یک connection string معین یا اسم connection string را به صورت صریح تعریف نکنید، EF فرض می گیرد که اسمconnection string با اسم کلاس یکی است. اسم پیش فرض connection string در این مثال، SchoolContext خواهد بود، یکسان با آنچه به صورت صریح تعریف می کنید.
تعریف اسامی جدول به صورت فردی و جمعی
دستور modelBuilder.Conventions.Remove در متد OnModelCreating مانع از این می شود که اسامی جدول به صورت جمعی تعریف شوند. اگر این کار نمی کردیم، جداول ایجاد شده به ترتیب Students، Courses و Enrollments نام گذاری می شدند. با استفاده از این دستور، اسامی جداول Student، Course و Enrollment به صورت فردی و بدون s جمع نام گذاری شده اند. برنامه نویسان در رابطه با اینکه آیا اسم جداول به صورت جمعی تعریف شوند یا فردی، اختلاف نظر دارند. در مقاله ی حاضر از اسم فردی برای جداول بهره گرفته شده، اما شما می توانید مطابق میل خود با اضافه یا حذف کردن این خط کد، اسم جدول را فرد یا جمع تعریف کنید.
تنظیمEF جهت مقداردهی اولیه پایگاه داده با داده های آزمایش
EF قادر است هنگامی که برنامه اجرا می شود به صورت خودکار یک پایگاه داده را ایجاد (یا حذف و مجدد ایجاد) کند. این امکان برای شما وجود دارد که مشخص کنید آیا هر بار که برنامه اجرا می شود، پایگاه داده خودکار ایجاد گردد یا فقط زمانی کهmodel با پایگاه داده ی موجود همگام نیست، این اتفاق رخ دهد. همچنین می توانید یک متد Seed بنویسید که EF خودکار پس از ایجاد کردن پایگاه داده صدا می زند و به وسیله آن پایگاه داده ی مورد نظر را با داده های آزمایشی پر می کند.
در حالت پیش فرض تنها زمانی یک پایگاه داده ایجاد می شود که از قبل موجود نباشد (و در صورت تغییر یافتن model و موجود پایگاه داده پیام خطا صادر شود). در این بخش ما تعریف می کنیم که پایگاه داده با هر بار تغییر model، حذف و مجدد ایجاد شود. حذف پایگاه داده، از دست رفت داده ها را به دنبال دارد. این امر، حین برنامه نویسی و توسعه مشکلی را بوجود نمی آورد، زیرا متد Seed زمانی که پایگاه داده بازسازی می شود، اجرا شده و داده های آزمایشی شما را بار دیگر ایجاد می کند. اما طی فرایند تولید(production)، از دست رفت اطلاعات هر بار که schema ی پایگاه داده را تغییر می دهید، ملال آور خواهد بود.
در پوشه ی DAL، یک فایل کلاس جدید به نام SchoolInitializer.cs ایجاد کرده و کد template را با کد زیر جایگزین کنید. این کار باعث می شود پایگاه داده در صورت نیاز ایجاد شده و داده های آزمایشی در پایگاه داده ی جدید بارگذاری شوند.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using ContosoUniversity.Models;
namespace ContosoUniversity.DAL
{
public class SchoolInitializer : System.Data.Entity. DropCreateDatabaseIfModelChanges<SchoolContext>
{
protected override void Seed(SchoolContext context)
{
var students = new List<Student>
{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-0901")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
};
students.ForEach(s => context.Students.Add(s));
context.SaveChanges();
var courses = new List<Course>
{
new Course{CourseID=1050,Title="Chemistry",Credits=3,},
new Course{CourseID=4022,Title="Microeconomics",Credits=3,},
new Course{CourseID=4041,Title="Macroeconomics",Credits=3,},
new Course{CourseID=1045,Title="Calculus",Credits=4,},
new Course{CourseID=3141,Title="Trigonometry",Credits=4,},
new Course{CourseID=2021,Title="Composition",Credits=3,},
new Course{CourseID=2042,Title="Literature",Credits=4,}
};
courses.ForEach(s => context.Courses.Add(s));
context.SaveChanges();
var enrollments = new List<Enrollment>
{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050,},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
enrollments.ForEach(s => context.Enrollments.Add(s));
context.SaveChanges();
}
}
}
متد Seed، شی database context را به عنوان پارامتر ورودی می پذیرد، کد داخل متد به وسیله ی آن شی entity های جدید را به پایگاه داده اضافه می کند. به ازای هر entity type، کد یک مجموعه ی جدید از entity ها را ایجاد کرده و آن ها را به خاصیت DbSet مربوطه اضافه می کند، سپس تغییرات ایجاد شده را در پایگاه داده ذخیره می کند. ضرورتی ندارد متدSaveChanges را بعد از هر مجموعه entity (همان گونه که در این آموزش صورت گرفته) فراخوانی کرد. با این حال، انجام آن به شما کمک می کند در صورت رخداد خطا زمانی که کد در حال نوشته شدن در پایگاه داده هست، منشا یک مشکل را شناسایی کنید.
برای اینکه به EF دستور دهید از initializer class شما استفاده کند، یک المان را به عنصر entityFramework در فایلWeb.config (موجود در root folder پروژه) اضافه نمایید:
<entityFramework>
<contexts>
<context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">
<databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />
</context>
</contexts>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
context type
اسم کلاس context که به صورت کامل تعریف شده را به همراه assembly ای که در آن جای گرفته مشخص می کند. databaseinitializer type اسم کلاس initializer که به طور کامل تعریف شده را به همراه assembly ای که در آن قرار گرفته، مشخص می کند. (اگر نمی خواهید که EF از initializer استفاده کند، می توانید خصیصه ی disableDatabaseInitialization="true"را بر روی المان context تعریف کنید)
یک روش جایگزین برای تنظیم initializer در فایل Web.config، تنظیم آن در کد با اضافه کردن یک دستورDatabase.SetInitializer به متد Application_Start در فایل Global.asax.cs است.
اکنون برنامه به گونه ای تنظیم شده، که هنگامی که شما برای بار نخست در یکبار اجرای برنامه به پایگاه داده دسترسی پیدا می کنید، EF پایگاه داده را با model (SchoolContext و کلاس های entity) مقایسه می کند و در صورت برخورد با هر گونه تفاوت بین این دو، پایگاه داده را حذف کرده و آن را مجدد ایجاد می کند.
توجه: هنگامی که شما برنامه را روی web server تولیدی خود مستقر می کنید، بایستی کدی را که پایگاه داده را حذف و بازسازی می کند، غیر فعال نمایید.
تنظیم EF برای استفاده از یک نسخه ی LocalDB پایگاه داده ی SQL Server Express
LocalDB یک نسخه ی کم حجم از موتور پایگاه داده ی SQL Server Express است. نصب و پیکربندی آن بسیار ساده می باشد، به مجرد تقاضا و بنا به درخواست آغاز شده و در حالت user mode اجرا می شود. LocalDB در یک حالت اجرایی ویژه ازSQL Server Express اجرا می شود که به شما این امکان را می دهد، با پایگاه های داده مانند فایل های .mdf برخورد کنید.
اگر می خواهید پایگاه داده را همراه با پروژه کپی کنید، می توانید فایل های پایگاه داده ی LocalDB را در پوشه ی App_Data یک پروژه ی وب جای گذاری نمایید. امکان user instance در SQL Server Express نیر به شما اجازه می دهد با فایل های.mdf کار کنید، اما استفاده از این امکان توصیه نمی شود، بنابراین تنها LocalDB مناسب کار با فایل های .mdf می باشد. در ویرایش 2012 و جدیدتر Visual Studio، LocalDB به صورت پیش فرض توسط خود محیط نصب می شود.
به طور معمول SQL Server Express، به خصوص نسخه ی LocalDB آن برای برنامه های تولیدی تحت وب (production web applications) مورد استفاده قرار نمی گیرد (و برای کار با برنامه های تحت وب مناسب نمی باشد)، زیرا که نسخه ی ذکر شده اساسا برای کار با IIS طراحی نشده.
در این آموزش با LocalDB کار خواهیم کرد. فایل برنامه ی Web.config را باز کرده و یک المان connectionStrings پیش از المان appSettings اضافه نمایید. (فایل Web.config را حتما در root folder پروژه بروز رسانی کنید. البته یک فایلWeb.config دیگر در زیرپوشه ی Views وجود دارد که نیاز به بروز رسانی آن نیست.)
در صورت استفاده از Visual Studio 2015، لازم است به این خاطر که اسم پیش فرض نمونه ی SQL Server تغییر یافته، "v11.0" را داخل connection string با "MSSQLLocalDB" جایگزین کنید.
<connectionStrings>
<add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ContosoUniversity1;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Connection
string ای که اضافه کردید، تعریف می کند که EF از یک پایگاه داده ی LocalDB به نامContosoUniversity1.mdf استفاده کند.(پایگاه داده ای هنوز ایجاد نشده؛ ولی EF آن را ایجاد می کند.) اگر می خواستید پایگاه داده در پوشه ی App_Data ایجاد شود، در آن صورت می بایستAttachDBFilename=|DataDirectory|\ContosoUniversity1.mdf را به connection string اضافه می کردید.
لزومی ندارد در فایل Web.config، یک connection string ایجاد کنید. در صورت فراهم نکردن connection string، EF بر اساس کلاس context شما، از یک connection string پیش فرض استفاده می کند.
ایجاد یک controller و views به نام Student
اکنون یک صفحه ی وب خواهیم ساخت که داده های ما را نمایش می دهد، فرایند درخواست داده به صورت خودکار پروسه ی ساخت پایگاه داده را فعال می کند. کار خود را با ایجاد یک controller آغاز خواهیم کرد. اما پیش از آن باید پروژه را کامپایل کرده (build) تا کلاس های model و context در اختیار MVC controller scaffolding قرار گیرد.
1. بر روی پوشه ی Controllers در Solution Explorer راست کلیک کرده، Add را انتخاب کنید، سپس New Scaffolded Item را کلیک نمایید.
2. در پنجره ی محاوره ی Add Scaffold، MVC 5 Controller with views, using Entity Framework را انتخاب نمایید.
3. در پنجره ی محاوره ی Add Controller، به ترتیب زیر اقدام کنید:
Model class: Student (ContosoUniversity.Models )
Data context class: SchoolContext (ContosoUniversity.DAL )
Controller name: StudentController
مقادیر فیلدهای دیگر را تغییر ندهید.
هنگامی که بر روی Add کلیک می کنید، scaffolder یک فایل StudentController.cs و مجموعه ای از view ها (فایل های.cshtml) را ایجاد می کند که با controller کار می کنند. در پروژه هایی که در آینده ایجاد می کنید و در آن ها از EF استفاده می کنید، می توانید از تعدادی قابلیت اضافی scaffolder بهره بگیرید: کافی است اولین کلاس model خود را ایجاد کرده، سپس در کادر Add Controller، یک کلاس context جدید تعریف کنید(در این مرحله از تعریف connection string خودداری نمایید).Scaffolder خود کلاس DbContext و connection string را به ضمیمه ی controller و view ها ایجاد می کند.
4. Visual Studio، فایل Controllers\StudentController.cs را باز می کند. خواهید دید که یک class variable اضافه شده که database context object را مقداردهی اولیه می کند:
private SchoolContext db = new SchoolContext();
متد اکشن Index یک لیست از دانشجویان را از entity set به نام Students بازیابی می کند. این کار با خواندن خاصیتStudents از نمونه ی database context صورت می گیرد:
public ViewResult Index()
{
return View(db.Students.ToList());
}
Student\Index.cshtml view ، این لیست را در یک جدول نمایش می دهد:
<table>
<tr>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstMidName)
</th>
<th>
@Html.DisplayNameFor(model => model.EnrollmentDate)
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</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>
}
</table>
2. CTRL+F5 را زده تا پروژه اجرا شود. (در صورت برخورد با خطای "Cannot create Shadow Copy"، مرورگر را بسته و مجددا امتحان کنید.)
روی تب Students کلیک کرده تا داده هایی که توسط متد Seed درج گردیده را مشاهده نمایید. اگر پنجره ی مرورگر باریک بود، باید بر گوشه ی بالا، سمت راست کلیک کنید و یا در صورت بزرگ بودن پنجره، می توانید لینک تب Students را در نوار آدرس بالای پنجره ببینید و انتخاب کنید.
مشاهده ی پایگاه داده
هنگامی که صفحه ی Students را اجرا کردید و برنامه سعی کرد به پایگاه داده دسترسی پیدا کند، EF متوجه می شود که پایگاه داده ای ایجاد نشده، بنابراین خود یک پایگاه داده ایجاد کرده، سپس با اجرا کردن متد seed پایگاه داده را با داده های آزمایشی پر می کند.
برای مشاهده ی پایگاه داده در محیط Visual Studio، می توان از Server Explorer یا SQL Server Object Explorer استفاده کرد. در این آموزش از Server Explorer استفاده خواهیم کرد (در نسخه های پیش از 2013، Server Explorer، Database Explorer خوانده می شود.)
1. مرورگر را ببندید.
2. در پنجره ی Server Explorer، Data Connections => School Context (ContosoUniversity) و سپس Tables را باز کرده تا جداول را در پایگاه داده ی جدید خود مشاهده کنید:
3. روی جدول Student راست کلیک کرده و بر روی Show Table Data کلیک کنید تا ستون هایی که ایجاد شده و سطرهایی که در جدول درج گردیده را مشاهده کنید.
4. اتصال Server Explorer را قطع کنید.
فایل های ContosoUniversity1.mdf و .ldf در پوشه ی C:\Users\yourusername>> قرار دارند.
به این خاطر که شما از DropCreateDatabaseIfModelChanges initializer استفاده می کنید، می توانید تغییراتی را به کلاسStudent اعمال نمایید، حال برنامه را مجدد اجاره کنید، خواهید دید که پایگاه داده به صورت خودکار مجدد ایجاد شده و خود را با تغییراتی که شما اعمال کرده اید، مطابق می کند. به عنوان مثال، اگر خاصیت EmailAddress را به کلاس Student اضافه کنید و صفحه ی students را مجدد اجرا کنید، سپس به جدول مورد نظر مراجعه کنید، خواهید دید که یک ستون جدید به نامEmailAddress اضافه شده است.
مقدار کدی که بایستی می نوشتید تا EF بتواند یک پایگاه داده ی کامل را ایجاد کند، به دلیل وجود قرارداد ها (conventionها) بسیار کم بود. متوجه برخی از آن ها شدید و برخی هم گونه ای بودند که از وجود و اجرای آن ها آگاه نبودید:
1. صورت جمع اسم های کلاس entity که به عنوان اسم جداول مورد استفاده واقع شدند.
2. اسم های property های entity که برای اسم ستون بکار برده شدند.
3. خاصیت های entity که ID یا classnameID نام گذاری شدند و به عنوان خاصیت های primary key شناخته می شوند.
4. یک خاصیت زمانی به عنوان foreign key در نظرگرفته می شوند که بدین صورت نام گذاری شده باشد <navigation property name><primary key property name> (به عنوان مثال، می توان به StudentID برای Student navigation property اشاره کرد، زیرا که کلید اصلی موجودیت Student، ID می باشد). خواص foreign key را نیز می توان به همان شیوه نام گذاری کرد <primary key property name>. (به عنوان مثال، EnrollmentID زیرا که کلید اصلی موجودیت Enrollment، EnrollmentIDمی باشد).
همچنین مشاهده کردید که قرار دادها را می توان باطل کرده و بازنویسی کرد. برای مثال، تعیین کردید که اسم جداول به صورت جمع تعریف نشوند.
چکیده
در این درس یک برنامه ی ساده ایجاد کردید با بهره گیری از تکنولوژی EF و نسخه ی LocalDB اس کیو ال سرور اکسپرس داده ها را ذخیره کرده و به نمایش گذاشت. در مبحث بعدی با نحوه ی انجام عملیات ساده CRUD آشنا خواهید شد.