Loading...

Follow Christian Nagel C# on Feedspot

Continue with Google
Continue with Facebook
or

Valid

After some first experiments using the EF Core provider with Azure Cosmos DB, with the second article on EF Core with Azure Cosmos DB has a focus on associations. With relational databases, EF Core can be used to define relations between different tables in an OO-model. Using a NoSQL database like Azure Cosmos DB, there are different needs. With NoSQL, relations defined in the OO model should often result in hierarchical information stored within one entity. This article describes mapping for such scenarios with EF Core.

Azure Cosmos DB is a NoSQL database from Microsoft. It is globally distributed and offers multiple models. You can store data with key/values pairs, records with multiple columns (table storage), documents, and data linked within graphs. If you need massive amounts of data, reads, and writes with fast responses and high throughput, Azure Cosmos DB gives you great options. EF Core can be used with the documents version to store data. Here, JSON is used storing documents, and the content of the documents can be queried.

Mapping to Azure Cosmos DB with EF Core

In the previous article about using EF Core with Azure Cosmos DB, I’ve demonstrated first steps including using shadow state with EF Core and Cosmos DB.

Defining Relations

The sample application defines Book, Chapter, and Author types. The Book type defines the LeadAuthor property of type Author. This is a one-to-one relation. The property named Chapters is of type IEnumerable to define a one-to-many relation between Book and Chapter.

public class Book
{
  public Book(string title, string publisher)
    : this(title, publisher, Author.Empty)
  { }

  public Book(string title, string publisher, Author leadAuthor, params Chapter[] chapters)
  {
    BookId = Guid.NewGuid();
    Title = title;
    Publisher = publisher;
    LeadAuthor = leadAuthor;
    _chapters.AddRange(chapters);
  }

  public Guid BookId { get; set; }
  public string Title { get; set; }
  public string? Publisher { get; set; }

  private List<Chapter> _chapters = new List<Chapter>();
  public IEnumerable<Chapter> Chapters => _chapters:

  public Author LeadAuthor { get; set; }
}
public class Chapter
{
  public Chapter(int number, string title, int pages) =>
    (Number, Title, Pages) = (number, title, pages);

  public Guid ChapterId { get; set; } = Guid.NewGuid();
  public int Number { get; set; }
  public string Title { get; set; }
  public int Pages { get; set; }
}
public class Author
{
  public Author(string firstName, string lastName) =>
    (FirstName, LastName) = (firstName, lastName);

  public Guid AuthorId { get; set; } = Guid.NewGuid();
  public string FirstName { get; set; }
  public string LastName { get; set; }

  public override string ToString() => $"{FirstName} {LastName}";

  public static Author Empty => new Author(string.Empty, string.Empty);
}
Define Owned Entities

The relations are defined in the DbContext derived type BooksContext. In the OnModelCreating method, first the name of the EF Core container is defined. By default, the name of the container is the name of the context. Here, the container name is specified invoking the method HasDefaultContainerName. To define different entity types in different containers, the EntityTypeBuilder extension method ToContainer can be used.

With Azure Cosmos DB, container names should not be mapped to the types of the entities. You can store multiple entities of different types into a single container. With the first pricing models for Azure Cosmos DB, payment was by container. With a new variant for the pricing, you can use shared RUs for multiple containers of the same database – but this option needs to be configured on creation of the database.

The relation between Book and the Author types is defined with the OwnsOne method. With relational databases, defining this relation, the columns of the Author type are stored in the table of the Books table. With Cosmos DB, the content of the associated lead author is stored in the book entity. The Book type defines a association to a list of Chapter objects. This relation is mapped with the OwnsMany extension method to define an owned collection. This method is new since EF Core 2.2. With relational databases, owned collections are mapped to separate tables, such as normal one-to-many relations. With relational databases, using this extension method can still result in a different behavior to automatically load the relation on querying the owner type. With document-oriented databases such as Cosmos DB, the entity collection is stored within the owned entity.

public class BooksContext : DbContext
{
  public BooksContext(DbContextOptions<BooksContext> options)
    : base(options) { }

  public DbSet<Book>? Books { get; set; }

  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
    modelBuilder.HasDefaultContainerName("BooksContainer");
    modelBuilder.Entity<Book>().OwnsOne(b => b.LeadAuthor);
    modelBuilder.Entity<Book>().OwnsMany(b => b.Chapters);
  }
}

Besides using OwnsOne or OwnsMany with the owner entity, you can also define the Author and Chapter types to be owned, either by using the fluent model API Owned on the modelBuilder, or specify the Owned attribute on these types.

Adding Records

The sample application defines the BooksService class. Here, the database is created in the method CreateTheDatabaseAsync. The method WriteBooksAsync creates a new book with multiple chapters and a lead author. The code is not different when using a relational database:

public async Task CreateTheDatabaseAsync()
{
  var created = await _booksContext.Database.EnsureCreatedAsync();
  string message = created ? "created" : "already exists";
  Console.WriteLine($"database {message}");
}

public async Task WriteBooksAsync()
{
  var author = new Author("Christian", "Nagel");
  var c1 = new Chapter(1, ".NET Applications and Tools", 38);
  var c2 = new Chapter(2, "Core C#", 38);
  var c3 = new Chapter(3, "Objects and Types", 34);

  var book1 = new Book("Professional C# 7 and .NET Core 2.0", "Wrox Press", author, c1, c2, c3);
  _booksContext.Books?.Add(book1);
  int changed = await _booksContext.SaveChangesAsync();
  Console.WriteLine($"created {changed} record(s)");
}

Running the application to create the database and to write a book, using the Data Explorer in the Microsoft Azure Portal, the document can be retrieved:

{
"BookId": "bda886b2-76f7-4b4e-acbb-4a213067a0e9",
"Discriminator": "Book",
"Publisher": "Wrox Press",
"Title": "Professional C# 7 and .NET Core 2.0",
"id": "Book|bda886b2-76f7-4b4e-acbb-4a213067a0e9",
"Chapters": [
{
"BookId": "bda886b2-76f7-4b4e-acbb-4a213067a0e9",
"ChapterId": "3bebe9b4-55da-40ac-9953-d5dfaa02e441",
"Discriminator": "Chapter",
"Number": 1,
"Pages": 38,
"Title": ".NET Applications and Tools"
},
{
"BookId": "bda886b2-76f7-4b4e-acbb-4a213067a0e9",
"ChapterId": "e41104e0-a8cf-4680-8e09-88b5bb798920",
"Discriminator": "Chapter",
"Number": 2,
"Pages": 38,
"Title": "Core C#"
},
{
"BookId": "bda886b2-76f7-4b4e-acbb-4a213067a0e9",
"ChapterId": "48e4afcc-bc8a-4765-a995-a30384931954",
"Discriminator": "Chapter",
"Number": 3,
"Pages": 34,
"Title": "Objects and Types"
}
],
"LeadAuthor": {
"BookId": "bda886b2-76f7-4b4e-acbb-4a213067a0e9",
"AuthorId": "b59e4e0b-e257-4d98-8ca6-dd693e56c6b8",
"Discriminator": "Author",
"FirstName": "Christian",
"LastName": "Nagel"
},
"__partitionKey": "0",
"_rid": "6fk5AN7uXiwBAAAAAAAAAA==",
"_self": "dbs/6fk5AA==/colls/6fk5AN7uXiw=/docs/6fk5AN7uXiwBAAAAAAAAAA==/",
"_etag": "\"08005bb4-0000-0d00-0000-5cb3304b0000\"",
"_attachments": "attachments/",
"_ts": 1555247179
}

Query

A query to Cosmos DB can now done in the same way like with a relational database. With owned entities, and owned collections, results are retrieved:

public void ReadBooks()
{
  var books = _booksContext.Books.Where(b => b.Publisher == "Wrox Press");
  foreach (var book in books)
  {
    Console.WriteLine($"{book.Title} {book.Publisher} {book.BookId}");
    foreach (var chapter in book.Chapters)
    {
      Console.WriteLine($"chapter: {chapter.Title}");
    }
    Console.WriteLine($"author: {book.LeadAuthor}");
    Console.WriteLine();
  }
}
Summary

The same API used with Microsoft SQL Server – Entity Framework Core (EF Core) – can not only be used with relational databases, but also with NoSQL. Contrary to the older version Entity Framework, EF Core was designed not only for relational databases, but also for NoSQL. With .NET Core 3.0, a provider is planned for Azure Cosmos DB. Concepts such as owned entities and owned collections map nicely to NoSQL.

If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.

Interesting Links for this article:

First experiments using EF Core with Azure Cosmos DB

Mapping to Getter-only Properties with EF Core

More information on EF Core and writing data-driven applications is in my book Professional C# 7 and .NET Core 2.0, and in my Data Programming workshops.

Enjoy learning and programming!

Christian

  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

With C#, interfaces can be implemented implicitly or explicitly. With implicit interface implementations, the members of the interface are public in the class. With explicit implementations, in the class the interface members are not declared as public members and cannot be directly accessed using an instance of the class, but a cast to the interface allows accessing the members. Let’s go into the details.

Usually I’m writing about new or upcoming features. This time I’m writing about C# feature that is available since the first version of C#. The plan is to have this part of an ongoing series on some classic features. However, showing the classic features, I’m also using new C# syntax where it applies (like here with a sample using C# 8 switch expressions).

Implicit Interface Implementations

Interfaces are implemented implicit by declaring a public member in the class with the same signature of the method as defined in the interface and the same return type. This is how you normally implement interfaces.

public interface IFoo1
{
  void Foo();
}

public class FooImpl1 : IFoo1
{
  public void Foo() => 
    Console.WriteLine("ImplicitInterfaceImplementation.Foo");
}
Explicit Interface Implementation

Implementing interfaces explicitly, the interface is no longer declared public with the implementation, and the interface member is prefixed with the name of the interface:

public class FooImpl2 : IFoo1
{
  void IFoo.Foo() => Console.WriteLine("ExplicitInterfaceImplementation.Foo");
}

Using the implementation FooImpl2, the member of the interface cannot be used directly. A cast is needed to invoke the Foo method. Of course you can also use the is and as operators, or pass the instance to a method requiring an IFoo parameter:

static void Main()
{
  var f2 = new FooImpl2();
  // use a cast
  ((IFoo)f2).Foo();

  // use the is operator
  if (f2 is IFoo f)
  {
    f.Foo();
  }

  // the as operator
  (f2 as IFoo)?.Foo();

  // invoke a method with IFoo parameter
  DoIt(f2);
}

static void DoIt(IFoo foo)
{
  foo.Foo();
}

This is nice, but what is it good for?

Hiding Interface Implementations

One reason to use explicit interface implementations is to hide the members of the interface from a concrete class.

A concrete classic example is the class StringCollection implementing the interface IList. Both of these types are available before generics have been available. The IList interface defines a member with requiring an object parameter: int Add(object value); Of course, this is not the best option for the StringCollection. The StringCollection defines the method int Add(string value) which is preferred using strings. To still allow passing the StringCollection to methods requiring IList, some members of the interface IList are implemented explicitly.

Resolving Conflicts

Another reason is to resolve conflicts. Let’s get into the declaration of the IDataErrorInfo interface. This interface declares the Error property and an indexer:

public interface IDataErrorInfo
{
  string Error { get; }
  string this[string columnName] { get; }
}

The class MyCollection should implement this interface. However, the class already defines an indexer with a string parameter for another use case of the class – just not error handling. To fulfill the requirements of this interface, it can be implemented explicitly. Implementations making use of IDataErrorInfo (for example WPF), access the explicit implemented interface members:

public class MyCollection : IDataErrorInfo
{
  private Dictionary<string, string> _data = new Dictionary<string, string>();

  public string this[string key]
  {
    get => _data[key];
    set
    {
      if (_data.ContainsKey(key))
      {
        _data[key] = value;
      }
      else
      {
        _data.Add(key, value);
      }
    }
  }

  public int Data1 { get; set; }
  public int Data2 { get; set; }

  string? IDataErrorInfo.this[string columnName] =>
    columnName switch
    {
      nameof(Data1) => Data1 > 5 ? "error with Data1" : null,
      nameof(Data2) => Data2 > 3 ? "error with Data2" : null,
      _ => null
    };

  string IDataErrorInfo.Error => throw new NotImplementedException();
}

The implementation of the indexer for the interface IDataErrorInfo uses new C# 8 syntax – switch expression. In this scenario, the switch expression has a simpler and shorter implementation compared to the switch statement.

The same scenario applies having the same members defined with multiple interfaces, but the need to have different implementations. This can be resolved easily with explicit interface implementations.

Summary

With C# interfaces can be implemented implicit and explicit. Usually you’ll use implicit interface implementations, but there are good reasons when to use explicit implementations such as hiding interface members, but still having the contract implemented when it’s needed, and to resolve conflicts with different implementations needed for the same member.

If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.

More information on C# and .NET Core is in my book Professional C# 7 and .NET Core 2.0, and in my workshops.

Enjoy learning and programming!

Christian

  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

C# has different meanings for the using keyword. One is the using directive to import types from namespaces, and to create aliases to types. The second meaning is the using statement as a convenient syntax on using the IDisposable interface. With C# 6, also the using static directive was added to allow accessing static class members without the need to specify the type. C# 8 now adds another variant to the using keyword – one that is related with the using statement, the using declaration. I think I will replace most of my usages of the using statement to use the new using declaration instead. This article does not step into the using directive, but gives you information about the new C# 8 feature using declaration.

Disposing Resources

First, let’s start with the traditional using statement and the class AResource which implements the IDisposable interface:

public class AResource : IDisposable
{
    public void UseIt() => Console.WriteLine($"{nameof(UseIt)}");
    public void Dispose() => Console.WriteLine($"Dispose {nameof(AResource)}");
}

The using statement can be used to reference a variable or the result from a method, and at the end of the scope defined by the using statement, the Dispose method gets invoked:

private static void TraditionalUsingStatement()
{
    using (var r = new AResource())
    {
        r.UseIt();
    }  // r.Dipose is called
}

Behind the scenes, the compiler creates code using try/finally to make sure Disposeis also called when an exception is thrown:

private static void TraditionalUsingStatementExpanded()
{
    var r = new AResource();
    try
    {
        r.UseIt();
    }
    finally
    {
        r.Dispose();
    }
}

With the new C# 8 using declaration, the code with the using statement can be simplified. Curly brackets are no longer needed. At the end of the scope of the variable r (which is here the end of the method), the Dispose method is invoked. Here, the compiler also creates a *try/finally block to make sure Dispose is called if errors occur.

private static void NewWithUsingDeclaration()
{
    using var r = new AResource();
    r.UseIt();
}

That’s a small feature of C# 8, but we need to get a little bit more into details.

Disposing Multiple Resources

Using multiple resources, I’ve often seen code like this with multiple nested using statements:

private static void TraditionalMultipleUsingStatements()
{
    using (var r1 = new AResource())
    {
        using (var r2 = new AResource())
        {
            r1.UseIt();
            r2.UseIt();
        }
    }
}

Because the body of the outer using statement just consists of a single statement – the inner using statement, it is possible to simplify the code. This looks better than the previous one, and it stays better also if more than two resources need to be disposed:

private static void TraditionalMultipleUsingStatements2()
{
    using (var r1 = new AResource())
    using (var r2 = new AResource())
    {
        r1.UseIt();
        r2.UseIt();
    }
}

Next let’s do the same with the new using declaration. The following code is even shorter compared to the previous one – no matter how many resources you need to dispose:

