Entity Framework Core Extensions: Getting Primary Keys and Dirty Properties

Two simple hacks: finding the primary key values:

public static IDictionary<string, object> GetKeys(this DbContext ctx, object entity)
{
if (ctx == null)
{
throw new ArgumentNullException(nameof(ctx));
}

if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}

var entry = ctx.Entry(entity);
var primaryKey = entry.Metadata.FindPrimaryKey();
var keys = primaryKey.Properties.ToDictionary(x => x.Name, x => x.PropertyInfo.GetValue(entity));

return keys;
}

This returns a dictionary because some entities may have composite primary keys.

As for getting the dirty (modified) properties’ names for an entity:

public static IEnumerable<string> GetDirtyProperties(this DbContext ctx, object entity)
{
if (ctx == null)
{
throw new ArgumentNullException(nameof(ctx));
}

if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}

var entry = ctx.Entry(entity);
var originalValues = entry.OriginalValues;
var currentValues = entry.CurrentValues;

foreach (var prop in originalValues.Properties)
{
if (object.Equals(originalValues[prop.Name], currentValues[prop.Name]) == false)
{
yield return prop.Name;
}
}
}
Picking on the last one, if we wish to reset an entity to it’s original values:
public static void Reset(this DbContext ctx, object entity)
{
if (ctx == null)
{
throw new ArgumentNullException(nameof(ctx));
}

if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}

var entry = ctx.Entry(entity);
var originalValues = entry.OriginalValues;
var currentValues = entry.CurrentValues;

foreach (var prop in originalValues.Properties)
{
currentValues[prop.Name] = originalValues[prop.Name];
}

entry.State = EntityState.Unchanged;
}

Mind you, this one will not reset collections or references, just plain properties.

Hope it helps!

Getting the HTML for a ViewResult in ASP.NET Core

This is another post tagged “hack”: this time, how to get the HTML for a rendered view, in code. This is a standard solution that does not use any kind of reflection (or other) magic.

