我有以下问题,我的头脑缠绕了好几个小时:
我想要过滤几个实体。 它们都有一个共同的 Person 类型的导航属性 - 虽然它在所有这些实体中都没有被称为相同。
Person 实体有一个 CompanyRelation - 实例列表,其中说明了人所拥有的 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扩展,它可以在任何Entity-Collection上使用,并获取导航属性的路径和一些静态过滤器参数。由于我查询的实体没有公共基础,因此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));
}
这里显而易见的问题是我没有物业&#34; ContractCreator&#34;在类型T的通用上下文中。
现在的问题是:我如何转换personExpr,我在其中将导航属性的路径定义为可以编写我的过滤器查询的表单,并且仍然可以使用LINQ to SQL。
我也尝试过将其作为lambda使用tc调用,但由于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));
}
为了完整性&#39;为了更好地理解,这里是我称之为扩展的方式:
Guid companyId = ... //Some Company's Id
var result = this.unitOfWork.Contracts .HasAnyRelation(c => c.ContractCreator, companyId, CompanyRelationType.Employee);
我非常期待你的回答!
答案 0 :(得分:1)
您可以使用LinqKit AsExpandable
和Invoke
扩展方法,如下所示:
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));
}