private static void NewMultipleUsingDeclarations()
{
    using var r1 = new AResource();
    using var r2 = new AResource();
    r1.UseIt();
    r2.UseIt();
}
Using Scopes

What if a resource should be disposed before the method ends? You just need to add a separate scope using curly brackets. When the variable is out of scope, the resource is disposed:

private static void UsingDeclarationWithScope()
{
    {
        using var r1 = new AResource();
        r1.UseIt();
    }  // r1 is disposed here!
    Console.WriteLine("r1 is already disposed");
}
What can’t be done with the using declaration

Is there a reason to not use the using declaration, and keep the using statement?

In case you’ve a method returning a disposable, such as the method GetTheResource,

public static AResource GetTheResource() => new AResource();

and you don’t need a variable of this type, you just need to make sure the resource returned is disposed – with the using statement this code is possible:

private static void TraditionalResourceReturned()
{
    using (GetTheResource())
    {
        // do something here
    }  // resource is disposed here
}

If you try to do the same with the using declaration, you’ll get multiple compilation errors – all in the same code line:

private static void NewResourceReturned()
{
    using GetTheResource();
    // do something here
}  // resource is disposed here
  • CS1001: Identifier expected
  • CS1528: Expected ; or = (cannot specify constructor arguments in declaration)
  • CS1003: Syntax error, ‘[‘ expected
  • CS1003: Syntax error, ‘]’ expected

Probably a future version of the compiler results in a different compiler error.

The reason is that the using declaration requires a variable for the scope. In case you don’t need the variable afterwards, there’s an easy fix – just use _ for the variable name, and ignore it:

private static void NewResourceReturned()
{
    using var _ = GetTheResource();
    // do something here
}  // resource is disposed here
Summary

It’s just a small feature of C# 8, but it will change the code in many places. Currently I don’t see a reason to stay with the old using statement. I think I’ll switch to the new using declaration with all my code. The number of curly brackets are reduced, but it can still be seen easily where a resource is disposed. The number of code lines is reduced using the name using declaration.

If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.

Interesting Links for this article:

Complete code sample

Other C# 8 articles:

Async Streams with C# 8

C# 8 Proposal for Async Streams

Proposal: IAsyncEnumerable.WithCancellation Extension Method

C# 8: Indexes and Ranges

C# 8: Pattern matching extended

C# 8: No more NullReferenceExceptions – What about legacy code?

More information on C# and programming .NET Core applications is in my book Professional C# 7 and .NET Core 2.0, and in my workshops.

Enjoy learning and programming!

Christian

  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

.NET Core 3.0 doesn’t make it easier to choose the correct Web technology creating .NET applications. Some more options have been added to select from, e.g. ASP.NET Razor Components. Did you already know when the best options would be Razor Pages instead of MVC? Now there’s also the option gRPC. What is this good for?
In this article I try to explain the features of the different templates creating ASP.NET Core applications, and with which requirements you should select which option.

Using Visual Studio 2019 there’s a huge list to select from after selecting to create a new ASP.NET Core Web Application. All these options are available from the .NET Core CLI as well – although often named differently.

Let’s get into the different options to chose from.

Web

Using Visual Studio 2019, you can select Empty. The description says This template does not have any content in it. This is not really true. There’s not a lot content, but the Main method makes use of the new Host class for setup, and the Startup class is generated where you can define the services that should be injected, and define your middleware. Instead of empty, the dotnet CLI commands offer the option dotnet new web. I think this naming is a better fit contrary to the template in Visual Studio. The .NET Core 3.0 version includes the new endpoint routing.

In case you just need to dynamically generate HTML code and don’t have the need to create HTML code with Razor HTML helpers and tag helpers, this can be the best option to start with. If your service just needs to offer SignalR services, this project type can be used to start with.

Features:

  • Host for configuration, logging
  • Startup to configure DI and Middleware
  • No other library configured than the framework netcoreapp3.0 and the SDK Microsoft.NET.Sdk.Web

Use when:

  • Creating a SignalR Service when you don’t need REST APIs or Razor pages/views in addition to the SignalR service
  • Dynamically create and return Web pages without using Razor syntax and views
  • You need a Web project with simple server-side infrastructure
Worker

This feature is new with ASP.NET Core 3.0. This project type can be used if you need background processing. The generated code includes a worker with a while loop that is repeated as long as the cancellation token is not signaled. The worker derives from the base class BackgroundService. BackgroundService implements the interface IHostedService with methods for starting and stopping. The worker is defined as a hosted service in the Main method with the startup configuration.

Features:

  • Host for configuration, logging
  • Background service
  • The library Microsoft.Extensions.Hosting is ued in addition to the framework netcoreapp3.0

Use when

  • You need to do some continuous or repeating background processing

Alternatives:

  • You should consider using Azure Functions when hosting with Microsoft Azure. Azure Functions offer different triggers when the function should be started – e.g. a timer-based trigger.
gRPC

If you need fast and efficient binary communication between different systems using an RPC-based protocol, this project type can be used. No, this is not using .NET Remoting. Communication is based on the GRPC protocol made by Google. This protocol is based on HTTP/2 – thus you need servers supporting HTTP/2. Google’s Protocol Buffers are used to define the binary communication between the parties. To create C# code from a protocol definition with protobuf, tools from the tool package *Grpc.Tools are used.

Features:

  • Host for configuration, logging
  • Startup with DI container configuration and middleware
  • GRPC Protocol with Protobuf for the message format
  • Client application using the generated files from the Protobuf definition
  • The packages Grpc.Core, Grpc.Tools, and Google.Protobuf are referenced
  • Based on HTTP/2

Use when:

  • For fast communication
  • Communication between Microservices when REST is not required
Web API

The Web API project (dotnet new webapi) offers REST services with ASP.NET Core. Controllers are used with attribute-based routing to react to HTTP GET, POST, PUT, and DELETE requests. You can add OpenAPI (Swagger) support to get documentation and test pages. By default, JSON data is returned – but you can configure services and middleware to return XML, MessagePack, or Protobuf. You can also create a library to put the functionality with the controllers in the library, and reference the library from the host application.

Features:

  • Host for configuration, logging
  • Startup for dependency injection and middleware
  • Controllers to offer REST services
  • Configure services and middleware for different protocols

Use when:

  • Use for communication via REST
  • Create REST Services
  • Create Microservices
Razor Pages (Web App)

Let’s switch to user interfaces. With .NET Core 2.0, Razor Pages have seen the light (dotnet new webapp). Compared to using the bigger older brother ASP.NET Core MVC, Razor Pages are easier to start with. HTML code and C# code can be mixed – all within a .cshtml file. However, you can also separate C# from the HTML code using code-behind. This is similar to how this is done with WPF or Windows Forms. The big functionality in your Web pages shouldn’t be in the Razor pages anyway – no matter if you’re using code-behind or not. The functionality should be implemented in service classes – no matter if you implement the Web application with Razor Pages or with MVC. Razor Pages allow injection of services similar to inject services in views or controllers.

Razor Pages are based on the same foundations as ASP.NET Core MVC, and it’s easy to mix Razor Pages, MFC, and Web API in the same project.

Features:

  • Host for configuration, logging
  • Startup for dependency injection and middleware
  • Static files in wwwroot
  • Create services to be injected with Razor pages
  • Mixing HTML code and C# code or use code-behind
  • Injection of services into Razor pages, services, and middleware
  • Tag helpers, HTML helpers
  • Using Razor Pages, you can also create user interfaces into libraries
  • Write HTML and JavaScript for client-side functionality

Use when:

  • Web sites, returning HTML code and more

Alternatives

  • Consider to use MVC with ASP.NET Core Web API if the C# code in the pages becomes too complex. Instead, you might also move more functionality into services.
ASP.NET Core MVC

