您的位置:首页 > 移动开发

[转]Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application (3 of 10)

2015-03-16 17:48 1116 查看
本文转自:http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application

DownloadCompletedProject

TheContosoUniversitysamplewebapplicationdemonstrateshowtocreateASP.NETMVC4applicationsusingtheEntityFramework5CodeFirstandVisualStudio2012.Forinformationaboutthetutorialseries,seethefirsttutorialintheseries.Youcanstartthetutorialseriesfromthebeginningordownloadastarterprojectforthischapterandstarthere.

Ifyourunintoaproblemyoucan’tresolve,downloadthecompletedchapterandtrytoreproduceyourproblem.Youcangenerallyfindthesolutiontotheproblembycomparingyourcodetothecompletedcode.Forsomecommonerrorsandhowtosolvethem,seeErrorsandWorkarounds.

IntheprevioustutorialyouimplementedasetofwebpagesforbasicCRUDoperationsfor
Student
entities.Inthistutorialyou'lladdsorting,filtering,andpagingfunctionalitytotheStudentsIndexpage.You'llalsocreateapagethatdoessimplegrouping.

Thefollowingillustrationshowswhatthepagewilllooklikewhenyou'redone.Thecolumnheadingsarelinksthattheusercanclicktosortbythatcolumn.Clickingacolumnheadingrepeatedlytogglesbetweenascendinganddescendingsortorder.



AddColumnSortLinkstotheStudentsIndexPage

ToaddsortingtotheStudentIndexpage,you'llchangethe
Index
methodofthe
Student
controllerandaddcodetothe
Student
Indexview.

AddSortingFunctionalitytotheIndexMethod

InControllers\StudentController.cs,replacethe
Index
methodwiththefollowingcode:

publicActionResultIndex(stringsortOrder)
{
ViewBag.NameSortParm=String.IsNullOrEmpty(sortOrder)?"Name_desc":"";
ViewBag.DateSortParm=sortOrder=="Date"?"Date_desc":"Date";
varstudents=fromsindb.Students
selects;
switch(sortOrder)
{
case"Name_desc":
students=students.OrderByDescending(s=>s.LastName);
break;
case"Date":
students=students.OrderBy(s=>s.EnrollmentDate);
break;
case"Date_desc":
students=students.OrderByDescending(s=>s.EnrollmentDate);
break;
default:
students=students.OrderBy(s=>s.LastName);
break;
}
returnView(students.ToList());
}

Thiscodereceivesa
sortOrder
parameterfromthequerystringintheURL.ThequerystringvalueisprovidedbyASP.NETMVCasaparametertotheactionmethod.Theparameterwillbeastringthat'seither"Name"or"Date",optionallyfollowedbyanunderscoreandthestring"desc"tospecifydescendingorder.Thedefaultsortorderisascending.

ThefirsttimetheIndexpageisrequested,there'snoquerystring.Thestudentsaredisplayedinascendingorderby
LastName
,whichisthedefaultasestablishedbythefall-throughcaseinthe
switch
statement.Whentheuserclicksacolumnheadinghyperlink,theappropriate
sortOrder
valueisprovidedinthequerystring.

Thetwo
ViewBag
variablesareusedsothattheviewcanconfigurethecolumnheadinghyperlinkswiththeappropriatequerystringvalues:

ViewBag.NameSortParm=String.IsNullOrEmpty(sortOrder)?"Name_desc":"";
ViewBag.DateSortParm=sortOrder=="Date"?"Date_desc":"Date";

Theseareternarystatements.Thefirstonespecifiesthatifthe
sortOrder
parameterisnullorempty,
ViewBag.NameSortParm
shouldbesetto"name_desc";otherwise,itshouldbesettoanemptystring.Thesetwostatementsenabletheviewtosetthecolumnheadinghyperlinksasfollows:

CurrentsortorderLastNameHyperlinkDateHyperlink
LastNameascendingdescendingascending
LastNamedescendingascendingascending
Dateascendingascendingdescending
Datedescendingascendingascending
ThemethodusesLINQtoEntitiestospecifythecolumntosortby.ThecodecreatesanIQueryablevariablebeforethe
switch
statement,modifiesitinthe
switch
statement,andcallsthe
ToList
methodafterthe
switch
statement.Whenyoucreateandmodify
IQueryable
variables,noqueryissenttothedatabase.Thequeryisnotexecuteduntilyouconvertthe
IQueryable
objectintoacollectionbycallingamethodsuchas
ToList
.Therefore,thiscoderesultsinasinglequerythatisnotexecuteduntilthe
returnView
statement.

AddColumnHeadingHyperlinkstotheStudentIndexView

InViews\Student\Index.cshtml,replacethe
<tr>
and
<th>
elementsfortheheadingrowwiththehighlightedcode:

<p>
@Html.ActionLink("CreateNew","Create")
</p>
<table>
<tr>
<th>
@Html.ActionLink("LastName","Index",new{sortOrder=ViewBag.NameSortParm})
</th>
<th>FirstName
</th>
<th>
@Html.ActionLink("EnrollmentDate","Index",new{sortOrder=ViewBag.DateSortParm})
</th>
<th></th>
</tr>

