Tag Archives: ef core

Query Tags in EF Core for ASP .NET Core 3.1 Web Apps

By Shahed C on April 27, 2020

This is the seventeenth of a new series of posts on ASP .NET Core 3.1 for 2020. In this series, we’ll cover 26 topics over a span of 26 weeks from January through June 2020, titled ASP .NET Core A-Z! To differentiate from the 2019 series, the 2020 series will mostly focus on a growing single codebase (NetLearner!) instead of new unrelated code snippets week.

Previous post:

NetLearner on GitHub:

In this Article:

Q is for Query Tags in EF Core

Query Tags were introduced in Entity Framework (EF) Core 2.2, as a way to associate your LINQ Queries with SQL Queries. This can be useful when browsing log files during debugging and troubleshooting. This article explains how Query Tags work, how to find the output and how to format the text strings before displaying them.

Query Tags in ASP .NET Core web apps
Query Tags in ASP .NET Core web apps

NOTE: You may have read that Query Types have been renamed to entities without keys, but please note that Query Types (introduced in EF Core 2.1) are not the same thing as Query Tags.

As of ASP .NET Core 3.0 Preview 1, EF Core must be installed separately via NuGet (e.g. v3.0.0-preview4.19216.3), as it is no longer included with the ASP .NET Core shared framework. Also, the dotnet ef tool has to be installed as a global/local tool, as it is no longer part of the .NET Core SDK. For more information, see the official announcement for Preview 4, where it was first mentioned:

Implementing Query Tags

The NetLearner source code includes a C# model called LearningResource, with a few basic fields:

public class LearningResource
{
    public int Id { get; set; }

    [DisplayName("Resource")]
    public string Name { get; set; }


    [DisplayName("URL")]
    [DataType(DataType.Url)]
    public string Url { get; set; }

    public int ResourceListId { get; set; }
    [DisplayName("In List")]
    public ResourceList ResourceList { get; set; }

    [DisplayName("Feed Url")]
    public string ContentFeedUrl { get; set; }

    public List<LearningResourceTopicTag> LearningResourceTopicTags { get; set; }
}

A collection of LearningResource objects are defined as a DbSet in the LibDbContext database context class:

public DbSet<LearningResource> LearningResources { get; set; }

The GetTop() service method in the LearningResourceService class defines a Query Tag with the TagWith() method, as shown below:

public async Task<List<LearningResource>> GetTop(int topX)
{
    var myItems =
    (from m in _context.LearningResources
        .Include(r => r.ResourceList)
        .TagWith($"This retrieves top {topX} Items!")
        orderby m.Id ascending
        select m)
    .Take(topX);

    return (await myItems.ToListAsync());
}

In the above query, the TagWith() method takes a single string value that can they be stored along with wherever the resultant SQL Queries are logged. This may include your persistent SQL Server database logs or Profiler logs that can be observed in real-time. It doesn’t affect what gets displayed in your browser.

This can be triggered by visiting the LearningResourcesController’s GetTop method, while passing in an integer value for topX. This causes the Index view to return the top “X” learning resources in a list. For example: if topX is set to 5, the resulting view will display 5 items in the displayed list.

Observing Query Tags in Logs

Using the SQL Server Profiler tool, the screenshot below shows how the Query Tag string defined in the code is outputted along with the SQL Query. Since topX is set to 5 in this example, the final string includes the value of topX inline within the logged text (more on formatting later).

SQL Server Profiler showing text from Query Tag
SQL Server Profiler showing text from Query Tag

From the code documentation, the TagWith() method “adds a tag to the collection of tags associated with an EF LINQ query. Tags are query annotations that can provide contextual tracing information at different points in the query pipeline.

Wait a minute… does it say “collection of tags”…? Yes, you can add a collection of tags! You can call the method multiple times within the same query. In your code, you could call a string of methods to trigger cumulative calls to TagWith(), which results in multiple tags being stored in the logs.

Formatting Query Tag Strings

You may have noticed that I used the $ (dollar sign) symbol in my Query Tag samples to include variables inline within the string. In case you’re not familiar with this language feature, the string interpolation feature was introduced in C# 6.

$"This retrieves top {topX} Items!"

You may also have  noticed that the profiler is showing the first comment in the same line as the leading text “exec sp_executesql” in the Profiler screenshot. If you want to add some better formatting (e.g. newline characters), you can use the so-called verbatim identifier, which is essentially the @ symbol ahead of the string.

@"This string has more
than 1 line!"

While this is commonly used in C# to allow newlines and unescaped characters (e.g. backslashes in file paths), some people may not be aware that you can use it in Query Tags for formatting. This operator allows you to add multiple newlines in the Query Tag’s string value. You can combine both operators together as well.