So, the idea is to pick up a ViewResult (it will also work for a PartialViewResult, but, alas, they do not share a common class – see #6984) and call some method, say, ToHtml, to get the rendered output. This method can look like this:

public static class ViewResultExtensions
{
public static string ToHtml(this ViewResult result, HttpContext httpContext)
{
var feature = httpContext.Features.Get<IRoutingFeature>();
var routeData = feature.RouteData;
var viewName = result.ViewName ?? routeData.Values["action"] as string;
var actionContext = new ActionContext(httpContext, routeData, new ControllerActionDescriptor());
var options = httpContext.RequestServices.GetRequiredService<IOptions<MvcViewOptions>>();
var htmlHelperOptions = options.Value.HtmlHelperOptions;
var viewEngineResult = result.ViewEngine?.FindView(actionContext, viewName, true) ?? options.Value.ViewEngines.Select(x => x.FindView(actionContext, viewName, true)).FirstOrDefault(x => x != null);
var view = viewEngineResult.View;
var builder = new StringBuilder();

using (var output = new StringWriter(builder))
{
var viewContext = new ViewContext(actionContext, view, result.ViewData, result.TempData, output, htmlHelperOptions);

view
.RenderAsync(viewContext)
.GetAwaiter()
.GetResult();
}

return builder.ToString();
}
}
To use it, just do:
var view = this.View(“ViewName”);
var html = view.ToHtml();

Have fun! Winking smile

This is the eight post in a series of posts about bringing the features that were present in Entity Framework pre-Core into EF Core. The others are:

  • Part 1: Introduction, Find, Getting an Entity’s Id Programmatically, Reload, Local, Evict

  • Part 2: Explicit Loading

  • Part 3: Validations

  • Part 4: Conventions

  • Part 5: Getting the SQL for a Query

  • Part 6: Lazy Loading

  • Part 7: Entity Configuration in Mapping Classes

This time I’m going to talk about the possibility to log the generated SQL to the output. In the past, we could do it by assigning a writer to DbContext.Database.Log:

ctx.Database.Log = Console.Log;
This would cause all SQL statements to be sent to the console. We can do something similar in EF Core, by leveraging the logging framework:
var loggerFactory = new LoggerFactory()
.AddDebug((categoryName, logLevel) => (logLevel == LogLevel.Information) && (categoryName == DbLoggerCategory.Database.Command.Name))
.AddConsole((categoryName, logLevel) => (logLevel == LogLevel.Information) && (categoryName == DbLoggerCategory.Database.Command.Name));

var optionsBuilder = new DbContextOptionsBuilder<MyContext>()
.UseLoggerFactory(loggerFactory)
.UseSqlServer(@"<connectionString>");

var ctx = new MyContext(optionsBuilder.Options);
We are creating a new logger factory and populating it with the console and debug providers. You will need to add the Microsoft.Extensions.Logging.Console and Microsoft.Extensions.Logging.Debug NuGet packages (you don’t need both). For each of these providers, we are filtering the output by LogLevel.Information and category DbLoggerCategory.Database.Command.Name (“Microsoft.EntityFrameworkCore.Database.Command”), which are the values used when outputting SQL.

Then, we are creating a DbContextOptionsBuilder and in it we are replacing the default logger factory with our own. We then use it to create an option which we pass to our DbContext’s constructor, or we could do the same in the OnConfiguring method.

The output will look something like this:

SELECT [p].[ProjectId], [p].[CreatedAt], [p].[CreatedBy], [p].[CustomerId], [p].[Description], [p].[End], [p].[Name], [p].[Start], [p].[UpdatedAt], [p].[UpdatedBy]
FROM [Projects] AS [p]

Hope this helps! Winking smile

 

Postal.NET Revisited

Some of you may be aware of my Postal.NET project. It is an open-source library for writing decoupled applications that is available in GitHub and in Nuget. I already blogged about it before.

I recently updated it so that it targets .NET Standard 2.0 and also fixed the namespaces for its companion projects so that they are all under PostalNET. Current version for all projects is 1.2.0.

In a nutshell, Postal.NET publishes messages to channels and topics, either synchronously or asynchronously, and interested parties can subscribe to these.

Besides the core Postal.NET project, there are a few others:

  • PostalConventions.NET: configurable conventions for channels and topics
  • PostalCqrs.NET: a Command-Query Responsibility Segregation library built on top of Postal.NET
  • PostalInterceptor.NET: interception for message publishing
  • PostalRX.NET: Reactive Extensions
  • PostalRequestResponse.NET: a request-response wrapper
  • PostalWhen.NET: “when this, do that”

I still need to write unit tests, but there are many samples available that hopefully will be enough to get you started. If you have interest, please have a look and share your thoughts, either here or by creating issues in GitHub!

User Interface Unit Tests with .NET Core

In a previous post I talked about doing unit tests with .NET Core. What I didn’t cover was unit testing for the user interface (UI). It is actually something quite common, and we will see how we can do it now.

Selenium is a portable software-testing framework for web applications and there is a .NET port of it. We will be using the Selenium.WebDriver package, plus one or more of the following, to target different browsers:

Selenium offers a “minimum” contract that works across all browsers.

I won’t go through all of it, but I will give you some examples on how it works. We start by instantiating a driver:

using (var driver = (IWebDriver) new ChromeDriver(Environment.CurrentDirectory))
{
//...
}
Notice the Environment.CurrentDirectory parameter; it specifies the path where the driver can find the chromedriver.exe file, or geckodriver.exe for Firefox or MicrosoftWebDriver.exe, in the case of IE/Edge. These executables are added automatically by the Nuget packages. If you don’t dispose of the driver, the window will remain open after the unit test finishes. You can also call Quit at any time.
Now, we can navigate to some page:
driver
.Navigate()
.GoToUrl("http://www.google.com");
And find some element from its name:
var elm = driver.FindElement(By.Name("q"));
Besides the name, we can also search by:
  • Id: By.Id
  • CSS class: By.ClassName
  • CSS selector: By.CssSelector
  • Tag name: By.TagName
  • Link text: By.LinkText
  • Partial link text: By.PartialLinkText
  • XPath: By.XPath

Once we find an element, we can access its properties:

var attr = elm.GetAttribute("class");
var css = elm.GetCssValue("display");
var prop = elm.GetProperty("enabled");

Then we can send it text strokes:

elm.SendKeys("asp.net core");

Or click on it:

elm.Click();
As we know, page loading can take some time, so, we can configure the default time to wait for it, probably before we do a GoToUrl:
var timeouts = driver.Manage().Timeouts();
timeouts.ImplicitWait = TimeSpan.FromSeconds(1);
timeouts.PageLoad = TimeSpan.FromSeconds(5);
ImplicitWait is just a time that Selenium waits before searching for an element.
If we need to wait for some period of time, like, until some AJAX request finishes, we can do this:
var waitForElement = new WebDriverWait(driver, TimeSpan.FromSeconds(5));

var logo = waitForElement.Until(ExpectedConditions.ElementIsVisible(By.Id("hplogo")));
The condition passed to ExpectedConditions can be one of:
  • AlertIsPresent
  • AlertState
  • ElementExists
  • ElementIsVisible
  • ElementSelectionStateToBe
  • ElementToBeClickable
  • ElementToBeSelected
  • FrameToBeAvailableAndSwitchToIt
  • InvisibilityOfElementLocated
  • InvisibilityOfElementWithText
  • PresenceOfAllElementsLocatedBy
  • StalenessOf
  • TextToBePresentInElement
  • TextToBePresentInElementLocated
  • TextToBePresentInElementValue
  • TitleContains
  • TitleIs
  • UrlContains
  • UrlMatches
  • UrlToBe
  • VisibilityOfAllElementsLocatedBy
As you can see, you have a wealth of conditions that you can use. If the condition is not met before the timer expires, then the value returned by Until is null.
This can be a nice complement to your unit tests. Hope you find this useful! Winking smile

SignalR in ASP.NET Core

Introduction

SignalR is a Microsoft .NET library for implementing real-time web sites. It uses a number of techniques to achieve bi-directional communication between server and client; servers can push messages to connected clients anytime.

It was available in pre-Core ASP.NET and now a pre-release version was made available for ASP.NET Core. I already talked a few times about SignalR.

Installation

You will need to install the Microsoft.AspNetCore.SignalR.Client and Microsoft.AspNetCore.SignalR Nuget pre-release packages. Also, you will need NPM (Node Package Manager). After you install NPM, you need to get the @aspnet/signalr-client package, after which, you need to get the signalr-client-1.0.0-alpha1-final.js file (the version may be different) from the node_modules\@aspnet\signalr-client\dist\browser folder and place it somewhere underneath the wwwroot folder, so that you can reference it from your pages.

Next, we need to register the required services in ConfigureServices:, before Use

services.AddSignalR();

We will be implementing a simple chat client, so, we will register a chat hub, in the Configure method:

app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("chat");
});

