C# 编译为存储方法的Linq扩展方法
我有一个代码优先的EF数据库,其中的对象具有跟踪历史的“状态”。它们是这样实现的:C# 编译为存储方法的Linq扩展方法,c#,entity-framework,linq,C#,Entity Framework,Linq,我有一个代码优先的EF数据库,其中的对象具有跟踪历史的“状态”。它们是这样实现的: public class Example { public Example() { this.Statuses = new HashSet<Status>(); } public Guid Id { get; set; } public virtual ICollection<Status> Statuses { get; set;
public class Example
{
public Example()
{
this.Statuses = new HashSet<Status>();
}
public Guid Id { get; set; }
public virtual ICollection<Status> Statuses { get; set; }
}
public class Status
{
public Guid Id { get; set; }
public DateTimeOffset SetOn { get; set; }
public string SetBy { get; set; }
}
我认为,如果我们可以通过扩展来实现这些功能,它会更具可读性,因为获取最新或最旧的状态只是按照升序或降序排序的不同
如果我们已经从数据库中获得了结果,那么像这样的简单扩展方法适用于linq to对象:
public static Status Newest(this IQueryable<Status> items)
{
return items.OrderByDescending(s => s.SetOn).FirstOrDefault();
}
有没有办法将其重构为可转换为存储表达式的扩展方法或表达式?使用LINQKit可以通过定义一个从示例返回状态的表达式,并用LINQKit的Expandable包装IQueryable来完成此操作。使用上面的课程,我可以做如下事情
private Expression<Func<Example, Status>> Newest =
e => e.Statuses.OrderByDescending(s => s.SetOn).FirstOrDefault();
如果您想处理
IQueryable
,为什么要接受IEnumerable
而不是IQueryable
?为什么不为IQueryable
添加此扩展的副本,这样您就可以将这两种情况都覆盖编辑可以IQueryable-但EF提供程序仍然无法将其转换为存储表达式。我将对该示例进行编辑以使其更清晰。为什么不让您的扩展方法采用示例
对象?@NetMage这是可能的,但我们仍然存在一个根本问题,即EF无法将其转换为linq to entities查询的存储表达式。
var date = DateTimeOffset.Parse("4/1/2018");
var query = repository.Where(ex => ex.Statuses.Newest().SetOn > date).FirstOrDefault();
private Expression<Func<Example, Status>> Newest =
e => e.Statuses.OrderByDescending(s => s.SetOn).FirstOrDefault();
var results = from example in repository.AsExpandable()
select new
{
Example = example,
LatestStatus = Newest.Invoke(example)
};