我正在为EF
bool
应用创建搜索功能。我正在使用动态查询创建它。并遵循此方法https://www.codeproject.com/Articles/493917/Dynamic-Querying-with-LINQ-to-Entities-and-Express
用于为实体的string
和Applicant
字段创建谓词。我的应用中的主要实体是Applicant
EDMX public partial class Applicant
{
public Applicant()
{
this.ApplicantEducations = new HashSet<ApplicantEducation>();
this.ApplicantSkills = new HashSet<ApplicantSkill>();
this.Applications = new HashSet<Application>();
this.Experiences = new HashSet<Experience>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public byte[] CV_Upload1 { get; set; }
public string CV_Upload2 { get; set; }
public string email { get; set; }
public string password { get; set; }
public Nullable<System.DateTime> DOB { get; set; }
virtual ICollection<ApplicantEducation> ApplicantEducations { get; set; }
virtual ICollection<ApplicantSkill> ApplicantSkills { get; set; }
virtual ICollection<Application> Applications { get; set; }
virtual ICollection<Experience> Experiences { get; set; }
}
正在关注
public partial class ApplicantEducation
{
public int id { get; set; }
public Nullable<int> ApplicantId { get; set; }
public Nullable<int> InstituteId { get; set; }
public Nullable<int> EducationLevelId { get; set; }
public Nullable<bool> IsComplete { get; set; }
public Nullable<System.DateTime> DateStart { get; set; }
public Nullable<System.DateTime> DateEnd { get; set; }
public Nullable<short> GPA { get; set; }
public virtual EducationLevel EducationLevel { get; set; }
public virtual Institute Institute { get; set; }
public virtual Applicant Applicant { get; set; }
}
我想搜索,即在申请人类型学院的教育机构中提交的机构名称。申请人可以拥有一个或多个ApplicantEducations对象。
以下是我的申请人教育的EDMX课程
public class Institute
{
public int Id { get; set; }
public string Name { get; set; }
}
我的学院实体课就像这样
private static Expression<Func<TDbType, bool>> ApplyStringCriterion<TDbType,
TSearchCriteria>(TSearchCriteria searchCriteria, PropertyInfo searchCriterionPropertyInfo,
Type dbType, MemberInfo dbFieldMemberInfo, Expression<Func<TDbType, bool>> predicate)
{
// Check if a search criterion was provided
var searchString = searchCriterionPropertyInfo.GetValue(searchCriteria) as string;
if (string.IsNullOrWhiteSpace(searchString))
{
return predicate;
}
// Then "and" it to the predicate.
// e.g. predicate = predicate.And(x => x.firstName.Contains(searchCriterion.FirstName)); ...
// Create an "x" as TDbType
var dbTypeParameter = Expression.Parameter(dbType, @"x");
// Get at x.firstName
var dbFieldMember = Expression.MakeMemberAccess(dbTypeParameter, dbFieldMemberInfo);
// Create the criterion as a constant
var criterionConstant = new Expression[] { Expression.Constant(searchString) };
// Create the MethodCallExpression like x.firstName.Contains(criterion)
var containsCall = Expression.Call(dbFieldMember, StringContainsMethod, criterionConstant);
// Create a lambda like x => x.firstName.Contains(criterion)
var lambda = Expression.Lambda(containsCall, dbTypeParameter) as Expression<Func<TDbType, bool>>;
// Apply!
return predicate.And(lambda);
}
因此,用户将通过指定学院名称进行搜索,所有申请人将通过该学院的教育进行检索。
正如我上面提到的链接。下面举例说明了字符串字段谓词构建
linq
上面的代码,用于构建主实体类(申请人)中包含的简单字符串字段的谓词。但申请人也有ApplicantEducation集合,所以我的问题是如何为 public class SearchCriteriaVM
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? DOB { get; set; }
public string Description { get; set; }
public ICollection<Models.ApplicantEducationVM> ApplicantEducations { get; set; }
public ICollection<Models.ExperienceVM> Experiences { get; set; }
public ICollection<Models.ApplicantSkillsVM> ApplicantSkills { get; set; }
public ICollection<Models.ApplicationsVM> Applications { get; set; }
}
的where子句(方法)创建动态查询(谓词),因此当用户搜索学院名称时,所有申请人都将获得相同的教育。
我的搜索条件如下:
.then()
我有点失落,怎么可能。
由于
答案 0 :(得分:2)
您可以使用以下方法在Lambda表达式中创建 Dynamic Where子句:
public ActionResult GetRecords(int? classId, string name, bool isAll = false)
{
var allRecords = repository.Students;
if (!isAll)
{
//Retrieve active records only
allRecords = allRecords.Where(m => m.StatusId == 1);
}
if (!string.IsNullOrEmpty(name))
{
allRecords = allRecords.Where(m => m.Name.StartsWith(name));
}
if (classId.HasValue)
{
allRecords = allRecords.Where(m => m.ClassId == classId);
}
// other stuff
}
同样,可以应用以下方法,以便仅检索以“query”参数值开头的记录,并在“query”参数值时检索所有记录为空:
IQueryable<StudentViewModel> students = repository.Students.Select(m =>
new StudentViewModel
{
Id = m.Id,
Name = m.Name + " " + m.Surname
});
if (!string.IsNullOrEmpty(query))
{
students = students.Where(m => m.Name.StartsWith(query));
}
或“表现不佳”的另一种方式:
.Where(m => string.IsNullOrEmpty(query) || m.Name.StartsWith(query));
希望这会有所帮助......
答案 1 :(得分:0)
在您的案例中,我们需要的基本功能是使用EF的动态查询构建器。即一种基本的“匹配”方法,它包含作为IQueryable格式的数据,搜索术语以及用于过滤记录的属性。我们需要在代码中使用“ 匹配 ”方法。
public static IQueryable<T> Match<T>(
IQueryable<T> data,
string searchTerm,
IEnumerable<Expression<Func<T, string>>> filterProperties)
{
var predicates = filterProperties.Select(selector =>
selector.Compose(value =>
value != null && value.Contains(searchTerm)));
var filter = predicates.Aggregate(
PredicateBuilder.False<T>(),
(aggregate, next) => aggregate.Or(next));
return data.Where(filter);
}
要构建此表达式方法,我们需要一个 Compose 方法,以便它可以接受需要搜索的参数。
public static Expression<Func<TFirstParam, TResult>>
Compose<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");
var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
这将组成并返回一个lambda表达式,但要构建此方法,我们需要“ 替换 ”扩展方法。顾名思义,此方法将一个表达式的所有实例替换为另一个表达式。
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
回到实际的“匹配”方法,我们需要一个谓词构建器,它将帮助我们呈现与搜索相关的AND,OR查询。
因此,谓词构建器将如下所示:
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Body.Replace(
expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, secondBody), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Body.Replace(
expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
}
}
因此,我们需要的是匹配方法,然后根据您的要求运行。
根据您的模型结构,如果您需要任何进一步的帮助,请告诉我。