@$"This string has more than 1 line 
and includes the {topX} items!"

In an actual example, a newline produces the following results:

SQL Server Profiler, showing Query Tag text with newline
SQL Server Profiler, showing Query Tag text with newline

The above screenshot now shows multiline text from a Query Tag using newlines within the text string.

References

EF Core Relationships in ASP .NET Core 3.1

By Shahed C on February 3, 2020

This is the fifth of a new series of posts on ASP .NET Core 3.1 for 2020. In this series, we’ll cover 26 topics over a span of 26 weeks from January through June 2020, titled ASP .NET Core A-Z! To differentiate from the 2019 series, the 2020 series will mostly focus on a growing single codebase (NetLearner!) instead of new unrelated code snippets week.

Previous post:

NetLearner on GitHub:

In this Article:

E is for EF Core Relationships

In my 2018 series, we covered EF Core Migrations to explain how to add, remove and apply Entity Framework Core Migrations in an ASP .NET Core web application project. In this article, we’ll continue to look at the newer 2020 NetLearner project, to identify entities represented by C# model classes and the relationships between them.

NOTE: Please note that NetLearner is a work in progress as of this writing, so its code is subject to change. The UI web apps still needs work (and will be updated at a later date) but the current version has the following models with the relationships shown below:

NetLearner database diagram
NetLearner database diagram

Classes and Relationships

The heart of the application is the LearningResource class. This represents any online learning resource, such as a blog post, single video, podcast episode, ebook, etc that can be accessed with a unique URL.

public class LearningResource
{
    public int Id { get; set; }

    [DisplayName("Resource")]
    public string Name { get; set; }


    [DisplayName("URL")]
    [DataType(DataType.Url)]
    public string Url { get; set; }

    public int ResourceListId { get; set; }
    [DisplayName("In List")]
    public ResourceList ResourceList { get; set; }

    public ContentFeed ContentFeed { get; set; }

    public List<LearningResourceTopicTag> LearningResourceTopicTags { get; set; }
} 

The ContentFeed class represents the RSS Feed (or channel information) for an online resource, a URL that can be used to retrieve more information about the online resource, if available.

public class ContentFeed
{
    public int Id { get; set; }

    [DisplayName("Feed URL")]
    public string FeedUrl { get; set; }

    public int LearningResourceId { get; set; }
    public LearningResource LearningResource { get; set; }
}

The ResourceList class represents a logical container for learning resources in the system. It is literally a list of items, where the items are your learning resources.

public class ResourceList
{
    public int Id { get; set; }

    public string Name { get; set; }

    public List<LearningResource> LearningResources { get; set; }
} 

The TopicTag class represents a single “tag” value that can be used to categorize online resources. Possibly values could be “.NET Core”, “ASP.NET Core” and so on.

public class TopicTag
{
    public int Id { get; set; }

    [DisplayName("Tag")]
    public string TagValue { get; set; }

    public List<LearningResourceTopicTag> LearningResourceTopicTags { get; set; }
} 

At this point, you may have noticed both the LearningResource and TopicTag classes contain a List<T> property of LearningResourceTopicTag. If you browse the database diagram, you will notice that this table appears as a connection between the two aforementioned tables, to establish a many-to-many relationship. (more on this later)

The following diagram shows an example of how the a LearningResource (e.g. link to a doc/video) is a part of a ResourceList, while each LearningResource also has a link back to its root site, channel or RSS feed (via ContentFeed).

One to One

Having looked through the above entities and relationships, we can see that each LearningResource has a ContentFeed. This is an example of a 1-to-1 relationship. For example:

  • Learning Resource = Wake Up and Code! blog site
  • Content Feed = RSS Feed for blog site

In the two classes, we see the following code:

public class LearningResource
{
public int Id { get; set; }

[DisplayName("Resource")]
public string Name { get; set; }


[DisplayName("URL")]
[DataType(DataType.Url)]
public string Url { get; set; }

public int ResourceListId { get; set; }
[DisplayName("In List")]
public ResourceList ResourceList { get; set; }

public ContentFeed ContentFeed { get; set; }

public List<LearningResourceTopicTag> LearningResourceTopicTags { get; set; }
}
public class ContentFeed
{
public int Id { get; set; }

[DisplayName("Feed URL")]
public string FeedUrl { get; set; }

public int LearningResourceId { get; set; }
public LearningResource LearningResource { get; set; }
}

Each Learning Resource has a corresponding Content Feed, so the LearningResource class has a property for ContentFeed. That’s pretty simple. But in the  ContentFeed class, you don’t necessarily need a property pointing back to the  LearningResource . In fact, all you need is a  LearningResourceId property. EF Core will ensure that LearningResource.Id points to ContentFeed.LearningResourceId in the database. But to help with object-property navigation in your code, it is useful to include an actual LearningResource object in the ContentFeed class to point back to LearningResource.

