C# 在Linq.Table.Where()中使用可选的OR子句

C# 在Linq.Table.Where()中使用可选的OR子句,c#,asp.net,linq-to-sql,lambda,C#,Asp.net,Linq To Sql,Lambda,有没有办法在可选块的下面进行ProjectID检查?我是最近从JavaEE转换过来的.Net,我正在寻找类似于Hibernate标准API的东西。我想简化下面的代码块,只需调用Where()一次。我也不确定使用lambdas执行Where()的性能影响,因为我一周前才开始使用.Net public IQueryable<Project> FindByIdOrDescription(string search) { int projectID;

有没有办法在可选块的下面进行ProjectID检查?我是最近从JavaEE转换过来的.Net,我正在寻找类似于Hibernate标准API的东西。我想简化下面的代码块,只需调用Where()一次。我也不确定使用lambdas执行Where()的性能影响,因为我一周前才开始使用.Net

public IQueryable<Project> FindByIdOrDescription(string search)
    {
        int projectID;
        bool isID = int.TryParse(search, out projectID);

        IQueryable<Project> projects;

        if (isID)
        {
            projects = dataContext.Projects.Where(p => p.ProjectDescription.Contains(search) || p.ProjectID == projectID);
        }
        else
        {
            projects = dataContext.Projects.Where(p => p.ProjectDescription.Contains(search));
        }

        return projects;
    }
public IQueryable findbyidordordescription(字符串搜索)
{
整数投影;
bool-isID=int.TryParse(搜索,out-projectd);
可供选择的项目;
如果(isID)
{
projects=dataContext.projects.Where(p=>p.ProjectDescription.Contains(search)| | p.projectd==projectd);
}
其他的
{
projects=dataContext.projects.Where(p=>p.ProjectDescription.Contains(search));
}
返回项目;
}

委托/表达式可以“链接”,如下所示(未测试的伪代码):

Expression predicate=p=>p.ProjectDescription.Contains(搜索);
如果(isID)
谓词=p=>谓词(p)| | p.ProjectID==ProjectID;
返回dataContext.Where(谓词);

直到您第一次实际访问iQueryTable的元素时,才会解析和执行查询。因此,无论您在何处添加了多少次(您甚至都没有在这里添加),您都不必担心会多次命中数据库。

如果您希望选择性地添加
和xyz
,您可以简单地链接
where
调用:

var projects = dataContext.Projects.Where(p => p.ProjectDescription.Contains(search));
if (isID)
    projects = projects.Where(p => p.ProjectID == projectID);
不幸的是,当您想执行
或xyz
时,事情就不是那么容易了。要使其工作,您需要手动构建谓词表达式不好看。一种方法是

Expression<Func<Project, bool>> predicate = p => p.ProjectDescription.Contains(search);
if (isID)
{
    ParameterExpression param = expr.Body.Parameters[0];
    predicate = Expression.Lambda<Func<Project, bool>>(
        Expression.Or(
            expr.Body,
            Expression.Equal(
                Expression.Property(param, "ProjectID"),
                Expression.Constant(projectID))),
        param);
}
var projects = dataContext.Projects.Where(predicate);

但是,请检查生成的SQL。

不幸的是,它甚至无法编译。不能在这样的表达式中调用表达式。在LINQ中有其他方法可以这样做吗?也许没有Lambdas?我提供了一个应该可以工作的示例,但它并不漂亮。是的,这看起来比在Hibernate中创建一个新标准要复杂得多。我猜LINQ不支持这样的东西。没错,它非常冗长。但是,对于您的情况,可能有一条捷径。我已经扩展了描述来提到这一点。
Expression<Func<Project, bool>> predicate = p => p.ProjectDescription.Contains(search);
if (isID)
{
    ParameterExpression param = expr.Body.Parameters[0];
    predicate = Expression.Lambda<Func<Project, bool>>(
        Expression.Or(
            expr.Body,
            Expression.Equal(
                Expression.Property(param, "ProjectID"),
                Expression.Constant(projectID))),
        param);
}
var projects = dataContext.Projects.Where(predicate);
var projects = dataContext.Projects.Where(
    p => p.ProjectDescription.Contains(search)
      || (isID && p.ProjectID == projectID));