A note: UseSignalR must be called before UseMvc!

You can do this for any number of hubs. as long as you have different endpoints. More on this in a moment.

In your view or layout file, add a reference to the signalr-client-1.0.0-alpha1-final.js file:

<script src="libs/signalr-client/signalr-client-1.0.0-alpha1-final.js"></script>

Implementing a Hub

A hub is a class that inherits from (you guessed it) Hub. In it you add methods that may be called by JavaScript. Since we will be implementing a chat hub, we will have this:

public class ChatHub : Hub
{
public async Task Send(string message)
{
await this.Clients.All.InvokeAsync("Send", message);
}
}

As you can see, we have a single method, Send, which, for this example, takes a single parameter, message. You do not need to pass the same parameters on the broadcast call (InvokeAsync), you can send whatever you want.

Going back to the client side, add this code after the reference to the SignalR JavaScript file:

    <script>
     
        var transportType = signalR.TransportType.WebSockets;
        //can also be ServerSentEvents or LongPolling
        var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
        var chatHub = new signalR.HttpConnection(`http://${document.location.host}/chat`, { transport: transportType, logger: logger });
        var chatConnection = new signalR.HubConnection(chatHub, logger);
     
        chatConnection.onClosed = e => {
            console.log('connection closed');
       };
    
       chatConnection.on('Send', (message) => {
           console.log('received message');
       });
    
       chatConnection.start().catch(err => {
           console.log('connection error');
       });
    
       function send(message) {
           chatConnection.invoke('Send', message);
       }
    
</script>

Notice this:

  1. A connection is created pointing to the current URL plus the chat suffix, which is the same that was registered in the MapHub call
  2. It is initialized with a specific transport, in this case, WebSockets, but this is not required, that is, you can let SignalR figure out for itself what works; for some operating systems, such as Windows 7, you may not be able to use WebSockets, so you have to pick either LongPolling or ServerSentEvents
  3. The connection needs to be initialized by calling start
  4. There is an handler for the Send method which takes the same single parameter (message) as the ChatHub’s Send method

So, whenever someone accesses this page and calls the JavaScript send function, it invokes the Send method on the ChatHub class. This class basically broadcasts this message to all connected clients (Clients.All). It is also possible to send messages to a specific group (we’ll see how to get there):

await this.Clients.Group("groupName").InvokeAsync("Send", message);
or to a specific client:
await this.Clients.Client("id").InvokeAsync("Send", message);
You can add a user, identified by a connection id and and a ClaimsPrincipal, if using authentication, as this:
public override Task OnConnectedAsync()
{
this.Groups.AddAsync(this.Context.ConnectionId, "groupName");

return base.OnConnectedAsync();
}
Yes, the OnConnectedAsync is called whenever a new user connects, and there is a similar method, OnDisconnectedAsync, for when someone disconnects:
public override Task OnDisconnectedAsync(Exception exception)
{
return base.OnDisconnectedAsync(exception);
}
The exception parameter is only non-null if there was some exception while disconnecting.
The Context property offers two properties, ConnectionId and User. User is only set if the current user is authenticated, but ConnectionId is always set, and does not change, for the same user.

Another example, imagine you wanted to send timer ticks into all connected clients, through a timer hub. You could do this in the Configure method:

TimerCallback callback = (x) => {
var hub = serviceProvider.GetService<IHubContext<TimerHub>>();
hub.Clients.All.InvokeAsync("Notify", DateTime.Now);
};

var timer = new Timer(callback);
timer.Change(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(10));
Here we are starting a Timer and, from there, we are getting a reference to the timer hub and calling its Notify method with the current timestamp. The TimerHub class is just this:
public class TimerHub : Hub
{
}
Notice that this class has no public method, because it is not meant to be callable by JavaScript, it merely is used to broadcast messages from the outside (the Timer callback).