This is the big brother of Razor Pages – ASP.NET Core using the Model-View-Controller (MVC) pattern. This is the more complex alternative to Razor Pages. The project structure mandates separation of functionality into models, views, and controllers. Views are crated using Razor syntax.

Features:

  • Host for configuration, logging
  • Startup for dependency injection and middleware
  • Static files in wwwroot
  • Injection of services with controllers, views, services, and middleware
  • Razor syntax in the views
  • Tag helpers, HTML helpers
  • View components
  • Write HTML and JavaScript for client-side functionality

Use when:

  • Web sites, returning HTML code and more

Alternatives

  • Consider to use MVC with ASP.NET Core Web API if the C# code in the pages becomes too complex. Instead, you might also move more functionality into services.
Razor Components

Razor Components is a new technology available with ASP.NET Core 3. From a syntax viewpoint, it adopts the syntax of Razor Pages. However, because Razor Components are very different, you also have a new file extension: .razor. Razor Components are the first technology coming out of the Blazor project. Blazor is discussed next. Be aware that there’s a big difference between Razor Components and Blazor. With Blazor, C# code runs on the client. Using Razor Components you can create event handlers for user interface elements, but this code runs on the server.

Programmatically, Razor Components are nice to work with as you can use components with HTML-like syntax, and create event handler to user interface elements with C# code. All this C# code runs on the server. Communication with the client is done using SignalR. SignalR makes use of WebSockets. Be aware that a connection is opened from every client to the server. Razor Components need a good network, and more resources on the server as connections are kept open for every connected client.

Features:

  • Host for configuration, logging
  • Startup for dependency injection and middleware
  • Static files in wwwroot
  • Razor components with data binding event handlers activated from client-side JavaScript (that you don’t need to write), and invoked on the server
  • Injection of services with Razor components, controllers, services, and middleware
  • Razor syntax
  • Tag helpers, HTML helpers
  • Write C# code for client-side functionality (but it runs on the server)

Use when:

  • Web sites with C# code written for
  • Web sites, returning HTML code and more

Be aware:

  • that SignalR us used behind the scenes.
  • Every client has a open connection to the server.
  • More resources needed on the server.

Ideas:

  • If you pay attention on how you implement the server side functionality, there can be an easy switch from Razor Components to Blazor
Blazor

Blazor is not yet released, it’s still in early stages. Blazor is based on the WebAssembly technology – a standard that runs in all modern browsers (all actual browsers with the exception of Internet Explorer). WebAssembly allows to run binary code. With Blazor, the Runtime is done using WASM (currently the Mono Runtime), C# code is compiled to IL code and sent within DLLs to the client. An interpreter of the Mono Runtime (JIT and/or AOT compilers are coming) run the IL code on the client.

Blazor code runs in the sandbox of the browser – so you are not allowed to do everything with the C# code you can do on the server in Blazor. An application can be designed that way to have an easy switch between Razor Components and Blazor, you need to pay attention with the application architecture. For example, using Razor Components you can access the SQL Server database using EF Core from services that are directly injected in Razor Components. Probably some time in the future we also get EF Core for Blazor – accessing IndexedDB, but it will not be possible to access SQL Server from within the browser. Instead, you need to inject the HttpClient class (which uses HttpWebRequest of the browser with Blazor), and call a Web API on the server where EF Core is used. Paying attention to these differences, it should not be too hard to switch between Razor Components and Blazor some time in the future.

Features:

  • Different project types for either just a Blazor front-end, or Blazor with ASP.NET Core in the backend
  • Dependency injection and startup code for the client that doesn’t look that different as when used on the server with ASP.NET Core
  • Syntax of Razor Components with Blazor
  • Host for configuration, logging
  • Static files in wwwroot
  • Writing C# code that runs in all modern browsers
  • Component-based architecture
  • Easy switch from Razor Components
  • Write C# code for client-side functionality, and it runs on the client

Use when:

  • You prefer C# code over JavaScript
  • Do not need to support Internet Explorer
  • You’re ok using a pre-released technology

Be aware:

  • It’s not yet released
  • WebAssembly itself is in its early stages (threading, can’t access DOM elements directly, JavaScript interop is needed)
Summary

ASP.NET Core gives you many different options. Creating background functionality running on the server, you can use the Worker template. Offering services that can be invoked across the network, you can use the Web API (webapi), and GRPC (grpc) for fast binary RPC-based communication. Creating user interfaces for the client, you can use Razor Pages (webapp) or ASP.NET Core Web App (Model-View-Controller) (mvc) depending on the application structure you prefer. A different technology but with similar syntax is given with Razor Components (razorcomponents) where SignalR is used behind the scenes to invoke C# created code on the server. Still in preview and not going to be released with .NET Core 3.0 is Blazor – a technology based on WebAssembly. Just because it’s programming model is similar to Razor Components, I’ve added it to this list. Paying attention to the application architecture, there could be an easy switch between Razor Components and Blazor.

If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.

Interesting Links for this article:

Source Code created from the templates – see the ASPNETCore/Compare folder

Host with .NET Core 3

ASP.NET Core Identity Pages with ASP.NET Core 2.1

Open APIs

Swagger

GRPC

C# Source Code for GRPC

Source Code Hosting with .NET Core 3

Can I Use – WebAssembly

More information on ASP.NET Core and writing Web applications applications is in my book Professional C# 7 and .NET Core 2.0, and in my workshops.

Enjoy learning and programming!

Christian

  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

ASP.NET Core included the WebHost class that was used in the Main method to startup everything up – including the dependency injection container. With Non-ASP.NET Core applications I used the same DI container (Microsoft.Extensions.DependencyInjection), but I had to create the ServiceCollection on my own. This changes with .NET Core 3.0 and the new Host class that is independent of Web applications.
It’s clear how the Host class is used from ASP.NET Core Web applications. I was wondering how to take advantage of this class from console, UWP, WPF, and Xamarin applications. With these application types, I’ve been using the ServiceCollectionclass directly to register my services. Now I can take advantage of the Host class. In this article I’m changing a previous sample from Dependency Injection with .NET Core to use the new Host class from the namespace Microsoft.Extensions.Hosting. You should read the older article first if you don’t know the DI container from Microsoft.Extensions.DependencyInjection.

Host in ASP.NET Core Web Applications

Creating an ASP.NET Core 3.0 application, the template-generated code invokes the static method CreateDefaultBuilder and the extension method ConfigureWebHostDefaults where the Startup class is defined to be used for the startup. In the Startup class the services are configured in the DI container. The code is very similar to older versions of ASP.NET Core – just the Host class is used instead of the older WebHost.

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
Sample Application

The sample application defines the interface contract IGreetingService, an implementation GreetingService, and the class HelloController where the IGreetingService is injected to. This is the same structure as used with the sample from the previous referenced article.

public interface IGreetingService
{
    string Greeting(string name);
}
public class GreetingService : IGreetingService
{
    public string Greeting(string name) => $"Hello, {name}";
}
public class HelloController
{
    private readonly IGreetingService _greetingService;
    public HelloController(IGreetingService greetingService) => 
        _greetingService = greetingService;

    public string Action(string name) =>
        _greetingService.Greeting(name);
}
Using the Host Class

Next, let’s get into the changes of the previous application architecture. Instead of creating a method where a new object of the ServiceCollection is instantiated (the DI container), let’s use the new Host class. This class is defined in the NuGet package Microsoft.Extensions.Hosting with a namespace of the same name. The static method CreateDefaultBuilder returns a builder object implementing the interface IHostBuilder. Now, extension methods such as ConfigureServices can be used. ConfigureServices defines a delegate parameter Action, thus a IServiceCollection is received with the parameter where services can be configured with the DI container. The Build method initializes the host and returns the disposable IHost interface. Behind the scenes, the Build method invokes the method BuildServiceProvider with the DI container. The container can be accessed with the Services property of the host. The IServiceProvider interface is received with the method UsingAContainer. In the method implementation, the HelloController is retrieved via the container. The container injects the required IGreetingService in the constructor of the HelloController. This functionality is the same as it was with the older implementation.