One to One Relationship
One to One Relationship

Another way of looking at the One-to-One relationship is to view the constraints of each database entity in the visuals below. Note that both tables have an Id field that is a Primary Key (inferred by EF Core) while the ContentFeeds table also has a Foreign Key for the LearningResourceId field used for the constraint in the relationship.

LearningResources table
LearningResources table
ContentFeeds table
ContentFeeds table
One to One Relationship
One to One Relationship

One to Many

Next, let’s take a look at the One-to-Many relationship for each ResourceList that has zero or more LearningResources. For example:

  • Resource List = ASP .NET Core Blogs (parent container)
  • Learning Resource = ASP .NET Core A-Z Blog Series (single URL)

In the two classes, we see the following code:

public class ResourceList
{
public int Id { get; set; }

public string Name { get; set; }

public List<LearningResource> LearningResources { get; set; }
}
public class LearningResource
{
public int Id { get; set; }

[DisplayName("Resource")]
public string Name { get; set; }


[DisplayName("URL")]
[DataType(DataType.Url)]
public string Url { get; set; }

public int ResourceListId { get; set; }
[DisplayName("In List")]
public ResourceList ResourceList { get; set; }

public ContentFeed ContentFeed { get; set; }

public List<LearningResourceTopicTag> LearningResourceTopicTags { get; set; }
}

Each Resource List has zero or more Learning Resources, so the ResourceList class has a List<T> property for LearningResources. This is even simpler than the previously described 1-to-1 relationship. In the LearningResource class, you don’t necessarily need a property pointing back to the ResourceList. But once again, to help with object-property navigation in your code, it is useful to include an actual ResourceList object in the LearningResource class to point back to ResourceList.

One to Many Relationship
One to Many Relationship

Another way of looking at the One-to-Many relationship is to view the constraints of each database entity in the visuals below. Note that both tables have an Id field that is a Primary Key (once again, inferred by EF Core) while the ResourceLists table also has a Foreign Key for the  ResourceListsId field used for the constraint in the relationship.

One to Many Constraint
One to Many Constraint

Many to Many

Finally, let’s also take a look at a Many-to-Many relationship, for each TopicTag and LearningResource, either of which can have many of the other. For example:

  • Topic Tag = “ASP .NET Core” (tag as a text description)
  • Learning Resource = Specific blog post on site (single URL)

This relationship is a little more complicated than all of the above, as we will need a “join table” to connect the two tables in question. Not only that, we will have to describe the entity in the C# code with connections to both tables we would like to connect with this relationship.

In the two classes we would like to connect, we see the following code:

public class TopicTag
{
    public int Id { get; set; }

    [DisplayName("Tag")]
    public string TagValue { get; set; }

    public List<LearningResourceTopicTag> LearningResourceTopicTags { get; set; }
} 
public class LearningResource
{
public int Id { get; set; }

[DisplayName("Resource")]
public string Name { get; set; }


[DisplayName("URL")]
[DataType(DataType.Url)]
public string Url { get; set; }

public int ResourceListId { get; set; }
[DisplayName("In List")]
public ResourceList ResourceList { get; set; }

public ContentFeed ContentFeed { get; set; }

public List<LearningResourceTopicTag> LearningResourceTopicTags { get; set; }
}

Next, we have the LearningResourceTopicTag class as a “join entity” to connect the above:

public class LearningResourceTopicTag
{
    public int LearningResourceId { get; set; }
    public LearningResource LearningResource { get; set; }

    public int TopicTagId { get; set; }
    public TopicTag TopicTag { get; set; }

}

This special class has the following properties:

  • LearningResourceId: integer value, pointing back to LearningResource.Id
  • LearningResource: optional “navigation” property, reference back to connected LearningResource entity
  • TopicTagId: integer value, pointing back to TopicTag.Id
  • TopicTag:  optional “navigation” property, reference back to connected TopicTag entity

To learn more about navigation properties, check out the official docs at:

Many to Many Relationship
Many to Many Relationship

Another way of looking at the Many-to-Many relationship is to view the constraints of each database entity in the visuals below. Note that the two connected tables both have an Id field that is a Primary Key (yes, inferred by EF Core!) while the LearningResourceTopicTag table has a Composite Key for the TopicTagId and LearningResourceId fields used for the constraints in the relationship.

Constraints for LearningResources
Constraints for LearningResources
 Constraints for TopicTags
Constraints for TopicTags

The composite key is described in the LibDbContext class inside the OnModelCreating() method:

