Logging in EF Core 2.2 Has a Simpler Syntax–More like ASP.NET Core

Logging EF Core’s memory operations and SQL operations has evolved a few times since EF Core arrived. It takes advantage of the same underlying features that ASP.NET Core uses. If you are using ASP.NET Core, logging is baked in and it is really simple to turn it on for EF Core and add filtering. See Shawn Wildermuth’s blog post about EF Core logging in ASP.NET Core.

But if you aren’t using ASP.NET Core, it’s a little more complicated. Not terribly, but still there’s some extra work to do. It involves setting up an ILoggerFactory in your DbContext and defining any filters at the same time.

I wrote an article about this (with the focus being on taking advantage of the various available filters for EF Core logging) in MSDN Magazine earlier this …oh wait, it’s Jan 1, so I can say “last  year”.  Data Points – Logging SQL and Change-Tracking Events in EF Core. I also used it heavily in my EF Core 2 Getting Started course, EF Core 2:Mappings and EF Core 2.1: What’s New courses on Pluralsight. (Note that I’ve updated the sample code for the Getting Started course to EF Core 2.2 and put it on GitHub at github.com/julielerman/PluralsightEFCore2GettingStarted)

My article and courses were using Console apps to demonstrate EF Core behavior and therefore the ConsoleLoggerProvider to tie the logger to the console. Note that the Data Points article contains a lot of good details about the various types of filtering. So you can use the new syntax (below) to specify that there should be a filter, but be sure to read the article to learn about the flavors of filtering and what type of details you’ll be able to see based on the choices you make.

But the logging API has continued to evolve and is providing some of the same shortcuts that ASP.NET had created. And the ConsoleLoggerProvider has been deprecated. The API is not part of EF Core. It’s part of .NET Core. Both EF Core and ASP.NET Core use it.

If you are using EF Core 2.2, the syntax has changed (simplified) and it’s going to get even more streamlined in 3.0.

In fact, if you use the earlier syntax with 2.2, you’ll get a warning about the ConsoleLoggerProvider:

Obsolete(“This method is obsolete and will be removed in a future version. The recommended alternative is using LoggerFactory to configure filtering and ConsoleLoggerOptions to configure logging options.”)

For a point of comparison, here is an example of using theold syntax to turn on logging, only show logs related to database commands and only show messages that are tagged as “Information”.

EF Core 2.0 & 2.1 Logic

public static readonly LoggerFactory MyConsoleLoggerFactory
            = new LoggerFactory(new[] {
              new ConsoleLoggerProvider((category, level)
                => category == DbLoggerCategory.Database.Command.Name
               && level == LogLevel.Information, true) });

Once your logger factory field is defined in the context class you tell the DbContext to use it when configuring.

protected override void OnConfiguring
  (DbContextOptionsBuilder optionsBuilder)
{
  var connectionString = 
    ConfigurationManager.ConnectionStrings["WPFDatabase"].ToString();
  optionsBuilder
    .UseLoggerFactory(MyConsoleLoggerFactory)
    .EnableSensitiveDataLogging(true)
    .UseSqlServer(connectionString);
}

So it’s the creation of the logger factory whose syntax is a little convoluded. The newer API follows how ASP.NET Core lets you filter with an AddFilter method that takes the filters as parameters. No lambdas needed. Also configuring the filter is a separate bit of logic that tellig the logger that it should be tied to the console.

EF Core 2.2 Logic

With EF Core 2.2, you can set up the logger factory in the constructor or another method as long as it’s available when you are configuring the option builder. I’m creating it in a method then using that method as a parameter of UseLoggerFactory. I’m still filtering on showing only database commands and log details flagged as Information.

private ILoggerFactory GetLoggerFactory()
{
  IServiceCollection serviceCollection = new ServiceCollection();
  serviceCollection.AddLogging(builder =>
         builder.AddConsole()
                .AddFilter(DbLoggerCategory.Database.Command.Name, 
                           LogLevel.Information)); 
  return serviceCollection.BuildServiceProvider()
          .GetService<ILoggerFactory>();
}

and then I’m calling GetLoggerFactory() in the UseLogging method on the optionsbuilder:

optionsBuilder.UseLoggerFactory(GetLoggerFactory())

Packages and References

In order to use the AddConsole() method, you still have to use the Microsoft.Extensions.Logging.Console package that the earlier ConsoleLoggerProvider was in. However, you do not need a using statement for the namespace (as you did for the ConsoleLoggerProvider).

Getting the SQL Server 2019 for Linux CTP2.0 Docker Image

If you are used to pulling the mssql-server images from the microsoft repository, e.g.,