@foreach(variteminModel)
{

Thiscodeusestheinformationinthe
ViewBag
propertiestosetuphyperlinkswiththeappropriatequerystringvalues.

RunthepageandclicktheLastNameandEnrollmentDatecolumnheadingstoverifythatsortingworks.



AfteryouclicktheLastNameheading,studentsaredisplayedindescendinglastnameorder.



AddaSearchBoxtotheStudentsIndexPage

ToaddfilteringtotheStudentsIndexpage,you'lladdatextboxandasubmitbuttontotheviewandmakecorrespondingchangesinthe
Index
method.Thetextboxwillletyouenterastringtosearchforinthefirstnameandlastnamefields.

AddFilteringFunctionalitytotheIndexMethod

InControllers\StudentController.cs,replacethe
Index
methodwiththefollowingcode(thechangesarehighlighted):

publicViewResultIndex(stringsortOrder,stringsearchString)
{
ViewBag.NameSortParm=String.IsNullOrEmpty(sortOrder)?"name_desc":"";
ViewBag.DateSortParm=sortOrder=="Date"?"date_desc":"Date";
varstudents=fromsindb.Students
selects;
if(!String.IsNullOrEmpty(searchString))
{
students=students.Where(s=>s.LastName.ToUpper().Contains(searchString.ToUpper())
||s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}
switch(sortOrder)
{
case"name_desc":
students=students.OrderByDescending(s=>s.LastName);
break;
case"Date":
students=students.OrderBy(s=>s.EnrollmentDate);
break;
case"date_desc":
students=students.OrderByDescending(s=>s.EnrollmentDate);
break;
default:
students=students.OrderBy(s=>s.LastName);
break;
}

returnView(students.ToList());
}

You'veaddeda
searchString
parametertothe
Index
method.You'vealsoaddedtotheLINQstatementa
where
clausethatselectsonlystudentswhosefirstnameorlastnamecontainsthesearchstring.Thesearchstringvalueisreceivedfromatextboxthatyou'lladdtotheIndexview.Thestatementthataddsthewhereclauseisexecutedonlyifthere'savaluetosearchfor.

NoteInmanycasesyoucancallthesamemethodeitheronanEntityFrameworkentitysetorasanextensionmethodonanin-memorycollection.Theresultsarenormallythesamebutinsomecasesmaybedifferent.Forexample,the.NETFrameworkimplementationofthe
Contains
methodreturnsallrowswhenyoupassanemptystringtoit,buttheEntityFrameworkproviderforSQLServerCompact4.0returnszerorowsforemptystrings.Thereforethecodeintheexample(puttingthe
Where
statementinsidean
if
statement)makessurethatyougetthesameresultsforallversionsofSQLServer.Also,the.NETFrameworkimplementationofthe
Contains
methodperformsacase-sensitivecomparisonbydefault,butEntityFrameworkSQLServerprovidersperformcase-insensitivecomparisonsbydefault.Therefore,callingthe
ToUpper
methodtomakethetestexplicitlycase-insensitiveensuresthatresultsdonotchangewhenyouchangethecodelatertousearepository,whichwillreturnan
IEnumerable
collectioninsteadofan
IQueryable
object.(Whenyoucallthe
Contains
methodonan
IEnumerable
collection,yougetthe.NETFrameworkimplementation;whenyoucallitonan
IQueryable
object,yougetthedatabaseproviderimplementation.)

AddaSearchBoxtotheStudentIndexView

InViews\Student\Index.cshtml,addthehighlightedcodeimmediatelybeforetheopening
table
taginordertocreateacaption,atextbox,andaSearchbutton.

<p>
@Html.ActionLink("CreateNew","Create")
</p>

@using(Html.BeginForm())
{
<p>
Findbyname:@Html.TextBox("SearchString")
<inputtype="submit"value="Search"/></p>
}

<table>
<tr>


Runthepage,enterasearchstring,andclickSearchtoverifythatfilteringisworking.



NoticetheURLdoesn'tcontainthe"an"searchstring,whichmeansthatifyoubookmarkthispage,youwon'tgetthefilteredlistwhenyouusethebookmark.You'llchangetheSearchbuttontousequerystringsforfiltercriterialaterinthetutorial.

AddPagingtotheStudentsIndexPage

ToaddpagingtotheStudentsIndexpage,you'llstartbyinstallingthePagedList.MvcNuGetpackage.Thenyou'llmakeadditionalchangesinthe
Index
methodandaddpaginglinkstothe
Index
view.PagedList.MvcisoneofmanygoodpagingandsortingpackagesforASP.NETMVC,anditsusehereisintendedonlyasanexample,notasarecommendationforitoverotheroptions.Thefollowingillustrationshowsthepaginglinks.



InstallthePagedList.MVCNuGetPackage

TheNuGetPagedList.MvcpackageautomaticallyinstallsthePagedListpackageasadependency.ThePagedListpackageinstallsa
PagedList
collectiontypeandextensionmethodsfor
IQueryable
and
IEnumerable
collections.Theextensionmethodscreateasinglepageofdataina
PagedList
collectionoutofyour
IQueryable
or
IEnumerable
,andthe
PagedList
collectionprovidesseveralpropertiesandmethodsthatfacilitatepaging.ThePagedList.Mvcpackageinstallsapaginghelperthatdisplaysthepagingbuttons.

FromtheToolsmenu,selectLibraryPackageManagerandthenManageNuGetPackagesforSolution.

IntheManageNuGetPackagesdialogbox,clicktheOnlinetabontheleftandthenenter"paged"inthesearchbox.WhenyouseethePagedList.Mvcpackage,clickInstall.



IntheSelectProjectsbox,clickOK.



AddPagingFunctionalitytotheIndexMethod

InControllers\StudentController.cs,adda
using
statementforthe
PagedList
namespace:

usingPagedList;

Replacethe
Index
methodwiththefollowingcode:

publicViewResultIndex(stringsortOrder,stringcurrentFilter,stringsearchString,int?page)
{
ViewBag.CurrentSort=sortOrder;
ViewBag.NameSortParm=String.IsNullOrEmpty(sortOrder)?"name_desc":"";
ViewBag.DateSortParm=sortOrder=="Date"?"date_desc":"Date";

if(searchString!=null)
{
page=1;
}
else
{
searchString=currentFilter;
}

ViewBag.CurrentFilter=searchString;

varstudents=fromsindb.Students
selects;
if(!String.IsNullOrEmpty(searchString))
{
students=students.Where(s=>s.LastName.ToUpper().Contains(searchString.ToUpper())
||s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}
switch(sortOrder)
{
case"name_desc":
students=students.OrderByDescending(s=>s.LastName);
break;
case"Date":
students=students.OrderBy(s=>s.EnrollmentDate);
break;
case"date_desc":
students=students.OrderByDescending(s=>s.EnrollmentDate);
break;
default://Nameascending
students=students.OrderBy(s=>s.LastName);
break;
}

intpageSize=3;
intpageNumber=(page??1);
returnView(students.ToPagedList(pageNumber,pageSize));
}

Thiscodeaddsa
page
parameter,acurrentsortorderparameter,andacurrentfilterparametertothemethodsignature,asshownhere:

publicActionResultIndex(stringsortOrder,stringcurrentFilter,stringsearchString,int?page)

Thefirsttimethepageisdisplayed,oriftheuserhasn'tclickedapagingorsortinglink,alltheparameterswillbenull.Ifapaginglinkisclicked,the
page
variablewillcontainthepagenumbertodisplay.

AViewBag
propertyprovidestheviewwiththecurrentsortorder,becausethismustbeincludedinthepaginglinksinordertokeepthesortorderthesamewhilepaging:

ViewBag.CurrentSort=sortOrder;

Anotherproperty,
ViewBag.CurrentFilter
,providestheviewwiththecurrentfilterstring.Thisvaluemustbeincludedinthepaginglinksinordertomaintainthefiltersettingsduringpaging,anditmustberestoredtothetextboxwhenthepageisredisplayed.Ifthesearchstringischangedduringpaging,thepagehastoberesetto1,becausethenewfiltercanresultindifferentdatatodisplay.Thesearchstringischangedwhenavalueisenteredinthetextboxandthesubmitbuttonispressed.Inthatcase,the
searchString
parameterisnotnull.

if(searchString!=null)
page=1;
else
searchString=currentFilter;

Attheendofthemethod,the
ToPagedList
extensionmethodonthestudents
IQueryable
objectconvertsthestudentquerytoasinglepageofstudentsinacollectiontypethatsupportspaging.Thatsinglepageofstudentsisthenpassedtotheview:

intpageSize=3;
intpageNumber=(page??1);
returnView(students.ToPagedList(pageNumber,pageSize));

The
ToPagedList
methodtakesapagenumber.Thetwoquestionmarksrepresentthenull-coalescingoperator.Thenull-coalescingoperatordefinesadefaultvalueforanullabletype;theexpression
(page??1)
meansreturnthevalueof
page
ifithasavalue,orreturn1if
page
isnull.

AddPagingLinkstotheStudentIndexView

InViews\Student\Index.cshtml,replacetheexistingcodewiththefollowingcode:

@modelPagedList.IPagedList<ContosoUniversity.Models.Student>
@usingPagedList.Mvc;
<linkhref="~/Content/PagedList.css"rel="stylesheet"type="text/css"/>

@{
ViewBag.Title="Students";
}

<h2>Students</h2>

<p>
@Html.ActionLink("CreateNew","Create")
</p>
@using(Html.BeginForm("Index","Student",FormMethod.Get))
{
<p>
Findbyname:@Html.TextBox("SearchString",ViewBag.CurrentFilterasstring)
<inputtype="submit"value="Search"/>
</p>
}
<table>
<tr>
<th></th>
<th>
@Html.ActionLink("LastName","Index",new{sortOrder=ViewBag.NameSortParm,currentFilter=ViewBag.CurrentFilter})
</th>
<th>
FirstName
</th>
<th>
@Html.ActionLink("EnrollmentDate","Index",new{sortOrder=ViewBag.DateSortParm,currentFilter=ViewBag.CurrentFilter})
</th>
</tr>

@foreach(variteminModel){
<tr>
<td>
@Html.ActionLink("Edit","Edit",new{id=item.StudentID})|
@Html.ActionLink("Details","Details",new{id=item.StudentID})|
@Html.ActionLink("Delete","Delete",new{id=item.StudentID})
</td>
<td>
@Html.DisplayFor(modelItem=>item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem=>item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem=>item.EnrollmentDate)
</td>
</tr>
}

</table>
<br/>
Page@(Model.PageCount<Model.PageNumber?0:Model.PageNumber)of@Model.PageCount

@Html.PagedListPager(Model,page=>Url.Action("Index",new{page,sortOrder=ViewBag.CurrentSort,currentFilter=ViewBag.CurrentFilter}))

The
@model
statementatthetopofthepagespecifiesthattheviewnowgetsa
PagedList
objectinsteadofa
List
object.

The
using
statementfor
PagedList.Mvc
givesaccesstotheMVChelperforthepagingbuttons.

ThecodeusesanoverloadofBeginFormthatallowsittospecifyFormMethod.Get.

@using(Html.BeginForm("Index","Student",FormMethod.Get))
{
<p>
Findbyname:@Html.TextBox("SearchString",ViewBag.CurrentFilterasstring)
<inputtype="submit"value="Search"/>
</p>
}

ThedefaultBeginFormsubmitsformdatawithaPOST,whichmeansthatparametersarepassedintheHTTPmessagebodyandnotintheURLasquerystrings.WhenyouspecifyHTTPGET,theformdataispassedintheURLasquerystrings,whichenablesuserstobookmarktheURL.TheW3CguidelinesfortheuseofHTTPGETspecifythatyoushoulduseGETwhentheactiondoesnotresultinanupdate.

Thetextboxisinitializedwiththecurrentsearchstringsowhenyouclickanewpageyoucanseethecurrentsearchstring.

Findbyname:@Html.TextBox("SearchString",ViewBag.CurrentFilterasstring)

Thecolumnheaderlinksusethequerystringtopassthecurrentsearchstringtothecontrollersothattheusercansortwithinfilterresults:

@Html.ActionLink("LastName","Index",new{sortOrder=ViewBag.NameSortParm,currentFilter=ViewBag.CurrentFilter})

Thecurrentpageandtotalnumberofpagesaredisplayed.

Page@(Model.PageCount<Model.PageNumber?0:Model.PageNumber)of@Model.PageCount

Iftherearenopagestodisplay,"Page0of0"isshown.(Inthatcasethepagenumberisgreaterthanthepagecountbecause
Model.PageNumber
is1,and
Model.PageCount
is0.)

Thepagingbuttonsaredisplayedbythe
PagedListPager
helper:

@Html.PagedListPager(Model,page=>Url.Action("Index",new{page}))

The
PagedListPager
helperprovidesanumberofoptionsthatyoucancustomize,includingURLsandstyling.Formoreinformation,seeTroyGoode/PagedListontheGitHubsite.

Runthepage.



Clickthepaginglinksindifferentsortorderstomakesurepagingworks.Thenenterasearchstringandtrypagingagaintoverifythatpagingalsoworkscorrectlywithsortingandfiltering.



CreateanAboutPageThatShowsStudentStatistics

FortheContosoUniversitywebsite'sAboutpage,you'lldisplayhowmanystudentshaveenrolledforeachenrollmentdate.Thisrequiresgroupingandsimplecalculationsonthegroups.Toaccomplishthis,you'lldothefollowing:

Createaviewmodelclassforthedatathatyouneedtopasstotheview.

Modifythe
About
methodinthe
Home
controller.

Modifythe
About
view.

CreatetheViewModel

CreateaViewModelsfolder.Inthatfolder,addaclassfileEnrollmentDateGroup.csandreplacetheexistingcodewiththefollowingcode:

usingSystem;
usingSystem.ComponentModel.DataAnnotations;

namespaceContosoUniversity.ViewModels
{
publicclassEnrollmentDateGroup
{
[DataType(DataType.Date)]
publicDateTime?EnrollmentDate{get;set;}

publicintStudentCount{get;set;}
}
}

ModifytheHomeController

InHomeController.cs,addthefollowing
using
statementsatthetopofthefile:

usingContosoUniversity.DAL;
usingContosoUniversity.ViewModels;

Addaclassvariableforthedatabasecontextimmediatelyaftertheopeningcurlybracefortheclass:

publicclassHomeController:Controller
{
privateSchoolContextdb=newSchoolContext();

Replacethe
About
methodwiththefollowingcode:

publicActionResultAbout()
{
vardata=fromstudentindb.Students
groupstudentbystudent.EnrollmentDateintodateGroup
selectnewEnrollmentDateGroup()
{
EnrollmentDate=dateGroup.Key,
StudentCount=dateGroup.Count()
};
returnView(data);
}

TheLINQstatementgroupsthestudententitiesbyenrollmentdate,calculatesthenumberofentitiesineachgroup,andstorestheresultsinacollectionof
EnrollmentDateGroup
viewmodelobjects.

Adda
Dispose
method:

protectedoverridevoidDispose(booldisposing)
{
db.Dispose();
base.Dispose(disposing);
}

ModifytheAboutView

ReplacethecodeintheViews\Home\About.cshtmlfilewiththefollowingcode:

@modelIEnumerable<ContosoUniversity.ViewModels.EnrollmentDateGroup>

@{
ViewBag.Title="StudentBodyStatistics";
}

<h2>StudentBodyStatistics</h2>

<table>
<tr>
<th>
EnrollmentDate
</th>
<th>
Students
</th>
</tr>

@foreach(variteminModel){
<tr>
<td>
@Html.DisplayFor(modelItem=>item.EnrollmentDate)
</td>
<td>
@item.StudentCount
</td>
</tr>
}
</table>

RuntheappandclicktheAboutlink.Thecountofstudentsforeachenrollmentdateisdisplayedinatable.



Optional:DeploytheapptoWindowsAzure

SofaryourapplicationhasbeenrunninglocallyinIISExpressonyourdevelopmentcomputer.TomakeitavailableforotherpeopletouseovertheInternet,youhavetodeployittoawebhostingprovider.Inthisoptionalsectionofthetutorialyou'lldeployittoaWindowsAzureWebSite.

UsingCodeFirstMigrationstoDeploytheDatabase

Todeploythedatabaseyou'lluseCodeFirstMigrations.WhenyoucreatethepublishprofilethatyouusetoconfiguresettingsfordeployingfromVisualStudio,you'llselectacheckboxthatislabeledExecuteCodeFirstMigrations(runsonapplicationstart).ThissettingcausesthedeploymentprocesstoautomaticallyconfiguretheapplicationWeb.configfileonthedestinationserversothatCodeFirstusesthe
MigrateDatabaseToLatestVersion
initializerclass.

VisualStudiodoesnotdoanythingwiththedatabaseduringthedeploymentprocess.Whenthedeployedapplicationaccessesthedatabaseforthefirsttimeafterdeployment,CodeFirstautomaticallycreatesthedatabaseorupdatesthedatabaseschematothelatestversion.IftheapplicationimplementsaMigrations
Seed
method,themethodrunsafterthedatabaseiscreatedortheschemaisupdated.

YourMigrations
Seed
methodinsertstestdata.Ifyouweredeployingtoaproductionenvironment,youwouldhavetochangethe
Seed
methodsothatitonlyinsertsdatathatyouwanttobeinsertedintoyourproductiondatabase.Forexample,inyourcurrentdatamodelyoumightwanttohaverealcoursesbutfictionalstudentsinthedevelopmentdatabase.Youcanwritea
Seed
methodtoloadbothindevelopment,andthencommentoutthefictionalstudentsbeforeyoudeploytoproduction.Oryoucanwritea
Seed
methodtoloadonlycourses,andenterthefictionalstudentsinthetestdatabasemanuallybyusingtheapplication'sUI.

GetaWindowsAzureaccount

You'llneedaWindowsAzureaccount.Ifyoudon'talreadyhaveone,youcancreateafreetrialaccountinjustacoupleofminutes.Fordetails,seeWindowsAzureFreeTrial.

CreateawebsiteandaSQLdatabaseinWindowsAzure

YourWindowsAzureWebSitewillruninasharedhostingenvironment,whichmeansitrunsonvirtualmachines(VMs)thataresharedwithotherWindowsAzureclients.Asharedhostingenvironmentisalow-costwaytogetstartedinthecloud.Later,ifyourwebtrafficincreases,theapplicationcanscaletomeettheneedbyrunningondedicatedVMs.Ifyouneedamorecomplexarchitecture,youcanmigratetoaWindowsAzureCloudService.CloudservicesrunondedicatedVMsthatyoucanconfigureaccordingtoyourneeds.

WindowsAzureSQLDatabaseisacloud-basedrelationaldatabaseservicethatisbuiltonSQLServertechnologies.ToolsandapplicationsthatworkwithSQLServeralsoworkwithSQLDatabase.

IntheWindowsAzureManagementPortal,clickWebSitesinthelefttab,andthenclickNew.



ClickCUSTOMCREATE.



TheNewWebSite-CustomCreatewizardopens.

IntheNewWebSitestepofthewizard,enterastringintheURLboxtouseastheuniqueURLforyourapplication.ThecompleteURLwillconsistofwhatyouenterhereplusthesuffixthatyouseenexttothetextbox.Theillustrationshows"ConU",butthatURLisprobablytakensoyouwillhavetochooseadifferentone.



IntheRegiondrop-downlist,choosearegionclosetoyou.Thissettingspecifieswhichdatacenteryourwebsitewillrunin.

IntheDatabasedrop-downlist,chooseCreateafree20MBSQLdatabase.



IntheDBCONNECTIONSTRINGNAME,enterSchoolContext.



Clickthearrowthatpointstotherightatthebottomofthebox.ThewizardadvancestotheDatabaseSettingsstep.

IntheNamebox,enterContosoUniversityDB.

IntheServerbox,selectNewSQLDatabaseserver.Alternatively,ifyoupreviouslycreatedaserver,youcanselectthatserverfromthedrop-downlist.

EnteranadministratorLOGINNAMEandPASSWORD.IfyouselectedNewSQLDatabaseserveryouaren'tenteringanexistingnameandpasswordhere,you'reenteringanewnameandpasswordthatyou'redefiningnowtouselaterwhenyouaccessthedatabase.Ifyouselectedaserverthatyoucreatedpreviously,you’llentercredentialsforthatserver.Forthistutorial,youwon'tselecttheAdvancedcheckbox.TheAdvancedoptionsenableyoutosetthedatabasecollation.

ChoosethesameRegionthatyouchoseforthewebsite.

Clickthecheckmarkatthebottomrightoftheboxtoindicatethatyou'refinished.



ThefollowingimageshowsusinganexistingSQLServerandLogin.



TheManagementPortalreturnstotheWebSitespage,andtheStatuscolumnshowsthatthesiteisbeingcreated.Afterawhile(typicallylessthanaminute),theStatuscolumnshowsthatthesitewassuccessfullycreated.Inthenavigationbarattheleft,thenumberofsitesyouhaveinyouraccountappearsnexttotheWebSitesicon,andthenumberofdatabasesappearsnexttotheSQLDatabasesicon.

DeploytheapplicationtoWindowsAzure

InVisualStudio,right-clicktheprojectinSolutionExplorerandselectPublishfromthecontextmenu.



IntheProfiletabofthePublishWebwizard,clickImport.



IfyouhavenotpreviouslyaddedyourWindowsAzuresubscriptioninVisualStudio,performthefollowingsteps.Inthesestepsyouaddyoursubscriptionsothatthedrop-downlistunderImportfromaWindowsAzurewebsitewillincludeyourwebsite.

a.IntheImportPublishProfiledialogbox,clickImportfromaWindowsAzurewebsite,andthenclickAddWindowsAzuresubscription.



b.IntheImportWindowsAzureSubscriptionsdialogbox,clickDownloadsubscriptionfile.



c.Inyourbrowserwindow,savethe.publishsettingsfile.



SecurityNote:Thepublishsettingsfilecontainsyourcredentials(unencoded)thatareusedtoadministeryourWindowsAzuresubscriptionsandservices.Thesecuritybestpracticeforthisfileistostoreittemporarilyoutsideyoursourcedirectories(forexampleintheLibraries\Documentsfolder),andthendeleteitoncetheimporthascompleted.Amalicioususerwhogainsaccesstothe
.publishsettings
filecanedit,create,anddeleteyourWindowsAzureservices.

d.IntheImportWindowsAzureSubscriptionsdialogbox,clickBrowseandnavigatetothe.publishsettingsfile.



e.ClickImport.



IntheImportPublishProfiledialogbox,selectImportfromaWindowsAzurewebsite,selectyourwebsitefromthedrop-downlist,andthenclickOK.



IntheConnectiontab,clickValidateConnectiontomakesurethatthesettingsarecorrect.



Whentheconnectionhasbeenvalidated,agreencheckmarkisshownnexttotheValidateConnectionbutton.ClickNext.



OpentheRemoteconnectionstringdrop-downlistunderSchoolContextandselecttheconnectionstringforthedatabaseyoucreated.

SelectExecuteCodeFirstMigrations(runsonapplicationstart).

UncheckUsethisconnectionstringatruntimefortheUserContext(DefaultConnection),sincethisapplicationisnotusingthemembershipdatabase.



ClickNext.

InthePreviewtab,clickStartPreview.



Thetabdisplaysalistofthefilesthatwillbecopiedtotheserver.Displayingthepreviewisn'trequiredtopublishtheapplicationbutisausefulfunctiontobeawareof.Inthiscase,youdon'tneedtodoanythingwiththelistoffilesthatisdisplayed.Thenexttimeyoudeploythisapplication,onlythefilesthathavechangedwillbeinthislist.



ClickPublish.
VisualStudiobeginstheprocessofcopyingthefilestotheWindowsAzureserver.

TheOutputwindowshowswhatdeploymentactionsweretakenandreportssuccessfulcompletionofthedeployment.



Uponsuccessfuldeployment,thedefaultbrowserautomaticallyopenstotheURLofthedeployedwebsite.
Theapplicationyoucreatedisnowrunninginthecloud.ClicktheStudentstab.



AtthispointyourSchoolContextdatabasehasbeencreatedintheWindowsAzureSQLDatabasebecauseyouselectedExecuteCodeFirstMigrations(runsonappstart).TheWeb.configfileinthedeployedwebsitehasbeenchangedsothattheMigrateDatabaseToLatestVersioninitializerwouldrunthefirsttimeyourcodereadsorwritesdatainthedatabase(whichhappenedwhenyouselectedtheStudentstab):



Thedeploymentprocessalsocreatedanewconnectionstring(SchoolContext_DatabasePublish)forCodeFirstMigrationstouseforupdatingthedatabaseschemaandseedingthedatabase.



TheDefaultConnectionconnectionstringisforthemembershipdatabase(whichwearenotusinginthistutorial).TheSchoolContextconnectionstringisfortheContosoUniversitydatabase.

YoucanfindthedeployedversionoftheWeb.configfileonyourowncomputerinContosoUniversity\obj\Release\Package\PackageTmp\Web.config.YoucanaccessthedeployedWeb.configfileitselfbyusingFTP.Forinstructions,seeASP.NETWebDeploymentusingVisualStudio:DeployingaCodeUpdate.Followtheinstructionsthatstartwith"TouseanFTPtool,youneedthreethings:theFTPURL,theusername,andthepassword."

Note:Thewebappdoesn'timplementsecurity,soanyonewhofindstheURLcanchangethedata.Forinstructionsonhowtosecurethewebsite,seeDeployaSecureASP.NETMVCappwithMembership,OAuth,andSQLDatabasetoaWindowsAzureWebSite.YoucanpreventotherpeoplefromusingthesitebyusingtheWindowsAzureManagementPortalorServerExplorerinVisualStudiotostopthesite.



CodeFirstInitializers

InthedeploymentsectionyousawtheMigrateDatabaseToLatestVersioninitializerbeingused.CodeFirstalsoprovidesotherinitializersthatyoucanuse,includingCreateDatabaseIfNotExists(thedefault),DropCreateDatabaseIfModelChangesandDropCreateDatabaseAlways.The
DropCreateAlways
initializercanbeusefulforsettingupconditionsforunittests.Youcanalsowriteyourowninitializers,andyoucancallaninitializerexplicitlyifyoudon'twanttowaituntiltheapplicationreadsfromorwritestothedatabase.Foracomprehensiveexplanationofinitializers,seechapter6ofthebookProgrammingEntityFramework:CodeFirstbyJulieLermanandRowanMiller.

Summary

Inthistutorialyou'veseenhowtocreateadatamodelandimplementbasicCRUD,sorting,filtering,paging,andgroupingfunctionality.Inthenexttutorialyou'llbeginlookingatmoreadvancedtopicsbyexpandingthedatamodel.

LinkstootherEntityFrameworkresourcescanbefoundintheASP.NETDataAccessContentMap.

ThisarticlewasoriginallycreatedonJuly30,2013

Tweet

AuthorInformation



TomDykstra–TomDykstraisaSeniorProgrammingWriteronMicrosoft'sWebPlatform&ToolsContentTeam...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