public class LibDbContext : IdentityDbContext
{
    ...
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
       ...
       modelBuilder.Entity<LearningResourceTopicTag>()
        .HasKey(lrtt => new { lrtt.LearningResourceId, lrtt.TopicTagId });
    }
}

Here, the HasKey() method informs EF Core that the entity LearningResourceTopicTag has a composite key defined by both LearningResourceId and TopicTagId.

References

For more information, check out the list of references below.

For detailed tutorials that include both Razor Pages and MVC, check out the official tutorials below:

ASP .NET Core code sharing between Blazor, MVC and Razor Pages

By Shahed C on December 16, 2019

In This Article:

Introduction

It’s been a while since I’ve published a standalone blog post on WakeUpAndCode.com. If you’ve been following the posts on this website, you may be familiar with my 2018 (surprise!) Happy New Year series and 2019 A-Z series on various ASP .NET Core topics. This led to a free ebook, which itself was generated by a .NET Core Worker Service.

Going forward, you can expect a 2020 A-Z series that will use ASP .NET Core 3.1 (LTS). The upcoming series will contain new and improved versions of the topics explored in the 2019 series, including Build 2020 coverage.

For now, this one-off blog post will discuss code-sharing for ASP .NET Core developers. For demonstrative purposes, the sample code accompanying this article includes code that is derived from the code snippets provided on the following blog:

Kudos to the author (aka PI Blogger) for this great intro article!

Why Share Code Across Projects/Assemblies?

There are multiple reasons why you may want to share code between multiple projects/assemblies.

  1. Code reuse: This should be pretty self-explanatory. You shouldn’t have to rewrite the same code more than once. Placing reusable code in a shared library enables code reuse.
  2. Multiple front-ends: In the sample code, there are multiple web apps, all using the same data layer. Splitting into separate assemblies allows you to develop multiple web apps in their own projects/assemblies.
  3. Separate deployments: You can deploy each assembly independent of one another.

Even if you’re just working on a single web app (just Blazor, or a web app that combines Blazor+MVC+Razor Pages), you can still benefit from this type of “physical” code separation. Note that this approach is not required for “separation of concerns”. The nature of ASP .NET Core web applications make them possible to implement separation of concerns, even if everything is in a single project (such as the one generated by the official VS2019 project templates).

NOTE: This article will focus on the creation of a shared library project to hold a shared database context, EF Core migrations, models and services. In your application, you can go further by separating your domain objects and related items into their own project/assembly.

For an official guide on ASP .NET Core architecture, download this free ebook and its sample code. The eShopOnWeb sample includes the “business layer” with domain entities under ApplicationCore, the “data layer” with data context + migrations under Infrastucture, and the “presentation layer” with its MVC components under Web.

Also, here’s a recent quote from author Steve Smith:

  • Tweet: https://twitter.com/ardalis/status/1207301716347150336
  • Quote: “Separating things by project ensures decisions about dependency direction are enforced by the compiler, helping avoid careless mistakes. Separating into projects isn’t solely about individually deploying or reusing assemblies.”

Creating a shared library

The quickest way to create a shared library project is to use the built-in project templates. Create a project of type .NET Standard 2.1 using either Visual Studio 2019 or CLI commands for use with VS Code.

To add the new project in Visual Studio 2019:

  1. Add | New Project
  2. Select the template for Class Library (.NET Standard)
  3. Click Next
  4. Name your project and select a location
  5. Click Create
Add New Project dialog

Verify that the shared library is a Class Library project targeting .NET Standard 2.1. Check out the official docs to learn more about how to pick a version of .NET Standard for your class libraries.

To verify the target version in Visual Studio 2019:

  1. Right-click your shared library project in Solution Explorer
  2. Select Properties in the popup context menu
  3. In the Application section, select a “Target framework” value of “.NET Standard 2.1”.
  4. Edit your .csproj project file manually to verify that the correct target framework is being used.
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>

If using the .NET CLI, type the following command:

>dotnet new classlib -f netstandard2.1

As of .NET Core 3.0, Entity Framework Core is now available via NuGet. As a result, you must add the following packages manually.

  • Microsoft.EntityFrameworkCore
  • Microsoft.AspNetCore.Identity.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer

To add EF Core in Visual Studio 2019:

  1. In Solution Explorer, right-click your shared library project
  2. Select “Manage NuGet Packages…”
  3. Search for the aforementioned packages and install v3.1 for each
EF Core Nuget Packages

To create a new database context in the shared library project:

  1. Create a “Data” folder at the root level of the project folder
  2. In the Data folder, create a new public class named “LibDbContext” that inherits from “IdentityDbContext”
  3. Create a “Models” folder at the root level of the project folder
  4. In the Models folder, add one or more model classes, to be used by your web application project(s)
  5. In the context class, add one or more DbSet<T> properties