docker pull microsoft/mssql-server

that won’t work for the 2019 CTP.

I was able to repull (aka update) using the former repository, but that wasn’t working for the CTP whose tag is vNext-CTP2.0-ubuntu.

I finally noticed the new docker pull command on the docker hub page for the image

It says: docker pull mcr.microsoft.com/mssql/server

So the command for pulling the CTP using it’s tag is as follows:

docker pull mcr.microsoft.com/mssql/server:vNext-CTP2.0-ubuntu

 

Grateful for the 16th MVP Award from Microsoft

 

15 years ago, July 1, 2003, I got a surprise in the mail. An envelope with this sheet of paper welcoming me to the Microsoft MVP program for the things I had done in the community in the past year. Believe it or not, this first award was triggered via Microsoft Academics because one of the things I’d been doing with INETA was working with college students.

With that piece of paper fresh out of the envelope, I jumped in my car and drove 15 miles to the job site where my husband was working on a roof, made him come down from the roof so I could show him. I was that excited and surprised. Even if the letter had not been completely out of the blue, had someone contacted me to fill out a form as the MVPs do these days, I am confident I would have been just as surprised and excited.

I’ve been honored to be awarded every July 1 since then for various things I do to try to shorten the learning curve for other programmers by sharing what I’ve learned. I don’t take the award for granted. I just follow my heart and do what I want to do and if it happens to be what they are looking for when the assessments are being done, then I’m grateful for that particular recognition.

I know it was a hard week for a lot of long term MVPs who were not being re-awarded this year and for the MVP leads (aka Community Program Managers (aka CMPs)) who made personal calls to each and every one of those MVPs to try to let them know as gently as possible. Given that, I’m extra grateful to continue to be part of the program for the July 2018 – June 2019 period.

My First Newsletter: New Course, Pluralsight Discount, Workshops & More

I recently decided it was time to start a newsletter to be sure people who are interested don’t miss out on things like new Pluralsight courses or articles that I’ve published, conferences I’m speaking at and even workshops that I’m teaching. I figure with 26K twitter followers, there might be a few people interested.

Read the June newsletter

Subscribe to my newsletter

I just sent out the first newsletter yesterday. Here are some highlights:

 

 

 

Pluralsight Subscriptions On Sale This Week!

Pluralsight is having a summer sale on annual subscriptions – $100 off (i.e. $199 for an entire year’s access to the entire library) which is a pretty amazing price for what you’re getting. Heck the regular price of $299 for a full year is amazing when you compare it to the cost of almost any type of training from the expert-authors). Anyway, I don’t have to tell you, you already know!

The $199 price is for new subscriptions, renewing  existing subscriptions and even converting from a monthly subscription!

EF Core’s IsConfigured and Logging

I got a little confused about some behavior today and finally realized my mistake so thought I would share it. This mostly happens in demo apps that I’m building that are not using  ASP.NET Core.

In these cases, I typically stick the DbContext provider configuration in the OnModelConfiguring method. For example, if I’m using SQLite, then I would specify that in the method as such:

protected override void OnConfiguring
 (DbContextOptionsBuilder optionsBuilder)
{
   optionsBuilder.UseSqlite (@"Filename=Data/PubsTracker.db");
}

I also have been using the logging factory a lot. After defining it, I also configure it. I hadn’t thought much about where I was placig it so added it in randomly.

protected override void OnConfiguring 
  (DbContextOptionsBuilder optionsBuilder)
{
  optionsBuilder.UseLoggerFactory (MyConsoleLoggerFactory);
  optionsBuilder.UseSqlite (@"Filename=Data/PubsTracker.db");
}

Then I added in some tests to had to avoid the SQLite provider if the InMemory provider was already configured, so I wrapped the UseSqlite method with a check to see if the options builder was already configured.

protected override void OnConfiguring
  (DbContextOptionsBuilder optionsBuilder)
{
  optionsBuilder.UseLoggerFactory (MyConsoleLoggerFactory);
  if(!optionsBuilder.IsConfigured)
  {
    optionsBuilder.UseSqlite (@"Filename=Data/PubsTracker.db");
  }
}

But my logic wasn’t working. I was running some migrations but they were suddenly not recognizing the UseSqlite method. I’ve used this pattern so many times. It took me a while to realize what was going on. The UseLoggerFactory is a configuration!

I just had to move the UseLoggerFactory logic after the IsConfigured check and all was well.

This is one of those dumb things that seems so silly you wouldn’t imagine someone else would make such a mistake. But since it bit me, I thought it was worth sharing mostly for the sake of the next coder who is trying to solve the same problem.

