[转]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
Thefollowingillustrationshowswhatthepagewilllooklikewhenyou'redone.Thecolumnheadingsarelinksthattheusercanclicktosortbythatcolumn.Clickingacolumnheadingrepeatedlytogglesbetweenascendinganddescendingsortorder.
Thiscodereceivesa
ThefirsttimetheIndexpageisrequested,there'snoquerystring.Thestudentsaredisplayedinascendingorderby
Thetwo
Theseareternarystatements.Thefirstonespecifiesthatifthe
ThemethodusesLINQtoEntitiestospecifythecolumntosortby.ThecodecreatesanIQueryablevariablebeforethe
Thiscodeusestheinformationinthe
RunthepageandclicktheLastNameandEnrollmentDatecolumnheadingstoverifythatsortingworks.
AfteryouclicktheLastNameheading,studentsaredisplayedindescendinglastnameorder.
You'veaddedawhereclauseisexecutedonlyifthere'savaluetosearchfor.
NoteInmanycasesyoucancallthesamemethodeitheronanEntityFrameworkentitysetorasanextensionmethodonanin-memorycollection.Theresultsarenormallythesamebutinsomecasesmaybedifferent.Forexample,the.NETFrameworkimplementationofthe
Runthepage,enterasearchstring,andclickSearchtoverifythatfilteringisworking.
NoticetheURLdoesn'tcontainthe"an"searchstring,whichmeansthatifyoubookmarkthispage,youwon'tgetthefilteredlistwhenyouusethebookmark.You'llchangetheSearchbuttontousequerystringsforfiltercriterialaterinthetutorial.
FromtheToolsmenu,selectLibraryPackageManagerandthenManageNuGetPackagesforSolution.
IntheManageNuGetPackagesdialogbox,clicktheOnlinetabontheleftandthenenter"paged"inthesearchbox.WhenyouseethePagedList.Mvcpackage,clickInstall.
IntheSelectProjectsbox,clickOK.
Replacethe
Thiscodeaddsa
Thefirsttimethepageisdisplayed,oriftheuserhasn'tclickedapagingorsortinglink,alltheparameterswillbenull.Ifapaginglinkisclicked,the
Anotherproperty,
Attheendofthemethod,the
Thenull-coalescingoperator.Thenull-coalescingoperatordefinesadefaultvalueforanullabletype;theexpression
The
The
ThecodeusesanoverloadofBeginFormthatallowsittospecifyFormMethod.Get.
ThedefaultBeginFormsubmitsformdatawithaPOST,whichmeansthatparametersarepassedintheHTTPmessagebodyandnotintheURLasquerystrings.WhenyouspecifyHTTPGET,theformdataispassedintheURLasquerystrings,whichenablesuserstobookmarktheURL.TheW3CguidelinesfortheuseofHTTPGETspecifythatyoushoulduseGETwhentheactiondoesnotresultinanupdate.
Thetextboxisinitializedwiththecurrentsearchstringsowhenyouclickanewpageyoucanseethecurrentsearchstring.
Thecolumnheaderlinksusethequerystringtopassthecurrentsearchstringtothecontrollersothattheusercansortwithinfilterresults:
Thecurrentpageandtotalnumberofpagesaredisplayed.
Iftherearenopagestodisplay,"Page0of0"isshown.(Inthatcasethepagenumberisgreaterthanthepagecountbecause
Thepagingbuttonsaredisplayedbythe
TheTroyGoode/PagedListontheGitHubsite.
Runthepage.
Clickthepaginglinksindifferentsortorderstomakesurepagingworks.Thenenterasearchstringandtrypagingagaintoverifythatpagingalsoworkscorrectlywithsortingandfiltering.
Createaviewmodelclassforthedatathatyouneedtopasstotheview.
Modifythe
Modifythe
Addaclassvariableforthedatabasecontextimmediatelyaftertheopeningcurlybracefortheclass:
Replacethe
TheLINQstatementgroupsthestudententitiesbyenrollmentdate,calculatesthenumberofentitiesineachgroup,andstorestheresultsinacollectionof
Adda
RuntheappandclicktheAboutlink.Thecountofstudentsforeachenrollmentdateisdisplayedinatable.
VisualStudiodoesnotdoanythingwiththedatabaseduringthedeploymentprocess.Whenthedeployedapplicationaccessesthedatabaseforthefirsttimeafterdeployment,CodeFirstautomaticallycreatesthedatabaseorupdatesthedatabaseschematothelatestversion.IftheapplicationimplementsaMigrations
YourMigrations
WindowsAzureFreeTrial.
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.
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
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.
MigrateDatabaseToLatestVersioninitializerbeingused.CodeFirstalsoprovidesotherinitializersthatyoucanuse,includingCreateDatabaseIfNotExists(thedefault),DropCreateDatabaseIfModelChangesandDropCreateDatabaseAlways.TheProgrammingEntityFramework:CodeFirstbyJulieLermanandRowanMiller.
LinkstootherEntityFrameworkresourcescanbefoundintheASP.NETDataAccessContentMap.
ThisarticlewasoriginallycreatedonJuly30,2013
Tweet
TomDykstra–TomDykstraisaSeniorProgrammingWriteronMicrosoft'sWebPlatform&ToolsContentTeam...
TheContosoUniversitysamplewebapplicationdemonstrateshowtocreateASP.NETMVC4applicationsusingtheEntityFramework5CodeFirstandVisualStudio2012.Forinformationaboutthetutorialseries,see
Ifyourunintoaproblemyoucan’tresolve,
IntheprevioustutorialyouimplementedasetofwebpagesforbasicCRUDoperationsfor
Studententities.Inthistutorialyou'lladdsorting,filtering,andpagingfunctionalitytotheStudentsIndexpage.You'llalsocreateapagethatdoessimplegrouping.
Thefollowingillustrationshowswhatthepagewilllooklikewhenyou'redone.Thecolumnheadingsarelinksthattheusercanclicktosortbythatcolumn.Clickingacolumnheadingrepeatedlytogglesbetweenascendinganddescendingsortorder.
AddColumnSortLinkstotheStudentsIndexPage
ToaddsortingtotheStudentIndexpage,you'llchangetheIndexmethodofthe
Studentcontrollerandaddcodetothe
StudentIndexview.
AddSortingFunctionalitytotheIndexMethod
InControllers\StudentController.cs,replacetheIndexmethodwiththefollowingcode:
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
sortOrderparameterfromthequerystringintheURL.ThequerystringvalueisprovidedbyASP.NETMVCasaparametertotheactionmethod.Theparameterwillbeastringthat'seither"Name"or"Date",optionallyfollowedbyanunderscoreandthestring"desc"tospecifydescendingorder.Thedefaultsortorderisascending.
ThefirsttimetheIndexpageisrequested,there'snoquerystring.Thestudentsaredisplayedinascendingorderby
LastName,whichisthedefaultasestablishedbythefall-throughcaseinthe
switchstatement.Whentheuserclicksacolumnheadinghyperlink,theappropriate
sortOrdervalueisprovidedinthequerystring.
Thetwo
ViewBagvariablesareusedsothattheviewcanconfigurethecolumnheadinghyperlinkswiththeappropriatequerystringvalues:
ViewBag.NameSortParm=String.IsNullOrEmpty(sortOrder)?"Name_desc":""; ViewBag.DateSortParm=sortOrder=="Date"?"Date_desc":"Date";
Theseareternarystatements.Thefirstonespecifiesthatifthe
sortOrderparameterisnullorempty,
ViewBag.NameSortParmshouldbesetto"name_desc";otherwise,itshouldbesettoanemptystring.Thesetwostatementsenabletheviewtosetthecolumnheadinghyperlinksasfollows:
Currentsortorder | LastNameHyperlink | DateHyperlink |
---|---|---|
LastNameascending | descending | ascending |
LastNamedescending | ascending | ascending |
Dateascending | ascending | descending |
Datedescending | ascending | ascending |
switchstatement,modifiesitinthe
switchstatement,andcallsthe
ToListmethodafterthe
switchstatement.Whenyoucreateandmodify
IQueryablevariables,noqueryissenttothedatabase.Thequeryisnotexecuteduntilyouconvertthe
IQueryableobjectintoacollectionbycallingamethodsuchas
ToList.Therefore,thiscoderesultsinasinglequerythatisnotexecuteduntilthe
returnViewstatement.
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
ViewBagpropertiestosetuphyperlinkswiththeappropriatequerystringvalues.
RunthepageandclicktheLastNameandEnrollmentDatecolumnheadingstoverifythatsortingworks.
AfteryouclicktheLastNameheading,studentsaredisplayedindescendinglastnameorder.
AddaSearchBoxtotheStudentsIndexPage
ToaddfilteringtotheStudentsIndexpage,you'lladdatextboxandasubmitbuttontotheviewandmakecorrespondingchangesintheIndexmethod.Thetextboxwillletyouenterastringtosearchforinthefirstnameandlastnamefields.
AddFilteringFunctionalitytotheIndexMethod
InControllers\StudentController.cs,replacetheIndexmethodwiththefollowingcode(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
searchStringparametertothe
Indexmethod.You'vealsoaddedtotheLINQstatementa
whereclausethatselectsonlystudentswhosefirstnameorlastnamecontainsthesearchstring.Thesearchstringvalueisreceivedfromatextboxthatyou'lladdtotheIndexview.Thestatementthataddsthe
NoteInmanycasesyoucancallthesamemethodeitheronanEntityFrameworkentitysetorasanextensionmethodonanin-memorycollection.Theresultsarenormallythesamebutinsomecasesmaybedifferent.Forexample,the.NETFrameworkimplementationofthe
Containsmethodreturnsallrowswhenyoupassanemptystringtoit,buttheEntityFrameworkproviderforSQLServerCompact4.0returnszerorowsforemptystrings.Thereforethecodeintheexample(puttingthe
Wherestatementinsidean
ifstatement)makessurethatyougetthesameresultsforallversionsofSQLServer.Also,the.NETFrameworkimplementationofthe
Containsmethodperformsacase-sensitivecomparisonbydefault,butEntityFrameworkSQLServerprovidersperformcase-insensitivecomparisonsbydefault.Therefore,callingthe
ToUppermethodtomakethetestexplicitlycase-insensitiveensuresthatresultsdonotchangewhenyouchangethecodelatertousearepository,whichwillreturnan
IEnumerablecollectioninsteadofan
IQueryableobject.(Whenyoucallthe
Containsmethodonan
IEnumerablecollection,yougetthe.NETFrameworkimplementation;whenyoucallitonan
IQueryableobject,yougetthedatabaseproviderimplementation.)
AddaSearchBoxtotheStudentIndexView
InViews\Student\Index.cshtml,addthehighlightedcodeimmediatelybeforetheopeningtabletaginordertocreateacaption,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'llmakeadditionalchangesintheIndexmethodandaddpaginglinkstothe
Indexview.PagedList.MvcisoneofmanygoodpagingandsortingpackagesforASP.NETMVC,anditsusehereisintendedonlyasanexample,notasarecommendationforitoverotheroptions.Thefollowingillustrationshowsthepaginglinks.
InstallthePagedList.MVCNuGetPackage
TheNuGetPagedList.MvcpackageautomaticallyinstallsthePagedListpackageasadependency.ThePagedListpackageinstallsaPagedListcollectiontypeandextensionmethodsfor
IQueryableand
IEnumerablecollections.Theextensionmethodscreateasinglepageofdataina
PagedListcollectionoutofyour
IQueryableor
IEnumerable,andthe
PagedListcollectionprovidesseveralpropertiesandmethodsthatfacilitatepaging.ThePagedList.Mvcpackageinstallsapaginghelperthatdisplaysthepagingbuttons.
FromtheToolsmenu,selectLibraryPackageManagerandthenManageNuGetPackagesforSolution.
IntheManageNuGetPackagesdialogbox,clicktheOnlinetabontheleftandthenenter"paged"inthesearchbox.WhenyouseethePagedList.Mvcpackage,clickInstall.
IntheSelectProjectsbox,clickOK.
AddPagingFunctionalitytotheIndexMethod
InControllers\StudentController.cs,addausingstatementforthe
PagedListnamespace:
usingPagedList;
Replacethe
Indexmethodwiththefollowingcode:
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
pageparameter,acurrentsortorderparameter,andacurrentfilterparametertothemethodsignature,asshownhere:
publicActionResultIndex(stringsortOrder,stringcurrentFilter,stringsearchString,int?page)
Thefirsttimethepageisdisplayed,oriftheuserhasn'tclickedapagingorsortinglink,alltheparameterswillbenull.Ifapaginglinkisclicked,the
pagevariablewillcontainthepagenumbertodisplay.
AViewBagpropertyprovidestheviewwiththecurrentsortorder,becausethismustbeincludedinthepaginglinksinordertokeepthesortorderthesamewhilepaging:
ViewBag.CurrentSort=sortOrder;
Anotherproperty,
ViewBag.CurrentFilter,providestheviewwiththecurrentfilterstring.Thisvaluemustbeincludedinthepaginglinksinordertomaintainthefiltersettingsduringpaging,anditmustberestoredtothetextboxwhenthepageisredisplayed.Ifthesearchstringischangedduringpaging,thepagehastoberesetto1,becausethenewfiltercanresultindifferentdatatodisplay.Thesearchstringischangedwhenavalueisenteredinthetextboxandthesubmitbuttonispressed.Inthatcase,the
searchStringparameterisnotnull.
if(searchString!=null)
page=1;
else
searchString=currentFilter;
Attheendofthemethod,the
ToPagedListextensionmethodonthestudents
IQueryableobjectconvertsthestudentquerytoasinglepageofstudentsinacollectiontypethatsupportspaging.Thatsinglepageofstudentsisthenpassedtotheview:
intpageSize=3;
intpageNumber=(page??1);
returnView(students.ToPagedList(pageNumber,pageSize));
The
ToPagedListmethodtakesapagenumber.Thetwoquestionmarksrepresentthe
(page??1)meansreturnthevalueof
pageifithasavalue,orreturn1if
pageisnull.
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
@modelstatementatthetopofthepagespecifiesthattheviewnowgetsa
PagedListobjectinsteadofa
Listobject.
The
usingstatementfor
PagedList.MvcgivesaccesstotheMVChelperforthepagingbuttons.
Thecodeusesanoverloadof
@using(Html.BeginForm("Index","Student",FormMethod.Get))
{
<p>
Findbyname:@Html.TextBox("SearchString",ViewBag.CurrentFilterasstring)
<inputtype="submit"value="Search"/>
</p>
}
Thedefault
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.PageNumberis1,and
Model.PageCountis0.)
Thepagingbuttonsaredisplayedbythe
PagedListPagerhelper:
@Html.PagedListPager(Model,page=>Url.Action("Index",new{page}))
The
PagedListPagerhelperprovidesanumberofoptionsthatyoucancustomize,includingURLsandstyling.Formoreinformation,see
Runthepage.
Clickthepaginglinksindifferentsortorderstomakesurepagingworks.Thenenterasearchstringandtrypagingagaintoverifythatpagingalsoworkscorrectlywithsortingandfiltering.
CreateanAboutPageThatShowsStudentStatistics
FortheContosoUniversitywebsite'sAboutpage,you'lldisplayhowmanystudentshaveenrolledforeachenrollmentdate.Thisrequiresgroupingandsimplecalculationsonthegroups.Toaccomplishthis,you'lldothefollowing:Createaviewmodelclassforthedatathatyouneedtopasstotheview.
Modifythe
Aboutmethodinthe
Homecontroller.
Modifythe
Aboutview.
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,addthefollowingusingstatementsatthetopofthefile:
usingContosoUniversity.DAL;
usingContosoUniversity.ViewModels;
Addaclassvariableforthedatabasecontextimmediatelyaftertheopeningcurlybracefortheclass:
publicclassHomeController:Controller
{
privateSchoolContextdb=newSchoolContext();
Replacethe
Aboutmethodwiththefollowingcode:
publicActionResultAbout()
{
vardata=fromstudentindb.Students
groupstudentbystudent.EnrollmentDateintodateGroup
selectnewEnrollmentDateGroup()
{
EnrollmentDate=dateGroup.Key,
StudentCount=dateGroup.Count()
};
returnView(data);
}
TheLINQstatementgroupsthestudententitiesbyenrollmentdate,calculatesthenumberofentitiesineachgroup,andstorestheresultsinacollectionof
EnrollmentDateGroupviewmodelobjects.
Adda
Disposemethod:
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.configfileonthedestinationserversothatCodeFirstusestheMigrateDatabaseToLatestVersioninitializerclass.
VisualStudiodoesnotdoanythingwiththedatabaseduringthedeploymentprocess.Whenthedeployedapplicationaccessesthedatabaseforthefirsttimeafterdeployment,CodeFirstautomaticallycreatesthedatabaseorupdatesthedatabaseschematothelatestversion.IftheapplicationimplementsaMigrations
Seedmethod,themethodrunsafterthedatabaseiscreatedortheschemaisupdated.
YourMigrations
Seedmethodinsertstestdata.Ifyouweredeployingtoaproductionenvironment,youwouldhavetochangethe
Seedmethodsothatitonlyinsertsdatathatyouwanttobeinsertedintoyourproductiondatabase.Forexample,inyourcurrentdatamodelyoumightwanttohaverealcoursesbutfictionalstudentsinthedevelopmentdatabase.Youcanwritea
Seedmethodtoloadbothindevelopment,andthencommentoutthefictionalstudentsbeforeyoudeploytoproduction.Oryoucanwritea
Seedmethodtoloadonlycourses,andenterthefictionalstudentsinthetestdatabasemanuallybyusingtheapplication'sUI.
GetaWindowsAzureaccount
You'llneedaWindowsAzureaccount.Ifyoudon'talreadyhaveone,youcancreateafreetrialaccountinjustacoupleofminutes.Fordetails,seeCreateawebsiteandaSQLdatabaseinWindowsAzure
YourWindowsAzureWebSitewillruninasharedhostingenvironment,whichmeansitrunsonvirtualmachines(VMs)thataresharedwithotherWindowsAzureclients.Asharedhostingenvironmentisalow-costwaytogetstartedinthecloud.Later,ifyourwebtrafficincreases,theapplicationcanscaletomeettheneedbyrunningondedicatedVMs.Ifyouneedamorecomplexarchitecture,youcanmigratetoaWindowsAzureCloudService.CloudservicesrunondedicatedVMsthatyoucanconfigureaccordingtoyourneeds.WindowsAzureSQLDatabaseisacloud-basedrelationaldatabaseservicethatisbuiltonSQLServertechnologies.ToolsandapplicationsthatworkwithSQLServeralsoworkwithSQLDatabase.
Inthe
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.TheAdvancedoptionsenableyoutosetthedatabase
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
.publishsettingsfilecanedit,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.configfileinthedeployedwebsitehasbeenchangedsothatthe
Thedeploymentprocessalsocreatedanewconnectionstring(SchoolContext_DatabasePublish)forCodeFirstMigrationstouseforupdatingthedatabaseschemaandseedingthedatabase.
TheDefaultConnectionconnectionstringisforthemembershipdatabase(whichwearenotusinginthistutorial).TheSchoolContextconnectionstringisfortheContosoUniversitydatabase.
YoucanfindthedeployedversionoftheWeb.configfileonyourowncomputerinContosoUniversity\obj\Release\Package\PackageTmp\Web.config.YoucanaccessthedeployedWeb.configfileitselfbyusingFTP.Forinstructions,see
Note:Thewebappdoesn'timplementsecurity,soanyonewhofindstheURLcanchangethedata.Forinstructionsonhowtosecurethewebsite,see
CodeFirstInitializers
InthedeploymentsectionyousawtheDropCreateAlwaysinitializercanbeusefulforsettingupconditionsforunittests.Youcanalsowriteyourowninitializers,andyoucancallaninitializerexplicitlyifyoudon'twanttowaituntiltheapplicationreadsfromorwritestothedatabase.Foracomprehensiveexplanationofinitializers,seechapter6ofthebook
Summary
Inthistutorialyou'veseenhowtocreateadatamodelandimplementbasicCRUD,sorting,filtering,paging,andgroupingfunctionality.Inthenexttutorialyou'llbeginlookingatmoreadvancedtopicsbyexpandingthedatamodel.LinkstootherEntityFrameworkresourcescanbefoundinthe
ThisarticlewasoriginallycreatedonJuly30,2013
AuthorInformation
TomDykstra–TomDykstraisaSeniorProgrammingWriteronMicrosoft'sWebPlatform&ToolsContentTeam...
相关文章推荐
- Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application
- Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10)
- Server-Side Paging with the Entity Framework and ASP.NET MVC 3
- using Silverlight 4 in an ASP.NET MVC 3 application and accessing data with JSON
- [转]Using the Repository Pattern with ASP.NET MVC and Entity Framework
- Using the Repository Pattern with ASP.NET MVC and Entity Framework
- http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
- ASP.NET MVC Example with Northwind and Entity Framework Published
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之目录导航
- 翻译:ASP.NET MVC Example Application over Northwind with Entity Framework
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第六章:管理产品图片——多对多关系(上篇)
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第六章:管理产品图片——多对多关系(上篇)
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第四章:更高级的数据管理
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第三章:搜索、高级过滤和视图模型
- Configuring Autofac to work with the ASP.NET Identity Framework in MVC 5
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第六章:管理产品图片——多对多关系(上篇)
- EF Database First with ASP.NET MVC: Creating the Web Application and Data Models开发遇到问题的解决办法
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第五章:排序、分页和路由
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库
- An Overview Of The New Services, Controls, And Features In ASP.NET 2.0