Your shared context class LibDbContext should now look like the following snippet:

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using SharedLib.Models;

namespace SharedLib.Data
{
public class LibDbContext : IdentityDbContext
{
public LibDbContext(DbContextOptions<LibDbContext> options)
: base(options)
{
}

protected LibDbContext()
{

}

public DbSet<CinematicItem> CinematicItems { get; set; }

}
}

In this case, the one DbSet property represents a collection of CinematicItems defined in its own CinematicItem model class file:

using System;

namespace SharedLib.Models
{
public class CinematicItem
{
public int Id { get; set; }

public string Name { get; set; }

public string Description { get; set; }

public int Phase { get; set; }

public DateTime ReleaseDate { get; set; }
}
}

Note that the new database context in the shared library is a replacement for any database context you may already have in your web app projects. In fact, you’ll have to edit your Startup.cs file in each web app project to ensure that it is using the correct database context.

Using the Shared Library

If you are starting a brand new web project, you can start with an auto-generated template. You could create an empty web project and add everything manually as needed. But it may be easier to start with a standard web template and remove/edit items as necessary.

To create a new web project in Visual Studio 2019:

  1. Add | New Project
  2. Select the template
    1. For Blazor, select Blazor App
    2. For MVC or Razor Pages, select ASP .NET Core Web Application
  3. Click Next
  4. Name your project and select a location
  5. Click Create
  6. Select .NET Core, ASP .NET Core 3.1, and a project template
    1. For Blazor, select Blazor Server App
    2. For Razor Pages, select Web Application
    3. For MVC, select Web Application (Model-View-Controller)
  7. For Authentication, change “No Authentication” to “Individual User Accounts”
  8. Under Advanced, leave the checkbox checked for “Configure for HTTPS”
New Project: Web Application
New Project: Blazor Server App

Following the above steps will add a new database context and an initial migration. Since we will be using our shared library instead, let’s do some cleanup in each web project you created.

In each web project, add the Shared Library as a dependency:

  1. In Solution Explorer, right-click Dependencies for a web project
  2. Click Add Reference under Dependencies
  3. Select the shared library project
  4. Click Ok
  5. Repeat for each web project

In each web project, update the Startup.cs class:

  1. Replace any mentions of ApplicationDbContext with LibDbContext
  2. Expand the UseSqlServer method call to refer to the connection string and db context in the shared assembly
services.AddDbContext<LibDbContext>(options =>
{
options
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
assembly =>
assembly.MigrationsAssembly
(typeof(LibDbContext).Assembly.FullName));
});