Defining a Defining Query in EF Core 2.1

I have to cut out some text from a too-long article I’ve written for a magazine (links when it’s published), so here is a simple example of using the new ToQuery method for creating a defining query in EF Core 2.1 (currently in Preview 2).

ToQuery is associated with the new Query Type feature that allows you to use types that are not mapped to a table in the database and are therefore not true entities, don’t require a key and are not change tracked.

I’m starting with a simple model that includes these two entities, which are mapped to tables in my DbContext.

public class Team
    {
        public int TeamId { get; set; }
        public string Name { get; set; }
        public string TwitterAlias { get; set; }
        public List Members { get; set; }
    }

    public class TeamMember
    {
        public int TeamMemberId { get; set; }
        public string Name { get; set; }
        public string Role { get; set; }
        public int TeamId { get; set; }
        public TimeSpan TypicalCommuteTime { get; private set; }
        public void CalculateCommuteTime (DateTime start, DateTime end)
        {
            TypicalCommuteTime = end.Subtract(start);
        }
    }

You’ll need to pre-define the type being used for the defining query, mine will have the Name and TypicalCommuteTime for the team member.

public class TeamCommute
{
   public TeamCommute(string name, TimeSpan commuteTime) 
  {
    Name = name;
    TypicalCommuteTime = commuteTime;
  }
  public string Name { get; set; }
  public TimeSpan TypicalCommuteTime { get; set; }
}

You can define queries directly in OnModelBuilding using either raw sql with FromSql or a LINQ query inside a new method called ToQuery. Here’s an example of using a Query type with a defining query and Linq:

modelBuilder.Query<TeamCommute>()   .ToQuery(() => 
   TeamMembers.Select(m => new TeamCommute( m.Name, m.TypicalCommuteTime ) )

With this query defined on the TeamCommute class, you can now use that in queries in your code for example:

var commutes = context.Query<TeamCommute>().ToList();

Keep I mind that you can’t define both a ToQuery and a ToView mapping on the same type.

New Pluralsight Course! EF Core 2: Getting Started

I’ve recently published my 19th course on Pluralsight.com: Entity Framework Core 2: Getting Started.

It’s 2hrs 40 minutes long and focuses on the basics.

This is using EF Core 2.0.1 in Visual Studio 2017.

Future plans: I’ve begun working on an intermediate level course to follow up and have others in the pipeline…such as a course to cover features of EF Core 2.1 when it gets released (I will wait until it has RTMd for stability) and other advanced topics. I am also planning to do a cross-platform version using VS Code on macOS because that’s my fave these days.

If you are not a Pluralsight subscriber, send me a note and I can give you a 30-day trial so you can watch the course. Be warned: the trial is akin to a gateway drug to becoming a subscriber.

Here is the table of contents for the course:

Introducing a New, Lighter Weight Version of EF   32m 40s
Introduction and Overview
What Is Entity Framework Core?
Where You Can Build and Run Apps with EF Core
How EF Core Works
The Path From EF6 to EF Core to EF Core
EF Core 2 New Features
Looking Ahead to EF Core 2.1 and Beyond
Review and Resources

Creating a Data Model and Database with EF Core    42m 36s
Introduction and Overview
Setting up the Solution
Adding EF Core with the NuGet Package Manager
Creating the Data Model with EF Core
Specifying the Data Provider and Connection String
Understanding EF Core Migrations
Adding Your First Migration
Inspecting Your First Migration
Using Migrations to Script or Directly Create the Database
Recreating the Model in .NET Core
Adding Many-to-many and One-to-one Relationships
Reverse Engineering an Existing Database
Review and Resources

Interacting with Your EF Core Data Model 34m 11s
Introduction and Overview
Getting EF Core to Output SQL Logs
Inserting Simple Objects
Batching Commands When Saving
Querying Simple Objects
Filtering Data in Queries
Updating Simple Objects
Disconnected Updates
Deleting Objects with EF Core
Review and Resources

Querying and Saving Related Data   20m 49s
Introduction and Overview
Inserting Related Data
Eager Loading Related Data
Projecting Related Data in Queries
Using Related Data to Filter Objects
Modifying Related Data
Review and Resources

Using EF Core in Your Applications    30m 52s
Introduction and Overview
EF Core on the Desktop or Device
The Desktop Application: Windows Presentation Foundation (WPF)
Creating the WPF Application
Walking Through the WPF Data Access
EF Core in ASP.NET Core MVC
Adding Related Data into the MVC App
Coding the MVC App’s Relationships
Review and Resources