忽略SQL的where子句linq中的空参数

问题描述

我需要忽略where子句中的空参数,以便可以从用户端使用应用的过滤器获取适当的数据。为了实现这一点,我目前正在使用if..else嵌套方法,该方法随着参数数量增加而增大。我想知道通过避免行数和复杂性并提高可读性来处理这种情况是否还有其他有效的方法

public List<Members> GetMembers(int currentPosition,string memberStatus,string package,string packageStatus,string branch)
{
    var members = new List<Members>();
    if (package != null)
    {
        //include package
        if (packageStatus != null)
        {
            //include package,packageStatus
            if (branch != null)
            {
                //include package,packageStatus,branch
                members = db.Members.Where(x => x.PackageName == package && x.PackageStatus == packageStatus && x.Branch == branch).ToList();
            }
            else
            {
                //include package,packageStatus
                members = db.Members.Where(x => x.PackageName == package && x.PackageStatus == packageStatus).ToList();
            }
        }
        else
        {
            if (branch != null)
            {
                //include package,branch
                members = db.Members.Where(x => x.PackageName == package && x.Branch == branch).ToList();
            }
            else
            {
                //include package
                members = db.Members.Where(x => x.PackageName == package).ToList();
            }
        }
    }
    else
    {
        if (packageStatus != null)
        {
            //include packageStatus
            if (branch != null)
            {
                //include packageStatus,branch
                members = db.Members.Where(x => x.PackageStatus == packageStatus && x.Branch == branch).ToList();
            }
            else
            {
                //include packageStatus
                members = db.Members.Where(x => x.PackageStatus == packageStatus).ToList();
            }
        }
        else
        {
            if (branch != null)
            {
                //include packageStatus,branch
                members = db.Members.Where(x => x.PackageStatus == packageStatus && x.Branch == branch).ToList();
            }
            else
            {
                //include nothing
                members = db.Members.ToList();
            }
        }
    }

    return members;
}

解决方法

您可以将这些条件添加到查询中。它不会构成可读性最强的SQL,但是假设您发现可读性代码更为重要并相信SQL Server的优化器:

members = db.Members.Where(x =>
    (package == null || x.PackageName == package) &&
    (packageStatus == null || x.PackageStatus == packageStatus) &&
    (branch == null || x.Branch == branch)
).ToList();
        

或者,您可以有条件地将Where()附加到类型IQueryable<Member>的变量中。例如参见entity framework: conditional filter

,

我想建议一种可读的方法:

public List<Members> GetMembers(int currentPosition,string memberStatus,string package,string packageStatus,string branch)
{
    var members = new List<Members>();

    members = db.Members.ToList();

    if (package != null)
    {
        members = members.Where(x => x.PackageName == package);
    }

    if (packageStatus != null)
    {
        members = members.Where(x => x.PackageStatus == packageStatus);
    }

    if (branch != null)
    {
        members = members.Where(x => x.Branch == branch);
    }

    return members.ToList();
}
,

我认为这行得通(没有尝试编译它,但是在我看来很有意义)

    public List<Members> GetMembers(int currentPosition,string branch)
    {
        List<Members> ret = db.Members()
        if(memberStatus != null || package != null || packageStatus != null || branch != null)
        {
            ret = db.Members.Where(x => 
                (memberStatus == null) ? (true) : (memberStatus == x.MemberStatus)
                && (package == null) ? (true) : (package == x.PackageName)
                && (packageStatus == null) ? (true) : (packageStatus == x.PackageStatus)
                && (branch == null) ? (true) : (branch == x.Branch)
            ).ToList();
        }
        return ret;
    }