Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the Primary Key for the DbSet?

I use Net Core 1.1 and Entity Framework Core with the fluent API. I am writing a simple extension method for DbSet to show its entities in Console:

public static class DbSetExtension
{
    public static void Show<T>(this DbSet<T> set) where T:class
    {

        WriteLine();
        WriteLine($"Set: {typeof(T).Name} - {set.Count()} objects.");
        WriteLine();

        foreach (var e in set)
        {
            WriteLine(e);
        }

        WriteLine();
        WriteLine();
    }
}

This works but I'd like to have the entities sorted by the primary key before showing them. If I had the DbContext it would have been easily accomplished by doing something like this:

var entityType = db.Model.FindEntityType(typeof(T));
var primaryKeyName = entityType.FindPrimaryKey().Properties.First().Name;
var set = db.Set<T>();
var orderedEntities = (set.OrderBy(e=> e.GetType().GetProperty(primaryKeyName).GetValue(e,null))).ToList();

Is there a way to get the same result starting from the DbSet?

like image 564
nico9T Avatar asked Mar 07 '17 10:03

nico9T


People also ask

How do I get a DbSet?

You can get DbSet from DbContext by Type using the method DbContext. Set(Type entityType) . So if you have the model class name as string you should do some mapping to actual clr type.

How do I set primary key in Entity Framework?

Configuring a primary key By convention, a property named Id or <type name>Id will be configured as the primary key of an entity. Owned entity types use different rules to define keys. You can configure a single property to be the primary key of an entity as follows: Data Annotations.

How do you create a composite primary key in EF core?

Entity Framework Core supports composite keys - primary key values generated from two or more fields in the database. Composite keys are not covered by conventions or data annotation attributes. The only way to configure composite keys is to use the HasKey method.


1 Answers

It's possible, but not "officially" - you have to use some methods marked as This API supports the Entity Framework Core infrastructure and is not intended to be used directly from your code. This API may change or be removed in future releases..

You basically utilize the fact that DbSet<T> implements IInfrastructure<IServiceProvider>, so you can obtain IDbContextServices via GetService method in order to get the model from Model property:

using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;

...
var model = set.GetService<IDbContextServices>().Model;
var entityType = model.FindEntityType(typeof(T));
var properties = entityType.GetProperties();
var primaryKeyName = entityType.FindPrimaryKey().Properties.First().Name;
var sortedSet = (set.OrderBy(e=> e.GetType().GetProperty(primaryKeyName).GetValue(e,null))).ToList();
...
like image 167
Ivan Stoev Avatar answered Sep 19 '22 21:09

Ivan Stoev