2017-03-07 66 views
3

我使用Net Core 1.1和Entity Framework Core以及流暢的API。我寫一個簡單的擴展方法DbSet以顯示其實體控制檯:如何獲得DbSet的主鍵?

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

這工作,但我想向他們展示之前,必須按主鍵排序的實體。

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開始同樣的結果:如果我有DbContext它會被輕易做這樣的事情實現的呢?

回答

4

這是可能的,但不是「正式」 - 您必須使用一些標記爲的方法此API支持實體框架核心基礎結構,不能直接在您的代碼中使用。此API可能會在以後的版本中更改或刪除。

你基本上利用了DbSet<T>實現IInfrastructure<IServiceProvider>的事實,這樣你就可以通過GetService方法,以便從Model屬性來獲取模型獲得IDbContextServices

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

我接受了伊萬Stoev的解決方案,因爲它的工作原理,因此是對我的問題非常好的回答。

但作爲伊萬指出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(); 

    } 
}