Sending Messages Into a Hub

Finally, it is also possible to send messages from the outside into a hub. When using a controller, you need to inject into it an instance of IHubContext<ChatHub>, from which you can send messages into the hub, which will then be broadcast to where appropriate:
private readonly IHubContext<ChatHub> _context;

[HttpGet("Send/{message}")]
public IActionResult Send(string message)
{
//for everyone
this._context.Clients.All.InvokeAsync("Send", message);
//for a single group
this._context.Clients.Group("groupName").InvokeAsync("Send", message);
//for a single client
this._context.Clients.Client("id").InvokeAsync("Send", message);

return this.Ok();
}

Note that this is not the same as accessing the ChatHub class, you cannot easily do that, but, rather, the chat hub’s connections.

Conclusion

SignalR has not been released yet, and it may still undergo some changes. For now, things appear to be working. On a future post I will talk more about SignalR, including its extensibility mechanisms and some more advanced scenarios. Stay tuned!

What’s New and Changed in Entity Framework Core 2

Introduction

By now you should know that EF Core 2 was released on August 14th. It brought something new and some breaking changes too. Alas, it still does not include some of the features that used to be in pre-Core editions and are in high demand, such as lazy loading and support for group by translation. See the list here.

.NET Standard 2.0

Entity Framework Core 2 now targets .NET Standard 2.0, which was also released just now. This means that it will be useful in other scenarios, on any platform that supports it.

Improved SQL Generation

Improvements include:

  • Unneeded nested sub-queries are not created
  • Select only requested columns (projections)
  • No more creating multiple SQL queries for a single LINQ query

Owned Entities

Complex types are back, and they are now called owned entities. Remember that a difference between a complex type and an entity is that the former does not have an identity. Think, for example, of an Address class and several properties, Personal, Work, etc; all of these properties can be mapped to this class, and they will be stored in the same table as the containing entity. It looks like this:

modelBuilder
.Entity<Customer>()
.OwnsOne(c => c.PersonalAddress);

You can also put the content for these properties in another table, and you do it like this:

modelBuilder
.Entity<Customer>()
.OwnsOne(c => c.PersonalAddress)
.ToTable(“CustomerAddress”);

Of course, you can “own” multiple properties at once. Not possible to declare owned entities through attributes at this time.

Table Splitting

You can now have different classes that point to the same physical table, Entity Framework Core will not complain. These classes will probably expose different properties.

Entity State Listener

There’s a new interface that is registered by default, ILocalViewListener, that can be used to track entity changes – not materialized entities, unfortunately:

var events = ctx.GetService<ILocalViewListener>();
events.RegisterView((entry, state) =>
{
//entry contains the entity and state its current state
});

In case you are wondering, you cannot use this to cancel changes, because it is only called after the actual event took place.

Pluralization

There is a new IPluralizer interface and a dummy implementation NullPluralizer. It can be used to pluralize table names when EF is generating the database (dotnet ef database update) or entities when generating classes from it (Scaffold-DbContext). The way to use it is somewhat tricky, as we need to have a class implementing IDesignTimeServices, and this class will be discovered automatically by these tools:

public class CustomPluralizerDesignTimeServices : IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection services)
{
services.AddSingleton<IPluralizer, CustomPluralizer>();
}
}

public class CustomPluralizer : IPluralizer
{
public string Pluralize(string name)
{
return ...;
}

public string Singularize(string name)
{
return ...;
}
}

Because the tools also rely on the dependency injection framework, we are providing an alternative implementation of the IPluralizer interface through it.

DbContext Pools

Normally when a DbContext is injected somewhere by the dependency injection framework, a new instance is created every time. With this, we can have a pool of instances, 128 by default. It is a performance improvement and it is configured like this:

services.AddDbContextPool<DataContext>(options =>
{
//...
}, poolSize: 256);

Attach

The Attach method, for attaching existing entities, is now more clever: if any of the entities in the graph being attached has its key set, it will be treated as unchanged, and if not, as new.

Entity Type Configuration

We can now store entity configuration in separate classes, similar to what we used to have:

public class MyEntityTypeConfiguration : IEntityTypeConfiguration<MyEntity>
{
public void Configure(EntityTypeBuilder<MyEntity> builder)
{
//...
}
}

only these classes are not discovered automatically any more:

modelBuilder.ApplyConfiguration(new MyEntityTypeConfiguration());

Global Filters

Global filters already existed, for entities, not collections, in pre-Core EF. They are useful in essentially two scenarios:

  • For multitenant apps
  • For soft deletes

Its configuration goes like this for soft deletes:

modelBuilder
.Entity<Post>()
.HasQueryFilter(p => !p.IsDeleted);

Or, for a multi-tenant:

modelBuilder
.Entity<Blog>()
.HasQueryFilter(p => p.TenantId == this.TenantId);

