我可以在Entity Framework SubQuery中使用扩展方法吗?

时间:2014-09-02 13:13:56

标签: c# sql-server asp.net-mvc linq entity-framework

我尝试使用Entity Framework整合访问不同表的逻辑。我创建了一个扩展方法,用于从我所在的注册实体中提取所有注册:

public static IEnumerable<Registration> Attending(this IEnumerable<Registration> registrations)
{
    return registrations.Where(r => r.Status == RegistrationStatus.Paid || r.Status == RegistrationStatus.Assigned || r.Status == RegistrationStatus.Completed);
}

这适用于这样的查询:

var attendees = db.Registrations.Attending().ToList();

但是在子查询中使用时它不起作用:

ProductTotals = db.Products.Where(p => p.EventID == ev.Id).Select(p => new ProductSummaryViewModel
{
    ProductID = p.ProductID,
    ProductName = p.Name,
    Registrations = p.Registrations.Attending().Count(),
}).ToList();

我收到以下错误:

  

LINQ to Entities无法识别该方法   &#39; {System.Collections.Generic.IEnumerable {1}} 1 [注册])&#39;   方法,并且此方法无法转换为商店表达式。

有没有办法在子查询中重用该代码?

1 个答案:

答案 0 :(得分:8)

您尝试实现的主要功能是重用定义Attending含义的谓词。您可以通过将表达式存储在一个只读变量中来实现,该变量可供应用程序中的任何人使用,例如在静态类ExpressionConstants中。

public static readonly Expression<Func<Registration, bool>> IsAttending = 
    r => r.Status == RegistrationStatus.Paid
      || r.Status == RegistrationStatus.Assigned
      || r.Status == RegistrationStatus.Completed;

然后你可以做

var attendees = db.Registrations.Where(ExpressionConstants.IsAttending).ToList();

在子查询中使用:

ProductTotals = db.Products.Where(p => p.EventID == ev.Id).Select(p => new ProductSummaryViewModel
{
    ProductID = p.ProductID,
    ProductName = p.Name,
    Registrations = p.Registrations.AsQueryable() // AsQueryable()
                     .Where(ExpressionConstants.IsAttending).Count(),
})

AsQueryable()是必要的,因为p.Registrations可能是ICollection