The sample code uses the C# 8 syntax for the using declaration. With the using declaration, the variable referenced by it is disposed at the end of the scope. Contrary to the using statement, it’s not necessary to write curly brackets to define the scope.

public class Program
{
    public static void Main()
    {
        using IHost host = Host.CreateDefaultBuilder()
            .ConfigureServices(ConfigureServices)
            .Build();

        UsingAContainer(host.Services);
    }

    private static void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IGreetingService, GreetingService>();
        services.AddTransient<HelloController>();
    }

    private static void UsingAContainer(IServiceProvider container)
    {
        var controller = container.GetService<HelloController>();
        string greeting = controller.Action("Katharina");
        Console.WriteLine(greeting);
    }
}
Extending the Use of the Host Class

The Host class also allows to define logging and configuration requirements. You can define the configuration for the application using ConfigureAppConfiguration, and define logging providers and filters with the extension method ConfigureLogging. Instead of just using the IHost object returned from the Build method, now the RunConsoleAsync method is used. This method builds and starts the host, and waits for a CTRL+C or SIGTERM to shutdown. The RunConsoleAsync method returns a Task, thus this method can be awaited.

public static async Task Main(string[] args)
{
    await Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(config =>
            config.SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: true)
                .AddEnvironmentVariables()
                .AddCommandLine(args))
        .ConfigureLogging(logging =>
        {
            logging.AddConsole().AddFilter(level => level >= LogLevel.Error);
        })
        .ConfigureServices(services =>
        {
            services.AddHostedService<GreetingHost>();
            services.AddTransient<IGreetingService, GreetingService>();
            services.AddTransient<HelloController>();
        }).RunConsoleAsync();
}

Using RunConsoleAsync needs a hosted service implementation – a class that implements the interface IHostedService. This interface defines the methods StartAsync and StopAsync that are invoked on starting and on ending the host. With the sample code, the HelloController is injected in the constructor and this object is used within the implementation of the StartAsync method. Because the application should not continue after writing of the greeting message, the interface IHostingApplicationLifetime is injected with the GreetingHost to send a StopApplication.

public class GreetingHost : IHostedService
{
    private readonly HelloController _controller;
    private readonly IHostApplicationLifetime _lifetime;
    public GreetingHost(HelloController controller, IHostApplicationLifetime lifetime) =>
        (_controller, _lifetime) = (controller, lifetime);

    public Task StartAsync(CancellationToken cancellationToken)
    {
        string greeting = _controller.Action("Matthias");
        Console.WriteLine(greeting);
        _lifetime.StopApplication();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("closing...");
        return Task.CompletedTask;
    }
}
Summary

Instead of the WebHost class that was in use with ASP.NET Core Web applications before .NET Core 3.0, now the Host class is available. With older versions of .NET Core I already used .NET Core features for configuration, logging, and dependency injection not only with my ASP.NET Core applications, but also with WPF, UWP, and Xamarin. Now I can also use the Host class to make this configuration for different application types. This can be as simple as just using it as a wrapper for the DI container Microsoft.Extensions.DependencyInjection, but also more advanced features e.g. to control the lifetime can be used.

If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.

Interesting Links for this article:

Complete code sample

Dependency Injection with .NET Core

.NET Core Dependency Injection with Options

.NET Core Dependency Injection with Configuration

Disposing Injected Services

HttpClientFactory with .NET Core 2.1

Configuration with .NET Core

Writing ILogger Diagnostics to a File

More information on EF Core and writing data-driven applications is in my book Professional C# 7 and .NET Core 2.0, and in my workshops.

Enjoy learning and programming!

Christian

  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 
Christian Nagel C# by Christian Nagel - 4M ago

One of the many great features of C# 8 is async streams. Before C# 8, you could use the await keyword only to get a single result – when the asynchronous method returns the result. This changes with C# 8. Using await it’s now possible to get a stream of results. This was made possible by defining asynchronous iterator interfaces, and updates to the foreach loop and the yield statement. This article gives you more information on this.

Sample application

With the sample application a device is simulated that returns two random values after a random time. The data returned from the device is implemented in the class SensorData. This is a simple type with two read-only properties:

public struct SensorData
{
    public SensorData(int value1, int value2) => (Value1, Value2) = (value1, value2);

    public int Value1 { get; }
    public int Value2 { get; }
}
Using yield to implement IAsyncEnumerable

The ADevice class implements the interface IAsyncEnumerable using the yield statement. yield was changed to not only implement synchronous iterators with the IEnumerable and IEnumerator interfaces, but also the IAsyncEnumerable and IAsyncEnumerator interfaces. In the method GetSensorData1, the yield statement is used to return sensor data with random values after a random time in an endless loop:

public class ADevice
{
    public async IAsyncEnumerable<SensorData> GetSensorData1()
    {
        var r = new Random();
        while (true)
        {
            await Task.Delay(r.Next(300));
            yield return new SensorData(r.Next(100), r.Next(100));
        }
    }
}
Async Enumerator Interfaces

For async streams, asynchronous versions of the enumerator interfaces have been created. The interfaces IEnumerable and IEnumerator need an asynchronous counterpart. The interface IAsyncEnumerable defines the method GetAsyncEnumerator which returns an IAsyncEnumerator. This is similar to the implementation of the IEnumerable interface. Because of the asynchronous nature of the interface, the GetAsyncEnumerator method defines an optional parameter of the CancellationToken type to allow for early cancellation.

public interface IAsyncEnumerable<out T>
{
    IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken));
}

The C# 8 proposal for async streams on GitHub mentions to define IAsyncEnumerable to be cancellation agnostic. This changed. The implementation in System.Runtime, version 4.2.1.0, the method GetAsyncEnumerator accepts an optional CancellationToken.

The interface IAsyncEnumerator defines the Current property and the MoveNextAsync method. There’s a small difference to the IEnumerator interface. This interface also defines the Reset method. The Reset method has its history with COM interoperability.

public interface IAsyncEnumerator<out T> : IAsyncDisposable
{
    T Current
    {
        get;
    }

    ValueTask<bool> MoveNextAsync();
}

Alternative interface definitions such as a MoveNextAsync method returning the value instead of the Current property was considered. However, this would be harder to use, and can’t be covariant.

An asynchronous version of the IDisposable interface is needed as well. IAsyncEnumerator derives from the interface IAsyncDisposable which allows for async disposal of resources with the DisposeAsync method:

public interface IAsyncDisposable
{
    ValueTask DisposeAsync();
}

It was considered to not derive IAsyncEnumerator from IAsyncDisposable. However, this design would complicate other parts, e.g. with pattern-based helpers that need to deal with different scenarios if

ValueTask instead of Task

The interfaces IAsyncDisposable and IAsyncEnumerator return ValueTask with the methods MoveNextAsync and DisposeAsync. C# 7 was changed to allow awaits not only on the Task type, but instead with any type implementing the GetAwaiter method. ValueTask is one of the types that can be used here. ValueTask is implemented as a value type instead of a reference type with the Task. With this, ValueTask doesn’t have the overhead of an object in the managed heap. This can be extremly useful iterating through a list where not every iteration really requires an asynchronous operation.

Using foreach

Next, let’s iterate the asynchronous stream. The foreach statement has been extended with asynchronous functionality – making use of the asynchronous interfaces when the await keyword is used. With await foreach, one item is retrieved after the other – without blocking the calling thread.

private static async Task Demo1Async()
{
    var aDevice = new ADevice();

    await foreach (var x in aDevice.GetSensorData1())
    {
        Console.WriteLine($"{x.Value1} {x.Value2}");
    }
}