It will apply filtering to any entities loaded as the result of a query (including eager loads) or from a one-to-many collection, but it will not filter a query by id, a one-to-one or many-to-one.

You can explicitly disable any existing filters by calling the IgnoreQueryFilters extension method:

ctx
.Blog
.IgnoreQueryFilters()
.ToList();

Disabling Client-Side Evaluation

You may be aware that EF Core can do client-side evaluation of methods that it does not know about, that is, cannot be translated to database calls. This happens transparently and may turn into a performance issue. Should you need to disable this, you now can by configuring the logging infrastructure to throw an exception when client evaluation occurs:

var builder = new DbContextOptionsBuilder<DataContext>()
.ConfigureWarnings(options =>
{
options.Throw(RelationalEventId.QueryClientEvaluationWarning);
options.Default(WarningBehavior.Log);
});

Like

We now have support for SQL’s LIKE function, although in the past we also supported something similar, through the String.Contains method. It goes like this:

ctx
.Posts
.Where(x => EF.Functions.Like(x.Title, “%NET%”)
.ToList();

Unfortunately, Microsoft didn’t make Like an extension method, which I think would be easier to use.

Calling Scalar Functions

Support for calling scalar functions is back too, with some minor caveats:

  • These functions need to be static and declared on the context class
  • They can only return and take as parameters scalar values

An example, first, the declaration, using the T-SQL built-in SOUNDEX function, through the [DbFunction] attribute:

[DbFunction]
public static string Soundex(string name)
{
throw new NotImplementedException();
}

Or by code:

modelBuilder.HasDbFunction(this.GetType().GetMethod(“Soundex”));

In either case you can specify both the schema or the function’s name, if it is different from the method to be used:

[DbFunction("FuncName", Schema = "dbo")]

modelBuilder.HasDbFunction(this.GetType().GetMethod("FuncName"), options =>
{
options.HasName("FuncName");
options.HasSchema("dbo");
});

And its usage:

var sounds = ctx
.MyEntity
.Select(x => x.Soundex(x.Name))
.ToList();

String Interpolation Support

Now, the FromSql and ExecuteSqlCommand methods support interpolated strings, and will happily produce parameters as needed. You do not have to worry about those nasty SQL injection attacks and performance issues due to query plan creation! It goes like this:

ctx
.Database
.ExecuteSqlCommand($"UPDATE Record SET Value = {value} WHERE Id = {id}");

Explicitly Compiled Queries

Entity Framework Core included query caching since version 1, but there is still some overhead associated with calculating the key from the query and getting it from the cache. Therefore, version 2 introduced a capability that existed in LINQ to SQL and Entity Framework pre-Core: explicit query compilation and execution. By this, we are able to pre-compile a query and use it in whatever context we want (of a compatible type, of course). We can even eagerly fetch associated collections or entities:

static readonly Func<MyEntityContext, int, IEnumerable<MyEntity>> 
CompiledQuery = EF.CompileQuery<MyEntityContext, int, MyEntity>((ctx, id) =>
ctx.MyEntities.Where(x => x.Id == id).Include(x => x.Others).OrderBy(x => x.Name));

As you can see, it returns a delegate that we can invoke passing it the proper parameters – in this example, a context and a parameter, but you can have up to 8 parameters, of different types:

var results = CompiledQuery(ctx, 100).ToList();

Breaking Changes

The IDbContextFacfory<T> interface was replaced by IDesignTimeDbContextFactory<T>. The signature of the CreateDbContext method changed also:

public class DummyContextFactory : IDesignTimeDbContextFactory<DummyContext>
{
    public DummyContext CreateDbContext(string[] args)
    {
        var builder = new DbContextOptionsBuilder<DummyContext>();
        builder.UseSqlServer("…");
        return new DummyContext(builder.Options);
    }
}

UseInMemoryDatabase now needs a name:

optionsBuilder.UseInMemoryDatabase("MyDatabase")

Package Microsoft.EntityFrameworkCore.SqlServer.Design is deprecated in favor of Microsoft.EntityFrameworkCore.Design (now provider-agnostic).

Only 2.0 providers will work, so any existing providers that target EF Core 1.x will need to be rewritten.

Logging event IDs have changed from the previous version and they are now identical to those used by corresponding ILogger messages. The logger categories now come from subclasses of DbLoggerCategory, such as DbLoggerCategory.Database.Command, DbLoggerCategory.Migrations, DbLoggerCategory.Infrastructure, etc, all of which offer a Name property.

What’s Still Not Here

Still missing are (not a complete list, mind you):

You can find a more thorough list here: https://weblogs.asp.net/ricardoperes/missing-features-in-entity-framework-core.

Conclusion

Still a long way to go; especially, GroupBy translation, many to many and lazy loading seems to be taking forever, both are scheduled for the next version (2.1) though. Non-relational providers are also nowhere to be seen. This new version has interesting new stuff and Microsoft seems to be going in the right direction, but it strikes me as odd that such high demand features are still absent. Let’s see how things evolve.

References

https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-entity-framework-core-2-0

https://docs.microsoft.com/en-us/ef/core/what-is-new

https://github.com/aspnet/EntityFrameworkCore/wiki/Roadmap

https://github.com/aspnet/EntityFrameworkCore/issues?q=is%3Aopen+is%3Aissue+milestone%3A2.0.0

https://weblogs.asp.net/ricardoperes/missing-features-in-entity-framework-core

Implementing Missing Features in Entity Framework Core – Part 7: Entity Configuration in Mapping Classes

This is the seventh post in a series of posts about bringing the features that were present in Entity Framework pre-Core into EF Core. The others are:

  • Part 1: Introduction, Find, Getting an Entity’s Id Programmatically, Reload, Local, Evict

  • Part 2: Explicit Loading

  • Part 3: Validations

  • Part 4: Conventions

  • Part 5: Getting the SQL for a Query

  • Part 6: Lazy Loading

This time I’m going to cover automatic entity configuration in mapping classes, that is, outside of the DbContext.OnModelCreating method. If you remember, Entity Framework Code First supported having classes inheriting from EntityTypeConfiguration in the same assembly as the context, and these classes would be loaded automatically. This made it much simpler to add new mapping classes to a project without touching the context.

This functionality hasn’t been ported to Entity Framework Core yet, but it is being developed for the next version, and is tracked by ticket 2805. My implementation finds mapping classes in the same assembly as the context automatically, or it can load configuration explicitly from a mapping class. Here is my contract for the mapping class:

public interface IEntityTypeConfiguration<T> where T : class
{
void Configure(EntityTypeBuilder<T> entityTypeBuilder);
}

As you can see, this needs to be implemented in a concrete generic class and bound to a specific entity type.

The actual implementation goes like this:

public static class EntityTypeConfigurationExtensions
{
private static readonly MethodInfo entityMethod = typeof(ModelBuilder).GetTypeInfo().GetMethods().Single(x => (x.Name == "Entity") && (x.IsGenericMethod == true) && (x.GetParameters().Length == 0));

private static Type FindEntityType(Type type)
{
var interfaceType = type.GetInterfaces().First(x => (x.GetTypeInfo().IsGenericType == true) && (x.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)));
return interfaceType.GetGenericArguments().First();
}

private static readonly Dictionary<Assembly, IEnumerable<Type>> typesPerAssembly = new Dictionary<Assembly, IEnumerable<Type>>();

public static ModelBuilder ApplyConfiguration<T>(this ModelBuilder modelBuilder, IEntityTypeConfiguration<T> configuration) where T : class
{
var entityType = FindEntityType(configuration.GetType());

dynamic entityTypeBuilder = entityMethod
.MakeGenericMethod(entityType)
.Invoke(modelBuilder, new object[0]);

configuration.Configure(entityTypeBuilder);

return modelBuilder;
}

public static ModelBuilder UseEntityTypeConfiguration(this ModelBuilder modelBuilder)
{
IEnumerable<Type> configurationTypes;
var asm = Assembly.GetEntryAssembly();

if (typesPerAssembly.TryGetValue(asm, out configurationTypes) == false)
{
typesPerAssembly[asm] = configurationTypes = asm
.GetExportedTypes()
.Where(x => (x.GetTypeInfo().IsClass == true) && (x.GetTypeInfo().IsAbstract == false) && (x.GetInterfaces().Any(y => (y.GetTypeInfo().IsGenericType == true) && (y.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)))));
}

var configurations = configurationTypes.Select(x => Activator.CreateInstance(x));

foreach (dynamic configuration in configurations)
{
ApplyConfiguration(modelBuilder, configuration);
}

return modelBuilder;
}
}

