如何獲取DbSet的主鍵?

.net-core c# entity-framework-core

我使用Net Core 1.1和Entity Framework Core以及流暢的API。我正在為DbSet編寫一個簡單的擴展方法,以在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();
    }
}

這有效,但我希望在顯示之前讓實體按主鍵排序。如果我有DbContext ,可以通過這樣的方式輕鬆完成:

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();

有沒有辦法從DbSet開始獲得相同的結果?

一般承認的答案

這可能,但不是“正式” - 您必須使用標記為此API的某些方法, 此API支持實體框架核心基礎結構,並不打算直接在您的代碼中使用。此API可能會在將來的版本中更改或刪除。

您基本上利用了DbSet<T>實現IInfrastructure<IServiceProvider>這一事實,因此您可以通過GetService方法獲取IDbContextServices ,以便從Model屬性獲取模型:

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();
...

熱門答案

我接受了Ivan Stoev的解決方案,因為它有效,所以它是我的問題的一個非常好的答案。

但正如Ivan所指出的, GetServiceIDbContextService API被標記為“ 此API支持實體框架核心基礎結構,並不打算直接從您的代碼中使用。此API可能會在將來的版本中更改或刪除.. ”而我更喜歡不要在我的代碼中使用它們。

不使用內部和反射的替代方法是重寫擴展方法以接受排序屬性作為參數。這也將增加其靈活性。

我發布這個替代解決方案,因為它可能對具有相同問題的其他人有用:

using System;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using static System.Console;

public static class DbSetExtension
{
    public static void ShowSortedBy<T,TKey>(this DbSet<T> set, Func<T,TKey> keySelector) where T:class
    {
        var sortedSet = set.OrderBy(x => keySelector(x)).ToList();

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

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

        WriteLine();
        WriteLine();

    }
}


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow