动态导航的通用 LINQ 扩展 属性
Generic LINQ Extension on dynamic Navigation property
我有以下问题,几个小时都无法解决问题:
我有几个要过滤的实体。
它们都有一个共同的 Person 类型的 Navigation 属性 - 尽管在所有这些实体中它的名称并不相同。
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 扩展,它可以用于任何实体集合并采用导航路径 属性 和一些静态过滤器参数。由于我查询的实体没有共同的基础,因此 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.
我也试过它作为 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));
}
为了完整起见,也可能是为了更好地理解,这里是我调用扩展名的方式:
Guid companyId = ... //Some Company's Id
var result = this.unitOfWork.Contracts .HasAnyRelation(c => c.ContractCreator, companyId, CompanyRelationType.Employee);
非常期待您的回答!
您可以像这样使用 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));
}
我有以下问题,几个小时都无法解决问题:
我有几个要过滤的实体。 它们都有一个共同的 Person 类型的 Navigation 属性 - 尽管在所有这些实体中它的名称并不相同。
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 扩展,它可以用于任何实体集合并采用导航路径 属性 和一些静态过滤器参数。由于我查询的实体没有共同的基础,因此 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.
我也试过它作为 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));
}
为了完整起见,也可能是为了更好地理解,这里是我调用扩展名的方式:
Guid companyId = ... //Some Company's Id
var result = this.unitOfWork.Contracts .HasAnyRelation(c => c.ContractCreator, companyId, CompanyRelationType.Employee);
非常期待您的回答!
您可以像这样使用 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));
}