You can see that it uses some dynamic magic to make things simpler, otherwise we’d need to have even more reflection. Dynamics take care of these things quite nicely.

The code essentially looks at the entry assembly and finds all non-abstract public types that implement IEntityTypeConfiguration<T>. For each of those, it creates an instance, extracts the template argument and creates an EntityTypeBuilder<T> from calling the Entity<T> method of the ModelBuilder class and calls the IEntityTypeConfiguration<T>.Configure method of the instantiated mapping class passing it the EntityTypeBuilder<T> which allows it to supply mapping configuration for the mapped entity (T).

We need to explicitly call this extension inside DbContext.OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.UseEntityTypeConfiguration();
base.OnModelCreating(modelBuilder);
}

And it takes care of everything for us. Or, if we want to load a single mapping class explicitly, we can also do so:

modelBuilder.UseEntityTypeConfiguration<MyEntityTypeConfiguration>();

Finally, a simple mapping class might be:

public class MyEntityTypeConfiguration : IEntityTypeConfiguration<MyEntity>
{
public void Configure(EntityTypeBuilder<MyEntity> entityTypeBuilder)
{
entityTypeBuilder.ToTable("MyEntity");
entityTypeBuilder.Property(x => x.MyEntityId).HasColumnName("Id");
}
}

In case you’re interested, this feature is similar to the one being implemented for .NET Core, except that it doesn’t find mapping classes automatically. The IEntityTypeConfiguration<T> interface is exactly the same.

