【问题标题】:Generic LINQ Extension on dynamic Navigation property动态导航属性上的通用 LINQ 扩展
【发布时间】:2016-11-13 11:17:36
【问题描述】:

我遇到了以下几个小时都无法解决的问题:

我有几个要过滤的实体。 它们都有一个共同的 Person 类型的导航属性 - 尽管在所有这些实体中它的名称不同。

Person 实体有一个 CompanyRelation-Instances 列表,其中说明了 Person 必须具备的 Relation一家公司

public class Person
{
   public Collection<CompanyRelation> CompanyRelations { get; set; }
}

public enum CompanyRelationType
{
    Employee,
    Manager
}

public class Contract
{
    public Person ContractCreator { get; set; }
}

public class CompanyRelation
{
    public virtual Guid PersonId { get; set; }

    public virtual Person Person { get; set; }

    public virtual Guid CompanyId { get; set; }

    public virtual Company Company { get; set; }

    public virtual CompanyRelationType RelationType { get; set; }
}

我现在想编写一个通用的 LINQ 扩展,它可以用于任何实体集合,并采用导航属性的路径和一些静态过滤器参数。由于我查询的实体没有共同的基础,LINQ 扩展在类型 T 上是通用的。

到目前为止,我想出了这样的事情:

    public static IQueryable<T> HasRelation<T>(this IQueryable<T> query, Expression<Func<T, Person>> personExpr, Guid companyId, CompanyRelationType relationType)
    {
        return query = query.Where(tc => tc.ContractCreator.CompanyRelations.Any(cr => cr.CompanyId == companyId));            
    }

这里明显的问题是我在 T 类型的通用上下文中没有属性“ContractCreator”。

现在的问题是:如何转换 personExpr,在其中我将导航属性的路径定义为可以编写过滤器查询并且仍然可以使用 LINQ to SQL 的表单。

我也尝试将它作为我用 tc 调用的 lambda,但由于 LINQ to SQL 不支持调用,所以它也不起作用:

    public static IQueryable<T> HasRelation<T>(this IQueryable<T> query, Func<T, Person> personExpr, Guid companyId, CompanyRelationType relationType)
    {
        return query = query.Where(tc => personExpr(tc).CompanyRelations.Any(cr => cr.CompanyId == companyId));            
    }

为了完整起见,也许为了更好地理解,这里我称之为扩展:

Guid companyId = ... //Some Company's Id

var result = this.unitOfWork.Contracts      .HasAnyRelation(c => c.ContractCreator, companyId, CompanyRelationType.Employee);

我真的很期待你的回答!

【问题讨论】:

  • 您对第三方库开放还是想要本地解决方案?
  • 只要 3rd 方库可以免费用于商业用途,并且对本地解决方案有显着改进,我会考虑使用它。我已经集成了 LinqKit,如果这有帮助的话。
  • 它确实有帮助:)

标签: .net entity-framework linq generics linq-to-sql


【解决方案1】:

你可以像这样使用LinqKitAsExpandableInvoke扩展方法:

public static IQueryable<T> HasRelation<T>(this IQueryable<T> query, Expression<Func<T, Person>> personExpr, Guid companyId, CompanyRelationType relationType)
{
    return query.AsExpandable().Where(tc => 
        personExpr.Invoke(tc).CompanyRelations.Any(cr => cr.CompanyId == companyId));            
}

【讨论】:

  • 非常感谢您的回答!我在编辑到表达式之前首先尝试了该解决方案,但已经弄清楚了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 2012-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多