services.AddDefaultIdentity<IdentityUser>(
options =>
options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<LibDbContext>();

Perform some additional cleanup in each web project:

  1. Delete the template-generated ApplicationDbContext class
  2. Delete any initial migrations in the Migrations folder
  3. In the Startup.cs class, remove any using statements that mention the .Data namespace in your web project
  4. Add a using statement referring to the .Data namespace in your shared library project, e.g. SharedLib.Data
  5. Make a similar change in your partial view “_ViewImports.chstml” if applicable
  6. If you have more than one web project, use the ConnectionString value from the first appsettings.json file and reuse it in the other web app projects.
  7. BUT WAIT: beyond any initial sample, always use app secrets during development to avoid connection strings in appsettings.json files. For Azure-deployed web projects, use Key Vault or environment variables in your App Service.

Running the Samples

In order to run the web app samples, clone the following repository:

Here, you will find 4 projects:

  1. SharedLib: shared library project
  2. WebAppBlazor: Blazor server-side web project
  3. WebAppMvc: MVC web project
  4. WebAppPages: Razor Pages web project

To create a local copy of the database:

  1. Open the solution file in Visual Studio 2019
  2. In the Package Manager Console panel, change the Default Project to “SharedLib” to ensure that EF Core commands are run against the correct project
  3. In the Package Manager console, run the Update-Database command
  4. Verify that there are no errors upon database creation

To run the samples from Visual Studio 2019:

  1. Run each web project one after another
  2. Navigate to the Cinematic Items link in the navigation menu
  3. Add/Edit/Delete items in any of the web apps
  4. Verify that your data changes are reflected no matter which web app you use
Sample: Blazor Web App
Sample: MVC Web App
Sample: Razor Pages Web App

NOTE: During Blazor development, editing a Razor component may not always trigger the proper Intellisense help in the containing Page. You may have to clean+rebuild solution or even reopen the solution in VS2019.

Conclusion

In this article, we covered the following:

  • Creation of a shared library project for use in one or more ASP .NET Core web apps
  • Some reasons for such an approach
  • Steps required to use the shared library
  • Sample projects to see the shared library in action

References

Summarizing Build 2019 + SignalR Service for ASP .NET (Core) Developers

By Shahed C on May 14, 2019

This is the nineteenth of a series of posts on ASP .NET Core in 2019. In this series, we’ll cover 26 topics over a span of 26 weeks from January through June 2019, titled A-Z of ASP .NET Core!

ASPNETCoreLogo-300x267 A – Z of ASP .NET Core!

In this Article:

S is for Summarizing Build 2019 (and SignalR Service!)

For the letter S, I was originally thinking of an article dedicated to SignalR Service. However, Microsoft’s annual Build Conference just happened at the time of this writing. So this week’s post will focus on Summarizing Build 2019 for ASP .NET (Core) Developers, followed by a sneak peek of SignalR Service at the end.

The biggest news for .NET Developers is that .NET Core is the future of .NET, going forward. Furthermore, .NET Core vNext will be named .NET 5, a unified platform for all .NET developers (.NET Framework, Xamarin/Mono and .NET Core).

The GIF below was generated from the .NET Overview session at Build 2019 to illustrate this future:

.NET Roadmap, 2019 and Beyond

.NET Roadmap, from 2014 through 2016, then 2019 and Beyond

Build 2019 for .NET Developers

The quickest to way to catch up on Build 2019 content is to watch all the relevant videos. But how do you know which ones to watch? Well, if you’re a .NET developer, I’ve put together a handy video playlist specifically for .NET Developers (including ASP .NET Core Developers).


Your key takeaways from new announcements should include:

  • .NET Core is the future of .NET: If you’ve already started working with .NET Core, that’s great! If you’re starting a new project, you should consider .NET Core.
  • .NET Framework will continue to be supported: If you have any existing applications on .NET Framework (Windows-only), you can keep those on .NET Framework.
  • .NET Releases will become more predictable: Starting with .NET 5.0, there will be 1 major release every year,  after which each even-numbered release (6.0, 8.0, etc) will come with LTS (Long-Term Support).

In 2019, the expected schedule for .NET Core 3.x is as follows:

  • July 2019: .NET Core 3.0 RC (Release Candidate)
  • September 2019: .NET Core 3.0 (includes ASP .NET Core 3.0)
  • November 2019: .NET Core 3.1 (LTS)

In 2020 and beyond, the expected schedule for .NET Core 5+ is shown below:

  • Early to mid 2020: .NET 5.0 Preview 1
  • November 2020: .NET 5.0
  • November 2021: .NET 6.0 (LTS)
  • November 2022: .NET 7.0
  • November 2023: .NET 8.0 (LTS)

Minor releases (e.g. 5.1, etc) will be considered only if necessary. According to the official announcement, the first preview of .NET 5.0 should be available within the first half of 2020.

NOTE: The upcoming .NET 5.0 should not be confused with the so-called “ASP .NET 5” which was the pre-release name for ASP .NET Core 1.0 before the product was first released in 2016. Going forward, the name of the unified framework is simply .NET 5, without the need for a trailing “Core” in the name.

What’s New in .NET Core 3.0 (Preview 5)

As of May 2019, .NET Core 3.0 is in Preview 5, is expected to be in RC in July 2019, to be followed by a full release in September 2019. This includes ASP .NET Core 3.0 for web development (and more!). For my first look at .NET Core 3.0, you may browse through this earlier post in this series:

The primary themes of .NET Core 3.0 are:

  1. Windows desktop apps: while this is usually not a concern for ASP .NET Core web application developers, it’s good to know that Windows developers can start using .NET Core right away.
  2. Full-stack web dev: Blazor is no longer experimental and its latest preview allows developers to use C# for full-stack web development. More info at: https://blazor.net
  3. AI & ML: Not just buzzwords, Artificial Intelligence and Machine Learning are everywhere. ML.NET 1.0 is now available for C# developers to join this exciting new area of software development. More info at: dot.net/ml
  4. Big Data: .NET for Apache Spark is now in Preview, available on Azure Databricks and Azure HDInsight. More info at: dot.net/spark

For more information on Blazor, you may browse through  this earlier post in this series:

A lot has changed with Blazor in recent months, so the above post will be updated after Core 3.0 is released. In the meantime, check out the official Blazor session from Build 2019.


What’s New in ASP.NET Core 3.0 (Preview 5)

What about ASP .NET Core 3.0 in Preview 5? In the Preview 5 announcement, you can see a handful of updates for this specific release. This includes the following:

  • Easy Upgrade: to upgrade from an earlier preview, update the package reference in your .csproj project file to the latest version (3.0.0-preview5-19227-01)
  • JSON Seralization: now includes support for reading/writing JSON using System.Text.Json. This is part of the built-in JSON support mentioned in the official writeup for .NET Core 3.0 Preview 5.
  • Integration with SignalR: Starting with this release, SignalR clients and servers will now use the aforementioned System.Text.Json as the default Hub protocol. You can read more about this in the SignalR section of the Migration guide for 2.x to 3.0.
  • Continued NewtonsoftJson support: In case you need to switch back to NewtonSoft.Json (previously the default option for the SignalR Hub), the instructions are provided in the aforementioned Migration guide and the announcement. Note that NewtonSoft.Json needs to be installed as a NuGet package.

There has been a lot of development in ASP .NET Core 3.0 in previous Preview releases, so you can refer to my earlier posts in the series for more info:

Here are links to all preview notes if you need a refresher on what was new in each Preview:

NOTE: Changes from each preview to the next is usually cumulative. However, please note that Blazor went from experimental to preview in April 2019, and is now called Blazor on both the client and server. Previously, server-side Blazor was temporarily renamed to Razor Components, but then it was changed back to server-side Blazor.

What’s Next for .NET Core (.NET Core vNext = .NET 5!)

So, what’s next for .NET Core? First of all, the next major version won’t be called .NET Core, as we now know. With the upcoming release of .NET 5, you can now rest assured that all your investment into .NET Core will carry over into the future unified release.

Imagine taking the cross-platform .NET Core and bringing in the best of Mono for a single BCL (Base Class Library implementation). You may recall that .NET Standard was introduced when there were multiple versions of .NET (Framework, Mono/Xamarin and Core). Going forward, .NET Standard will continue to exist and .NET 5 will adhere to .NET Standard.

DotNet5-Layers-Heading

Compare the unified diagram with the various versions of .NET Framework, .NET Core and Mono over the years:

DotNet-VersionHistory

Note that not everything in the world of .NET today will make it into .NET 5. Not to worry though, as there are various recommended alternatives for all .NET developers. Take the following technologies, for example:

  • Web Forms: As you may have noticed, ASP .NET Web Forms have not been ported to ASP .NET Core. Instead of Web Forms, developers may consider Blazor as their choice of web application development.
  • WCF: Although Web API has been included in ASP .NET Core, there is no option for WCF. Going forward, you may use gRPC as an alternative.

Migration Guides for the above scenarios will be provided at a later date.

EF 6.3 for .NET Core, SqlClient & Diagnostics

In addition to ASP .NET Core itself, there are other tools and technologies that may be useful for ASP .NET Core developers. That may include (but is not limited to) the following):

  • Entity Framework 6.3: In addition to the EF Core running on .NET Core, EF 6.x was known to run on the Windows-only .NET Framework 4.x but not on .NET Core. Going forward, EF 6.3 will run on .NET Core 3.0 across platforms.
  • SqlClient: Instead of replacing the existing System.Data.SqlClient package directly, the new Microsoft.Data.SqlClient (available on NuGet) will support both .NET Core and .NET Framework.
  • .NET Core Diagnostic Tools: Making use of .NET Core Global Tools, a new suite of tools will help developers with diagnostics and troubleshooting ofperf issues.