Implementing Missing Features in Entity Framework Core – Part 6: Lazy Loading

This will be the sixth post in my series of posts about bringing the features that were present in Entity Framework pre-Core into EF Core. The others are:

  • Part 1: Introduction, Find, Getting an Entity’s Id Programmatically, Reload, Local, Evict

  • Part 2: Explicit Loading

  • Part 3: Validations

  • Part 4: Conventions

  • Part 5: Getting the SQL for a Query

As you may know, the second major version of Entity Framework Core, 1.1, was released recently, however, some of the features that used to be in the non-Core versions still didn’t make it. One of these features is lazy loading of collections, and I set out to implement it… or, any way, something that I could use instead of it! Smile

Here’s what I came up with. First, let’s define a class that will act as a proxy to the collection to be loaded. I called it CollectionProxy<T>, and it goes like this:

internal sealed class CollectionProxy<T> : IList<T> where T : class
{
private bool _loaded;
private bool _loading;
private readonly DbContext _ctx;
private readonly string _collectionName;
private readonly object _parent;
private readonly List<T> _entries = new List<T>();

public CollectionProxy(DbContext ctx, object parent, string collectionName)
{
this._ctx = ctx;
this._parent = parent;
this._collectionName = collectionName;
}

private void EnsureLoaded()
{
if (this._loaded == false)
{
if (this._loading == true)
{
return;
}

this._loading = true;

var entries = this
._ctx
.Entry(this._parent)
.Collection(this._collectionName)
.Query()
.OfType<T>()
.ToList();

this._entries.Clear();

foreach (var entry in entries)
{
this._entries.Add(entry);
}

this._loaded = true;
this._loading = false;
}
}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
this.EnsureLoaded();

return this._entries.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return (this as ICollection<T>).GetEnumerator();
}

int ICollection<T>.Count
{
get
{
this.EnsureLoaded();
return this._entries.Count;
}
}

bool ICollection<T>.IsReadOnly
{
get
{
return false;
}
}

void ICollection<T>.Add(T item)
{
this.EnsureLoaded();
this._entries.Add(item);
}

void ICollection<T>.Clear()
{
this.EnsureLoaded();
this._entries.Clear();
}

bool ICollection<T>.Contains(T item)
{
this.EnsureLoaded();
return this._entries.Contains(item);
}

void ICollection<T>.CopyTo(T[] array, int arrayIndex)
{
this.EnsureLoaded();
this._entries.CopyTo(array, arrayIndex);
}

bool ICollection<T>.Remove(T item)
{
this.EnsureLoaded();
return this._entries.Remove(item);
}

T IList<T>.this[int index]
{
get
{
this.EnsureLoaded();
return this._entries[index];
}

set
{
this.EnsureLoaded();
this._entries[index] = value;
}
}

int IList<T>.IndexOf(T item)
{
this.EnsureLoaded();
return this._entries.IndexOf(item);
}

void IList<T>.Insert(int index, T item)
{
this.EnsureLoaded();
this._entries.Insert(index, item);
}

void IList<T>.RemoveAt(int index)
{
this.EnsureLoaded();
this._entries.RemoveAt(index);
}

public override string ToString()
{
this.EnsureLoaded();
return this._entries.ToString();
}

public override int GetHashCode()
{
this.EnsureLoaded();
return this._entries.GetHashCode();
}
}

You can see that, in order to be as compliant as possible, I made it implement IList<T>; this way, it can be easily compared and switched with, for example, ICollection<T> and, of course, the mother of all collections, IEnumerable<T>. How it works is simple:

  1. It receives in its constructor a pointer to a DbContext, the collection’s parent, and the collection-to-be-made-lazy’s name;
  2. There is an EnsureLoaded method that essentially checks if the collection has already been loaded, and, if not the case, does so, through the new (in EF Core 1.1) explicit loading API; it populates an internal list with the loaded collection’s items;
  3. Inner fields _loading and _loaded act as defenses to prevent the collection to be loaded twice, or to enter an infinite loop (stack overflow);
  4. I implemented all inherited methods and properties as explicit implementations, but there was no need for that, just a personal preference; all of them ensure that the collection is loaded (EnsureLoaded) before delegating to its internal field list;
  5. ToString and GetHashCode delegate to the internal list as well.

I created as well an extension method to make it’s usage more simple:

public static class CollectionExtensions
{
public static void Wrap<TParent, TChild>(this DbContext ctx, TParent parent, Expression<Func<TParent, IEnumerable<TChild>>> collection) where TParent : class where TChild : class
{
var prop = ((collection.Body as MemberExpression).Member as PropertyInfo);
var propertyName = prop.Name;

prop.SetValue(parent, new CollectionProxy<TChild>(ctx, parent, propertyName));
}
}

As you can see, I kept it very simple – no null/type checking or whatever, that is left to you, dear reader, as an exercise! Winking smile

Finally, here’s how to use it:

using (var ctx = new MyContext())
{
var parentEntity = ctx.MyParentEntities.First();

ctx.Wrap(parentEntity, x => x.MyChildren); //sets up the proxy collection

var childEntitiesCount = parentEntity.MyChildren.Count(); //forces loading

foreach (var child in parentEntity.MyChildren) //already loaded, so iterate in memory
{
child.ToString();
}
}

Hope you like it! Let me know your thoughts!

What’s New in Entity Framework Core 1.1

Introduction

Entity Framework Core 1.1 was released last November. With it, besides some bug fxes and semi-transparent improvements, came along a few goodies. If you read my previous post on features missing in Entity Framework Core 1.0, you’ll be please to know that a few have been addressed.

New API Methods

The Find method, for returning an entity from its primary key, is back (I had provided a workaround here):

var e1 = ctx.DbSet<MyEntity>().Find(1);

New is GetDatabaseValues, which goes to the database and fetches the current values for the current entity and primary key:

var dbProperties = ctx.Entry<MyEntity>(e).GetDatabaseValues();

Reload and Explicit Load

It is now again possible to reload an entity, causing it to be re-hydrated with the current values from the database, through the Reload method (also available as a workaround here):

ctx.Entry<MyEntity>(e).Reload();

And it is also possible to force load a not-loaded collection ():

ctx.Entry<MyEntity>(e).Collection(x => x.MyColl).Load();

As well as entity references (one-to-one, many-to-one):

ctx.Entry<MyEntity>(e).Reference(x => x.MyRef).Load();

Connection Resiliency

Connection resiliency made it way to version 1.1 as well:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer("my connection string", opt => opt.EnableRetryOnFailure());

base.OnConfiguring(optionsBuilder);
}

The EnableRetryOnFailure method is just a wrapper around ExecutionStrategy passing it SqlServerRetryingExecutionStrategy:

optionsBuilder
.ExecutionStrategy(x => new MyExecutionStrategy(x));

This one allows you to provide your own strategy for retries, by implementing IExecutionStrategy.

Configurable Change Tracking

Now, this is something that could have been really cool, but, as it is now, I find it somewhat crippled… you can now tell Entity Framework Core how should it find out if an entity has changed – the common change tracker functionality. But, the only supported techniques are the built-in (default, based on snapshots) or the use of INotifyPropertyChanged/INotifyCollectionChanged. This is not really that extensible, as you only have these two options. Here is how you configure it:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>()
.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangedNotifications);

base.OnModelCreating(modelBuilder);
}

If you want to use this approach, your entity must implement INotifyPropertyChanged and all of its collections must implement INotifyCollectionChanged. If any of the properties or collections in it changes, you must raise the PropertyChanged or CollectionChanged events, otherwise EF will not know that it is modified.

This can be set as the default for all entities, by the way:

modelBuilder
.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangedNotifications);

Using Fields

A most welcome addition, that was never previously available, is mapping to fields! This better supports a pure Domain Driven Design approach. It needs to be configured using code mapping:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<MyEntity>()
.Property(b => b.MyProp)
.HasField("_myField");

base.OnModelCreating(modelBuilder);
}

IEnumerable Collections

Another handy improvement is the ability to map collections declared as IEnumerable<T>, whereas in the past this was only possible for ICollection<T> (and derived classes, of course). The configuration is the same:

modelBuilder
.Entity<MyEntity>()
.HasMany(x => x.Children);

Of course, the concrete collection class must itself implement ICollection<T>, otherwise Entity Framework would have no way to populate it:

public class MyEntity
{
public IEnumerable<MyChild> Children { get; } = new HashSet<MyChild>();
}

Support for SQL Server In Memory Tables

In case you are using Hekaton, you can now tell Entity Framework that your entity is persisted as a memory-optimized table:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>()
.ForSqlServerIsMemoryOptimized();

base.OnModelCreating(modelBuilder);
}

Switching Services

Last, but not least, EF Core 1.1 makes it much easier to replace one of the services that EF uses internally:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.ReplaceService<IEntityStateListener, CustomEntityStateListener>();

base.OnConfiguring(optionsBuilder);
}

Conclusion

It’s nice to see things progressing, but there’s still a long way to go. In particular, as I said in my post about the missing features, there are quite a few features that still didn’t make it. In particular, I still miss:

  • Group By translation
  • Lazy loading
  • Date/Time operations
  • Support for custom SQL functions
  • Many-to-many relations
  • Command and query interception

We just have to wait for the next priorities of the team.