我使用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
开始获得相同的结果?
答案 0 :(得分:4)
这是可能的,但不是“正式” - 您必须使用标记为的某些方法。此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();
...
答案 1 :(得分:0)
我接受了Ivan Stoev的解决方案,因为它可以解决我的问题。
但正如Ivan所指出的,GetService
和IDbContextService
API被标记为&#34; 此API支持实体框架核心基础结构,不能直接在您的代码中使用。此API可能会在将来的版本中更改或删除。&#34;我宁愿不在我的代码中使用它们。
不使用内部和反射的替代方法是重写扩展方法以接受排序属性作为参数。这也将增加其灵活性。
我发布这个替代解决方案,因为它可能对具有相同问题的其他人有用:
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();
}
}