Behind the scenes, the compiler translates the async foreach statement to a While loop, invocation of the MoveNextAsync method, and accessing the Current property:

private static async Task Demo2Async()
{
    var aDevice = new ADevice();

    IAsyncEnumerable<SensorData> en = aDevice.GetSensorData1();
    IAsyncEnumerator<SensorData> enumerator = en.GetAsyncEnumerator();
    while (await enumerator.MoveNextAsync())
    {
        var sensorData = enumerator.Current;
        Console.WriteLine($"{sensorData.Value1} {sensorData.Value2}");
    }
    await enumerator.DisposeAsync();
}
Cancellation

Creating a custom implementation of the IAsyncEnumerator interface, it would be possible to directly access the CancellationToken defined with the GetAsyncEnumerator method. This is not (yet?) possible when using yield return to create the implementation. However, you can define a parameter of type CancellationToken, register with this token, and get out (throw the OperationCanceledException) when the operation should be canceled:

public async IAsyncEnumerable GetSensorData2(CancellationToken cancellationToken = default)
{
    bool cancel = false;
    using var registration = cancellationToken.Register(() => cancel = true);
    var r = new Random();
    while (!cancel)
    {
        await Task.Delay(r.Next(500));
        yield return new SensorData(r.Next(100), r.Next(100));
    }
    Console.WriteLine("cancel requested");
    throw new OperationCanceledException(cancellationToken);
}
´´´

Invoking the method `GetSensorData2`, the `CancellationToken` can be passed. The following sample code sends a cancellation after 5 seconds:

```csharp
private static async Task Demo3Async()
{
    try
    {
        var cts = new CancellationTokenSource();
        cts.CancelAfter(5000);
        var aDevice = new ADevice();

        await foreach (var x in aDevice.GetSensorData2(cts.Token))
        {
            Console.WriteLine($"{x.Value1} {x.Value2}");
        }
    }
    catch (OperationCanceledException ex)
    {
        Console.WriteLine(ex.Message);
    }
}

Using implementations of IAsyncEnumerable which make use of optional the passed CancellationToken, the extension method WithCancellation can be used to pass this token. Similarly, the extension method ConfigureAwait can be used if async streams should not continue on the captured context, if a different thread might be used with the continuation.

Comparing to IObservable

Since .NET Framework 4.0, .NET included the IObserver and IObservable interfaces. Reactive Extensions makes use of these interfaces. How does this compare to the new interfaces defined for async streams?
With the IObservable interface, the Subscribe method can be used to assign a subscriber and receive events. This explains the major difference between this model and the new async streams. Observables uses a push based model, the sender is in control. The subscriber receives events when new items are available. With async streams, a pull based model is used. The caller is in control when doing the next invocation of the GetNextAsync method, and waits here to receive the result. Because of the async implementation, the caller continues only when the result is received, but the calling thread is not blocked and can continue other work.

Summary

async streams fits well to the async programming model of C# available since C# 5. Instead of receiving just one result after the asynchronous operation is completed, a stream of results is returned – and you can use the well known C# statements foreach, and yield return together with the async and await keywords. The synchronous interfaces for enumerations have corresponding asynchronous interfaces that are implemented using yield, and used with async foreach.

If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.

Interesting Links related with this article:

Complete code samples

C# 8 Proposal for Async Streams

Proposal: IAsyncEnumerable.WithCancellation Extension Method

C# 8: Indexes and Ranges

C# 8: Pattern matching extended

C# 8: No more NullReferenceExceptions – What about legacy code?

More information on C# is in my book Professional C# 7 and .NET Core 2.0, and in my workshops.

Enjoy learning and programming!

Christian

  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

I had some great days at BASTA! Spring in Frankfurt – with three presentations. Thank you for joining! My presentations and source code are available for download!

The topics I talked about:

  • C# – What’s next?
  • Reference semantics with C# and .NET Core
  • Adaptive cards – user interfaces with JSON

C# – What’s next

Since C# 7.0 we received several point releases with small but nice features with C# 7.1, C# 7.2, and C# 7.3. After covering new features of the point releases, the big focus in this presentation was C# 8.0 with async streams, indexes and ranges, patterns extended and the nullable reference types.

C# What’s next on SlideShare

Also read my blog article on new C# 8 features:

Reference Semantics with C# and .NET Core

Performance is an important aspect of .NET Core. New language features of C# 7.x allow returning value types by reference, having local references, defining structs that can only be stored on the stack, and more – all without creating unsafe code. In this session I’ve explained the new language features, and how they led to improvements in .NET libraries and frameworks.

Reference Semantics on Slideshare

See also my blog article on array pools:

Adaptive Cards – User Interfaces with JSON

My third presentation at BAST! was about adaptive cards. With the XAML-based applications I’m creating, I try to reuse as much code as possible. Services and view-models are put in a .NET Standard library, and thus the same libraries can be reused across different technologies. Using adaptive cards it’s possible to reuse user interface elements. Not the complete user interface, but cards. Many applications make use of cards in some form. With adaptive cards it’s possible to create cards in the JSON format and reuse these cards on different platforms with renderers for every platform. See Adaptive Cards fir samples, the card schema, a designer, and documentation, and renderers available for different platform. The source code for adaptive cards and renderers is available on GitHub – AdaptiveCards.

Adaptive Cards on SlideShare

The source code for all the samples is available in my BASTA! Frankfurt repository on GitHub!

Read my book Professional C# 7 and . NET Core 2.0 on features of C# 7.

Probably you’ve also interest attending one of my .NET Core / ASP.NET Core / UWP / WPF / Azure / Xamarin workshops. For a company-based workshop, content can be completely adapted to your needs.

Enjoy learning and programming!
Christian

The next conference I’m talking at is the TechConference in Vienna:

  • Making Desktop Apps modern – WPF and UWP
  • ASP.NET Core 3.0 – what’s new?
  • Docker for Developers
  • From Development to Deployment: Azure DevOps
  • Click the button – Azure IoT
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 
Christian Nagel C# by Christian Nagel - 6M ago

Using EF Core, references can be eager loaded, explicitly loaded, and lazy loaded. With eager loading you load references by specifying what references should be included when defining the query. Specifying the query, you use the Include method to define what references should be included. This is best when knowing in advance the needed references. With explicit loading you explicitly invoke the Load method when references to single items or collections should be loaded. With lazy loading, you do not need to explicitly invoke the Load method. Instead, just accessing the property dynamically invokes a query to the database to retrieve the data for the needed references.

With EF Core, lazy loading is available since version 2.1. This article gives information on lazy loading which is very different to lazy loading with Entity Framework 6.

Overview

I usually prefer eager loading or explicit loading to lazy loading. With lazy loading, reading the code you can easily miss where queries to the database are done. More queries than needed could be done to retrieve data from the database. Using eager loading you can reduce the number of queries, and access relations with a single SQL query. Using explicit loading, usually the same number of queries like with lazy loading are done – it’s just shown explicitly where the database access is used.

Using lazy loading, every time a property is accessed and the data is not yet retrieved, a query to the database is done.

Because of the disadvantages of lazy loading, comparing the implementations of lazy loading between Entity Framework and EF Core, it’s now implemented in a different way. You need to explicitly turn it on.

If the issues don’t apply to your scenario, go ahead and use lazy loading. There’s just a little more work needed defining the model types, and doing some configuration.

Preparations

To use lazy loading, an additional package needs to be added. Lazy loading is not available if you just use the package Microsoft.EntityFrameworkCore. For using lazy loading, the package Microsoft.EntityFrameworkCore.Proxies needs to be added to the project references. As mentioned previously, because of the lazy loading disadvantages, it’s not included by default with your EF Core projects.

Checking the dependencies, Microsoft.EntityFrameworkCore.Proxies is dependent on the package Castle.Core. Castle.Core is part of the Castle Project. The Castle Project consists of several interesting projects. One of these is DynamicProxy. EF Core makes use of this package for dynamic-loading proxies.

With the sample code I’m using Visual Studio 2019 and C# 8. In case you don’t have this versions yet, you can change the code easily to use C# 7 – just remove some features on nullable reference types.

Configure Proxy

Proxies are used to make lazy loading possible. After adding the reference to the NuGet package, proxies can be configured using the method UseLazyLoadingProxies. This is an extension method to extend the DbContextOptionsBuilder. This method turns on proxy creation and uses proxy services implemented in the referenced NuGet package.

With the sample code, the lazy loading proxies are configured using the DI container. In case you are not using the DI Container with your EF Core application, you can use the method UseLazyLoadingProxies in the OnConfiguring method of the EF Core context.

Models and Context

The sample application defines the model classes Book, Chapter, and User.

The Book class contains a list of chapters with a one-to-many relation. The Book type also references multiple User types with different roles. A user can be the author, the reviewer, or the project editor. To make the class ready for lazy loading, the relations need to be specified with the virtual modifier. Behind the scenes, the created proxy class derives from the Book class and overrides these properties. The proxy then loads the data needed on first access of the property.

With the EF Core context class BooksContext, the fluent API is used to specify the relations. The book has a list of chapters, and a chapter belongs to one book – this is specified with HasMany and WithOne. One user is associated with multiple books with the relations WrittenBooks, ReviewedBooks, and EditedBooks.

The sample code uses the fluent API to specify the relation. Relations can also be specified using annotations. The book Professional C# 7 and .NET Core 2.0 covers all variants.

Lazy Loading

To access books, LINQ queries can be done like the one shown passing a where clause. After iterating the books, the references to chapters, authors, reviewers, and editors are done just by accessing the properties of the Book type:

Accessing the books, from the LINQ statement a SQL query is generated to access different columns from the Books table:

SELECT [b].[BookId], [b].[AuthorId], [b].[EditorId], [b].[Publisher], [b].[ReviewerId], [b].[Title]
      FROM [Books] AS [b]
      WHERE [b].[Publisher] LIKE N'Wrox' + N'%' AND (LEFT([b].[Publisher], LEN(N'Wrox')) = N'Wrox')

With the first query, other tables than the Books table are not accessed. However, accessing the Chapters property, this SQL query is done:

SELECT [e].[ChapterId], [e].[BookId], [e].[Number], [e].[Title]
      FROM [Chapters] AS [e]
      WHERE [e].[BookId] = @__get_Item_0

Later on in the code, accessing the Author, Reviewer, and Editor relations, more queries are done.

SELECT [e].[UserId], [e].[Name]
      FROM [Users] AS [e]
      WHERE [e].[UserId] = @__get_Item_0

When the data was not loaded previously, every time a property is accessed that maps to a related table, another query to the database is done. Behind the scenes, the query doesn’t return the defined Book types, but instead the class Castle.Proxies.BookProxy is returned. This class derives from the base class Book and overrides virtual properties.

Explicit Loading

With lazy loading, just properties need to be accessed from the C# code to get the data from the database as needed. This is easy to do, but you might miss better performance by reducing the number of queries. Using explicit loading you do have the same number of queries, it’s just easier to detect from the source code. Using the Collection method from the EntityEntry type, 1:n relations can be retrieved from the program invoking the Load method. Here, the same SQL statement is generated accessing the book chapters as with lazy loading. Accessing a 1:1 relation, the Reference method is used – again with the Load method.

You can also use the IsLoaded property to see if the related data is already loaded. The implementation of the Load method itself checks if the related data is already loaded to not query the database another time if the data is already in memory.

With explicit loading the source code gets more complex when accessing the objects from the EF Core database context. Related data needs to be explicit loaded using the Load method from the CollectionEntry or the ReferenceEntry returned from the Collection and Reference methods. The advantage using explicit loading is that you see it from the C# source code that additional SQL queries are done. Also, the model type doesn’t need special treatment. Here, virtual properties are no longer needed.

Eager Loading

In case you already know in advance the needed loaded relations, eager loading can be used. This should be the preferred way to get the data from the database. You can get deep relations with just one query. Defining the LINQ query, you now add calls to the Include method and specify the relations that should be included. The Include method is an extension to the IQueryable type defined in the Microsoft.EntityFrameworkCorenamespace.

In case you have deeper relations, and need to access relation by relation, e.g. by accessing another relation from the Chapter type, you can use the ThenInclude method.

The SQL statement now becomes more complex. Not just the Books table is queried, but with my current SQL Server provider two SELECT statements are done accessing the Books, Chapters, and Users table using LEFT JOIN and INNER JOIN. Now just one time information from the database is retrieved instead when accessing every single book:

 SELECT [b].[BookId], [b].[AuthorId], [b].[EditorId], [b].[Publisher], [b].[ReviewerId], [b].[Title], [b.Editor].[UserId], [b.Editor].[Name], [b.Reviewer].[UserId], [b.Reviewer].[Name], [b.Author].[UserId], [b.Author].[Name]
      FROM [Books] AS [b]
      LEFT JOIN [Users] AS [b.Editor] ON [b].[EditorId] = [b.Editor].[UserId]
      LEFT JOIN [Users] AS [b.Reviewer] ON [b].[ReviewerId] = [b.Reviewer].[UserId]
      LEFT JOIN [Users] AS [b.Author] ON [b].[AuthorId] = [b.Author].[UserId]
      WHERE [b].[Publisher] LIKE N'Wrox' + N'%' AND (LEFT([b].[Publisher], LEN(N'Wrox')) = N'Wrox')
      ORDER BY [b].[BookId]
SELECT [b.Chapters].[ChapterId], [b.Chapters].[BookId], [b.Chapters].[Number], [b.Chapters].[Title]
      FROM [Chapters] AS [b.Chapters]
      INNER JOIN (
          SELECT DISTINCT [b0].[BookId]
          FROM [Books] AS [b0]
          LEFT JOIN [Users] AS [b.Editor0] ON [b0].[EditorId] = [b.Editor0].[UserId]
          LEFT JOIN [Users] AS [b.Reviewer0] ON [b0].[ReviewerId] = [b.Reviewer0].[UserId]
          LEFT JOIN [Users] AS [b.Author0] ON [b0].[AuthorId] = [b.Author0].[UserId]
          WHERE [b0].[Publisher] LIKE N'Wrox' + N'%' AND (LEFT([b0].[Publisher], LEN(N'Wrox')) = N'Wrox')
      ) AS [t] ON [b.Chapters].[BookId] = [t].[BookId]
      ORDER BY [t].[BookId]

Instead of accessing the database with every property accessing a relation, the data is loaded early with less SQL statements sent to the database. Similar to explicit loading, the model doesn’t need special treatment. This scenario can also be used to return the model type and have all the associated data as needed when you can’t access the context instance to get additional data.

Summary

Using models to load related data is easy as long as the context is available. However, you need to pay attention not to create too many queries accessing the data from the database. If you know the relations needed in advance, you can use eager loading.
With lazy loading, proxy classes are created that derive from the model type. The proxy class overrides virtual properties to retrieve data needed dynamically.

The sample code is based on an EF Core sample from the book Professional C# 7 and .NET Core 2.0. In the book and in the book’s source code repository you can find samples with eager and explicit loading.

If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.

Interesting Links for this article:

Mapping to Getter-only Properties with EF Core

C# 8 & No More NullReferenceExceptions – What about legacy code?

Castle Project

Code Samples for Professional C# 7 and .NET Core 2.0

Complete Sample Code for this article

More information on EF Core and writing data-driven applications is in my book Professional C# 7 and .NET Core 2.0, and in my Data Programming workshops.

Enjoy learning and programming!

Christian

  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

I had some great days at Thrive in Ljubljana, Slovenia – with two presentations. Thank you for joining! Thanks for the organization of the great event in this beautiful city. My presentations and source code are now available for download!

  • Blazor – The New Silverlight?
  • C# 7.x What’s new and what’s coming with C# 8

Blazor – The New Silverlight?

WebAssembly is a new Web Standard for portable code that runs in the browser. Blazor is a Microsoft Project where you can write C# and ASP.NET Core Razor code – making use of WebAssembly. In this session you are invited to start the journey to a new world, a world that can change programming for the Web in the years to come.

With the Blazor presentation I’ve covered:

  • Intro to WebAssembly – features and use cases
  • Intro to Blazor
  • Creating Blazor Apps
  • What’s behind the scenes
  • Dependency Injection in Blazor
  • Razor Pages
  • Creating Blazor Components
  • WebAssembly alternatives for .NET
  • Razor Components

Blazor slides are available at SlideShare

Also read my blog article how to host Blazor with Azure Storage, and access Azure Functions via the HttpClient:

C# 7.x What’s new and what’s coming with C# 8

With C# – What’s next? I started explaining the goals and directions of C#, covering features of C# 7 including the newer versions 7.1, 7.2, and 7.3, and explained new features coming with C# 8 using Visual Studio 2019 Preview 1. Visual Studio 2019 Preview 1 was just on time. I’ve downloaded it in the hotel network just the evening before my session.

Here is a list of language features covered:

  • C# 7
    • tuples
    • deconstruction
    • pattern matching
    • expressions everywhere
    • reference semantics
  • C# 8
    • nullable reference types
    • async streams
    • ranges
    • default interface methods

C# 7 and 8 slides are available at SlideShare

Also read my blog articles covering features of C# 8!

The source code for all the samples is available in my Thrive repository on GitHub!

Read my book Professional C# 7 and . NET Core 2.0 on features of C# 7. You’ll also find Razor Pages in the book covering different variants with code-behind or having C# code in the cshtml file.

Probably you’ve also interest attending one of my .NET Core / ASP.NET Core / UWP / WPF / Azure / Xamarin workshops. For a company-based workshop, content can be completely adapted to your needs.

Enjoy learning and programming!
Christian

  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

With .NET Core, diagnostic information can be written using the ILogger interface. ILogger offers provider-based functionality to write to the console, the debug window, the Windows Event Log, to Microsoft Azure Ap Services diagnostics and logs, as well as to the TraceSource and the EventSource. Adapters to write to 3rd party logging frameworks such as Log4Net and NLog are available as well. What about just logging to files?

Logging with ILogger

The ILogger interface can be injected into a service, and easily used with extension methods to write information using different trace levels such trace, information, and error using the methods LogTrace, LogInformation, and LogError as shown in the following code snippet.

The ILogger interface can also be used without dependency injection, using the LoggerFactory. The interface ILoggerFactory can also be injected using DI.

Configure Microsoft.Services.DependencyInjection

Making the application ready for using the ILogger interface, the logging is added to the DI container invoking the extension method AddLogging. Using the overload with the Action delegate, logging is configured with the providers for the console and the debug window. Configuration information is used as well by applying the section Logging with the configuration. Other than logging, the HTTP client factory is registered with the DI container as well.

See my articles about dependency injection with Microsoft.Extensions.DependencyInjection

TraceSource to write files

The TraceSource class (namespace System.Diagnostics) to write diagnostic information was introduced with the .NET Framework 1.1. TraceSource gives a separation between tracing, providers where to log trace information, and a switch to turn tracing on or off. One of the available switches offers to differentiate trace levels such as verbose, information, and error traces. A provider needs to derive from the base class TraceListener. Derived from this class is the TextWriterTraceListener. Concrete classes deriving from TextWriterTraceListener are DelimitedListTraceListener and XmlWriterTraceListener which allow tracing to files.

To extend the .NET Core logging with trace source logging, the NuGet package Microsoft.Extensions.Logging.TraceSource is needed.

The method ConfigureTraceSourceLogging from the following code snippet creates a text file and passes the stream to the constructor of the TextWriterTraceListener. This listener can then be used with the configuration to log to the trace source.

The extension method AddTraceSource adds trace source logging to .NET Core logging – passing a SourceSwitch to write verbose information, and the previously created TextWriterTraceListener.

Running the application, the following log information is written to the log file. Because the provider is configured to write all verbose trace information, you can also see the information logged from the ClientHandler which is used with the HTTP client factory:

LoggingConfigurationSample.SampleController Information: 2002 : NetworkRequestSampleAsync started with url https://csharp.christiannagel.com
System.Net.Http.HttpClient.SampleController.LogicalHandler Information: 100 : Start processing HTTP request GET https://csharp.christiannagel.com/
System.Net.Http.HttpClient.SampleController.ClientHandler Information: 100 : Sending HTTP request GET https://csharp.christiannagel.com/
System.Net.Http.HttpClient.SampleController.ClientHandler Information: 101 : Received HTTP response after 857.3442ms - OK
System.Net.Http.HttpClient.SampleController.LogicalHandler Information: 101 : End processing HTTP request after 902.6099ms - OK
LoggingConfigurationSample.SampleController Information: 2002 : NetworkRequestSampleAsync completed, received 71575 characters
SeriLog to write files

A more modern way to write log information is offered from a third-party library Serilog. Serilog integrates with .NET Core logging and allows logging to many different sinks, e.g. to Email, Microsoft Teams, NLog, UDP, Azure Table Storage, and many others. With this library, you can also log to files.

To extend the .NET Core logging with serilog and logging to files, the NuGet packages Serilog.Extensions.Logging and Serilog.Sinks.File are needed.

To configure Serilog, either static members of the Log class in the namespace Serilog can be configured, or a new Logger can be created and supplied to the AddSerilog extension method.

With the following code snippet, the extension method AddSerilog is used to define another logging provider. Using the overload of AddSerilog to pass an ILogger, a logger is created with a new LoggerConfiguration that is configured to write to the File sink using the WriteTo property. With the configuration in place, the logger is created using the CreateLogger method.

Running the application, now the log information shows up in the serilog configured log file:

2018-11-11 14:36:45.095 +01:00 [INF] NetworkRequestSampleAsync started with url https://csharp.christiannagel.com
2018-11-11 14:36:45.156 +01:00 [INF] Start processing HTTP request GET "https://csharp.christiannagel.com/"
2018-11-11 14:36:45.165 +01:00 [INF] Sending HTTP request GET "https://csharp.christiannagel.com/"
2018-11-11 14:36:46.026 +01:00 [INF] Received HTTP response after 857.3442ms - "OK"
2018-11-11 14:36:46.029 +01:00 [INF] End processing HTTP request after 902.6099ms - "OK"
2018-11-11 14:36:46.100 +01:00 [INF] NetworkRequestSampleAsync completed, received 71575 characters
Summary

The logging facility offered by .NET Core offers great flexibility. With your services you can work with ILogger and ILoggerFactory, and can use any logger provider configured. Providers for the console class and debugging are built-in. For logging to files, you can use the old and traditional trace source, or other providers such as Serilog which offers a new and modern API. No matter what you select, it’s just a configuration of the logging provider and doesn’t influence the implementation of your service classes.

If this information helped you programming your .NET Core applications, consider buying me a coffee which helps me staying up longer and writing more articles.

More information on logging with .NET Core is in my book Professional C# 7 and .NET Core 2.0, and in my workshops.

Enjoy learning and programming!

Christian

Important links for the article:

Dependency Injection Articles
HTTP Client Factory with .NET Core 2.1
Configuration with .NET Core
Complete source code sample
Serilog

Photo ID 4073128 Files on shelf © Lane Erickson from Dreamstime

Read for later

Articles marked as Favorite are saved for later viewing.
close
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

Separate tags by commas
To access this feature, please upgrade your account.
Start your free month
Free Preview