CS295N Web Development 1: ASP.NET
Weekly Topics | |
---|---|
1. Intro to Web Dev | 6. Unit Testing |
2. Intro to MVC & Deploying to Azure | 7. Database & Entity Framework |
3. Working with Data | 8. Unit Testing & The Repository Pattern |
4. Bootstrap | 9. Linq & Seed Data |
5. Midterm Quiz & Term Project Proposal | 10. Debugging |
Contents
Announcements IntroductionSeeding Your DatabaseSeed Data class and methodCall the Seed method from Program.csLanguage Integrated Query (LINQ) ExampleExerciseReferences
For 11/22/23
Upcoming due dates:
Term project
The dates for the beta version and code review are flexible, but make arrangements with your lab partners if you want to change these dates.
Send a PR for the beta version: Tuesday, 11/28
Submit a link to a code review on a PR: Thursday, 11/30
Presentation to the class: Monday, 12/4
Submit links to the production version: Monday, 12/4
Labs
Lab 7 Production version: pushed out to Thursday, 11/30
But, if you have it working this week, submit it.
Lab 8 Code review: Tuesday, 11/28
Lab 8 Production version: 11/30
Lab 9 is optional, extra credit: 12/4
Final Quiz: online Monday 12/4 through Wednesday 12/6
If anyone wants to take the quiz on campus, in the classroom, I'll open the classroom on Wednesday.
Discuss questions.
.NET 6 example.
MySQL on Azure.
Duplicate entities in databases.
After covering seed data, I will talk about how to avoid creating duplicate entities, for example Books. We won't address duplicate entities for the same user this term. That will be taken care of by Identity next term.
Seed data is data that is automatically added to your database when the application is started. There are two main purposes for seed data:
Development testing.
Data that is needed in production. For example, data that will populate pre-defined select lists.
One way to seed your database is to write a class with a static method that will add entities to the database. The method to seed the database will be called from Startup. I put mine in a static class named SeedData, but it's not a special name (not part of a convention).
Note that the method I'm using here is different from the method shown in the textbook (Murach and Delameter, Ch. 4, pg 142, 2022).
x
public class SeedData
{
public static void Seed(AppDbContext context)
{
if (!context.Reviews.Any()) // this is to prevent adding duplicate data
{
// Create User objects
User reviewer1 = new User { Name = "Emma Watson" };
User reviewer2 = new User { Name = "Brian Bird" };
// Queue up user objects to be saved to the DB
context.Reviews.Add(user1);
context.Reviews.Add(user1);
context.SaveChantes(); // Saving adds UserId to User objects
Review review = new Review
{
BookTitle = "Prince of Foxes",
AuthorName = "Samuel Shellabarger",
ReviewText = "Great book, a must read!",
Reviewer = reviewer1,
ReviewDate = DateTime.Parse("11/1/2020")
};
context.Reviews.Add(review); // queues up a review to be added to the DB
review = new Review
{
BookTitle = "Virgil Wander",
AuthorName = "Lief Enger",
ReviewText = "Wonderful book, written by a distant cousin of mine.",
Reviewer = reviewer2,
ReviewDate = DateTime.Parse("11/30/2020")
};
context.Reviews.Add(review);
context.SaveChanges(); // stores all the reviews in the DB
}
}
}
}
Add code at the end of the file, just before app.Run();
Get an instance of your class that is derived from DbContext
xxxxxxxxxx
// Get a DbContext object -- we will refactor this
var scope = app.Services.CreateScope())
var context = scope.ServiceProvider
.GetRequiredService<AppDbContext>();
Call the Seed method and pass it your DbContext object
xxxxxxxxxx
SeedData.Seed(context);
Refactor this to use a using
statement (this is not the same as the using statement for namespaces).
xxxxxxxxxx
using (var scope = app.Services.CreateScope())
{
var dbContext = scope.ServiceProvider
.GetRequiredService<AppDbContext>();
SeedData.Seed(dbContext);
}
The Seed
method will get called when you run your web app.
Language Integrated Query – it’s part of C# (and all the .NET languages) and can be used to query almost anything: an array, list, XML file, database, and more.
Use this in place of embedded SQL in your C# code or in place of stored procedures.
LINQ use functional language concepts. By the way, SQL also uses some functional language concepts like statelessness and "all at once"(non-sequential) operations.
LINQ Query expression syntax (as opposed to LINQ fluent syntax) was inspired by languages like LISP and Haskell and looks superficially like SQL – but it’s significantly different.
Essential operators: from, select, where
Full list of LINQ keywords: Query Keywords
Walk through the Planet example.
Assume a Planet class.
public class Planet {
public string Name {get; set;}
public int Diameter {get; set;} // km
public int DistanceToSun {get; set;} // million km
}
Assume a Planet List in which each of the eight planets has: a name, size, and distance from the sun.
List<Planet> planets = new List<Planet>();
planets.Add(new Planet{Name="Mercury", Diameter=4879, DistanceToSun=67});
// TODO: add the other seven planets
This LINQ statement will return all the planets within 200 million km of the sun:
IEnumerable<String> innerPlanets =
from p in planets
where p.DistanceToSun < 200
select p.Name;
from declares the range variable.
The range variable represents the current element in the collection that is being queried. Its scope is just this query.
where filters the objects that are retrieved.
select specifies the objects to retrieve.
Compare the LINQ statement above to the header of the foreach
loop below. Notice the similar use of the range variables.
foreach (Planet p in planets)
Deferred execution: A LINQ statement returns an IEnumerable or an IQueryable. They look like collections, but they do not contain any actual data. They just represent the query and are executed when enumerated
The query above won't be executed until you enumerate innerPlanets
foreach (String s in innerPlanets){ Console.Write(s + ", ");}
You can get a collection directly from a LINQ query by adding a scalar operator, like ToList.
List<String> innerPlanets = (from p in planets where p.DistanceToSun < 200 select p.Name).ToList();
Queries return a collection unless a scalar operator is applied (first, count, etc.)
int planetCount = (from p in planets where p.DistanceToSun < 200 select p.Name).count();
Add to the Planet example:
Write a query to find all the planets greater than a certain size. Use a loop to display the name and size of each planet.
Write a query to search for "Earth".
Display the size and distance from the sun
Hint: Use .SingleOrDefault() at the end of the query so that your query returns a Planet object.
Murach's ASP.NET Core MVC, Delamater and Murach,
Ch. 4 – "How to develop a data-driven MVC web app"
ASP.NET Core MVC with EF Core - Sort, Filter, Paging (Contoso University app)
ASP.NET Core MVC Lecture Notes by Brian Bird is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.