From the tools‘ GitHub page, the following tools are currently available, with the following descriptions:

  • dotnet-dump: “Dump collection and analysis utility.”
  • dotnet-trace: “Enable the collection of events for a running .NET Core Application to a local trace file.”
  • dotnet-counters: “Monitor performance counters of a .NET Core application in real time.”

SignalR Service (Sneak Peek)

Finally, let’s take a quick peek at the all-new SignalR Service.

SignalR-Service-Portal

  • Who can use this: Web developers who want to build real-time features can get started with a variety of official Quickstart guides: ASP .NET Core, JavaScript, C#, Java and REST API

If you’re already familiar with using SignalR, switching to using Azure SignalR Service is as easy as 1-2-3.

  1. Append a call to .AddAzureSignalR() to AddSignalR() in the ConfigureServices() method of your Startup class.
  2. Replace the call to UseSignalR() with a call to UseAzureSignalR() in your Configure() method
  3. Ensure that your environment’s connection string is set correctly for the key “Azure:SignalR:ConnectionString“.

In the ConfigureServices() method, this is what your code should look like:

public void ConfigureServices(IServiceCollection services)
{
   // ...
   services.AddMvc();
   services.AddSignalR().AddAzureSignalR();
} 

In the Configure() method, this is what your code should look like:

app.UseAzureSignalR(routes =>
{
 routes.MapHub<HubClassName>("/HubRouteName");
});

Your connection string (in your environment or User Secrets) may look like the following:

"Azure:SignalR:ConnectionString": "Endpoint=<yourendpoint>;AccessKey=<yourkey>;"

