Bhu*_*tha 2 c# linq linq-to-entities
我的模型如下所示
public class Country
{
public int Id {get; set;}
public string Name {get; set;}
}
public class User
{
public int Id{get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string Email {get; set;}
}
public class Company
{
public int Id{get; set;}
public string Name {get;set;}
public string City {get; set;}
public string Address1 {get; set;}
public string Address2 {get; set;}
[ForeignKey("Country")]
public int CountryId{get; set;}
public Country Country{get; set;}
public ICollection<CompanyUsers> CompanyUsers {get; set;}
}
public class CompanyUsers
{
public int Id{get; set;}
[ForeignKye("Company")]
public int CompanyId {get; set;}
[ForeignKye("User")]
public int UserId {get; set;}
public Country Country{get; set;}
public User User{get; set;}
}
Run Code Online (Sandbox Code Playgroud)
我想让用户能够通过Country, Company or User class Id 属性之外定义的任何属性来搜索公司记录
我尝试查看此SO 讨论,但它不处理导航属性。有人可以帮助我构建动态 where 子句,包括导航属性中的属性。
通过这个实现我只能做如下
myContext.CompanyEntity
.Where(FilterLinq<CompanyEntity>
.GetWherePredicate(searchParams))
.ToList();
public class SearchField
{
public string Key { get; set; }
public string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
从您指出的答案中扩展这个想法并不那么复杂。
您需要更改假设,以便 SerchField 中的属性名称可以包含属性路径的定义,例如Company.CityorCompany.Country.Name以及 property FirstName。你需要处理它:
所以不要只拥有像这样的简单属性:
Expression columnNameProperty = Expression.Property(pe, fieldItem.Name);
Run Code Online (Sandbox Code Playgroud)
你需要处理财产链:
Expression columnNameProperty = GetPropertyExpression(pe, fieldItem.Name);
Expression GetPropertyExpression(Expression pe, string chain){
var properties = chain.Split('.');
foreach(var property in properties)
pe = Expression.Property(pe, property);
return pe;
}
Run Code Online (Sandbox Code Playgroud)
基本上,这段代码的作用是将属性应用于pe创建属性链的每个循环上的先前修改变量。实体框架将处理它并创建适当的连接。这仅适用于单一关系,不适用于集合。
所以该答案的修改后的代码如下所示:
public class FilterLinq<T>
{
Expression GetPropertyExpression(Expression pe, string chain)
{
var properties = chain.Split('.');
foreach(var property in properties)
pe = Expression.Property(pe, property);
return pe;
}
public static Expression<Func<T, Boolean>> GetWherePredicate(params SearchField[] SearchFieldList)
{
//the 'IN' parameter for expression ie T=> condition
ParameterExpression pe = Expression.Parameter(typeof(T), typeof(T).Name);
//combine them with and 1=1 Like no expression
Expression combined = null;
if (SearchFieldList != null)
{
foreach (var fieldItem in SearchFieldList)
{
//Expression for accessing Fields name property
Expression columnNameProperty = GetPropertyExpression(pe, fieldItem.Name);
//the name constant to match
Expression columnValue = Expression.Constant(fieldItem.Value);
//the first expression: PatientantLastName = ?
Expression e1 = Expression.Equal(columnNameProperty, columnValue);
if (combined == null)
{
combined = e1;
}
else
{
combined = Expression.And(combined, e1);
}
}
}
//create and return the predicate
return Expression.Lambda<Func<T, Boolean>>(combined, new ParameterExpression[] { pe });
}
}
Run Code Online (Sandbox Code Playgroud)