For a detailed tutorial for ASP .NET Core developers, try this official guide:

After the A-Z weekly series is complete, stay tuned for monthly blog posts about cool things .NET developers can do in Azure. This will include a more in-depth look at SignalR Service in a future writeup, including guidance for both web and mobile developers.

References for Build 2019 Announcements

References for SignalR Service

 

Query Tags in EF Core for ASP .NET Core Web Apps

By Shahed C on April 29, 2019

This is the seventeenth of a series of posts on ASP .NET Core in 2019. In this series, we’ll cover 26 topics over a span of 26 weeks from January through June 2019, titled A-Z of ASP .NET Core!

ASPNETCoreLogo-300x267 A – Z of ASP .NET Core!

In this Article:

Q is for Query Tags in EF Core

Query Tags were introduced in Entity Framework (EF) Core 2.2, as a way to associate your LINQ Queries with SQL Queries. This can be useful when browsing log files during debugging and troubleshooting. This article explains how Query Tags work, how to find the output and how to format the text strings before displaying them.

Blog-Diagram-QueryTags

NOTE: You may have read that Query Types have been renamed to entities without keys, but please note that Query Types (introduced in EF Core 2.1) are not the same thing as Query Tags.

As of ASP .NET Core 3.0 Preview 1, EF Core must be installed separately via NuGet (e.g. v3.0.0-preview4.19216.3), as it is no longer included with the ASP .NET Core shared framework. Also, the dotnet ef tool has to be installed as a global/local tool, as it is no longer part of the .NET Core SDK. For more information, see the official announcement for Preview 4, where it was first mentioned:

Implementing Query Tags

To follow along, take a look at the sample project on Github:

Web Query Tag Sample: https://github.com/shahedc/WebAppWithQueries

The sample includes a simple model called MyItem, with a few basic fields:

public class MyItem
{
   public int Id { get; set; }
   public string MyItemName { get; set; }
   public string MyItemDescription { get; set; }
}

A collection of MyItem objects are defined as a DbSet in the ApplicationDbContext:

public DbSet<WebAppWithQueries.Models.MyItem> MyItems { get; set; }

The QueriedData() action method in the MyItemController defines a Query Tag with the TagWith() method, as shown below:

public async Task<IActionResult> QueriedData()
{
   var topX = 2;
   var myItems =
   (from m in _context.MyItems.TagWith($"This retrieves top {topX} Items!")
   orderby m.Id ascending
   select m).Take(topX);

   return View(await myItems.ToListAsync());
}

In the above query, the TagWith() method takes a single string value that can they be stored along with wherever the resultant SQL Queries are logged. This may include your persistent SQL Server database logs or Profiler logs that can be observed in real-time. It doesn’t affect what gets displayed in your browser.

AspNetCore-QueryTags-Browser

Observing Query Tags in Logs

Using the SQL Server Profiler tool, the screenshot below shows how the Query Tag string defined in the code is outputted along with the SQL Query. Since topX is set to 2, the final string includes the value of topX inline within the logged text (more on formatting later).

AspNetCore-QueryTags-Profiler

From the code documentation, the TagWith() method “adds a tag to the collection of tags associated with an EF LINQ query. Tags are query annotations that can provide contextual tracing information at different points in the query pipeline.

Wait a minute… does it say “collection of tags”…? Yes, you can add a collection of tags! You can call the method multiple times within the same query. In the QueriedDataWithTags() action of method the MyItemController class, you can call a string of methods to trigger cumulative calls to TagWith(), which results in multiple tags being stored in the logs.

AspNetCore-QueryTags-Profiler-More

Formatting Query Tag Strings

You may have noticed that I used the $ (dollar sign) symbol in my Query Tag samples to include variables inline within the string. In case you’re not familiar with this language feature, the string interpolation feature was introduced in C# 6.

$"This retrieves top {topX} Items!"

You may also have  noticed that the profiler is showing the first comment in the same line as the leading text “exec sp_executesql” in the Profiler screenshot. If you want to add some better formatting (e.g. newline characters), you can use the so-called verbatim identifier, which is essentially the @ symbol ahead of the string.

@"This string has more
than 1 line!"

While this is commonly used in C# to allow newlines and unescaped characters (e.g. backslashes in file paths), some people may not be aware that you can use it in Query Tags for formatting. This operator allows you to add multiple newlines in the Query Tag’s string value. You can combine both operators together as well.

@$"This string has more than 1 line 
and includes the {topX} variable!"

In an actual example, a newline produces the following results:

AspNetCore-QueryTags-Profiler-Newlines

The above screenshot now shows the text from multiple Query Tags each on their own new line. As before, both of them were evaluated during the execution of a single SQL statement.

References