必须使用if和else块单独构建表达式谓词?

时间:2014-08-02 14:40:11

标签: c# linq linq-to-entities

我有2个版本的代码用于类方法“GetUserRoles”。如果该方法的传入参数“ exludeRoleNames 缺席 且异常“空对象引用“。我想了解为什么版本2代码并不总是有效,为什么版本1代码需要使用“if”和“else”块构建谓词。提前谢谢。

版本1:
以下代码始终有效。您可能会注意到有单独的“if”和“else”块来构建局部变量Expression<Func<UserRoleInApplication, bool>> predicate

public List<UserInRoleViewModel> GetUserRoles(long userId, params string[] exludeRoleNames)
        {
            List<UserInRoleViewModel> results = null;
            IQueryable<UserInRoleViewModel> items = null;


            Expression<Func<UserRoleInApplication, bool>> predicate = null;

            if (exludeRoleNames.Count() <= 0)
            {
                predicate = x => true;
            }
            else
            {
                predicate = x => !exludeRoleNames.Contains(x.UserRole.RoleName);
            }

            items = from uir in _repository.GetQuery<UserInRole>(x => x.UserId == userId)
                    join ura in _repository.GetQuery<UserRoleInApplication>(predicate)
                            on uir.UserRoleInApplicationId equals ura.UserRoleInApplicationId
                            into g
                    from item in g
                    select new UserInRoleViewModel
                    {
                        UserInRoleId = uir.UserInRoleId,
                        UserId = uir.UserId,
                        UserRoleInApplicationId = uir.UserRoleInApplicationId
                    };


            if (items != null && items.Any())
            {
                results = new List<UserInRoleViewModel>();
                results = items.ToList();
            }

            return results;
       }

版本2:
但是,以下代码在调用方法GetUserRoles时抛出异常“Null对象引用”,例如GetUserRoles(long userId) 而没有传入参数 “exludeRoleNames”。您可能会注意到没有单独的“if”和“else”阻止代码形成局部变量Expression<Func<UserRoleInApplication, bool>> predicate

    public List<UserInRoleViewModel> GetUserRoles(long userId, params string[] exludeRoleNames)
            {
                List<UserInRoleViewModel> results = null;
                IQueryable<UserInRoleViewModel> items = null;

 // Note: one line code and no separate "if" and "else" blocks *************
                Expression<Func<UserRoleInApplication, bool>> predicate = x => exludeRoleNames.Count() <= 0 ? true : !exludeRoleNames.Contains(x.UserRole.RoleName);


                items = from uir in _repository.GetQuery<UserInRole>(x => x.UserId == userId)
                        join ura in _repository.GetQuery<UserRoleInApplication>(predicate)
                                on uir.UserRoleInApplicationId equals ura.UserRoleInApplicationId
                                into g
                        from item in g
                        select new UserInRoleViewModel
                        {
                            UserInRoleId = uir.UserInRoleId,
                            UserId = uir.UserId,
                            UserRoleInApplicationId = uir.UserRoleInApplicationId
                        };


                if (items != null && items.Any()) // Note: throw exception "Null object reference" if parameter "exludeRoleNames" is absent on calling method GetUserRoles such as  GetUserRoles(long userId);
                {
                    results = new List<UserInRoleViewModel>();
                    results = items.ToList();
                }

                return results;
           }

2 个答案:

答案 0 :(得分:1)

尝试更改此内容:

Expression<Func<UserRoleInApplication, bool>> predicate = x => exludeRoleNames.Count() <= 0 ? true : !exludeRoleNames.Contains(x.UserRole.RoleName);

对此:

Expression<Func<UserRoleInApplication, bool>> predicate = x => true;
if(exludeRoleNames != null)
{
    foreach(string exl in exludeRoleNames)
    {    
        string temp = exl;
        predicate = predicate.Or(x=>x.UserRole.RoleName == temp);
    }
}

问题是你试图在exludeRoleNames上调用Count() - 这是null。因此,不要检查Count(),而是将其与null进行比较。如果为null,则可以将其视为空数组。如果它不为空,则检查它的内容。

另一个问题是你不能使用string []。包含在查询上下文中。实体框架(我假设您正在使用)并不支持它。所以,你必须构建谓词。

答案 1 :(得分:0)

我重新编写以下代码,它们正在运行。如果缺少参数“exludeRoleNames”,代码将创建一个空字符串数组:

public List<UserInRoleViewModel> GetUserRoles(long userId, params string[] exludeRoleNames)
            {
                List<UserInRoleViewModel> results = null;
            IQueryable<UserInRoleViewModel> items = null;

            exludeRoleNames = !exludeRoleNames.Any() ? new string[] { } : exludeRoleNames; // a MUST
            Expression<Func<UserRoleInApplication, bool>> predicate = x => !exludeRoleNames.Contains(x.UserRole.RoleName);

            items = from uir in _repository.GetQuery<UserInRole>(x => x.UserId == userId)
                    join ura in _repository.GetQuery<UserRoleInApplication>(predicate)
                            on uir.UserRoleInApplicationId equals ura.UserRoleInApplicationId
                            into g
                    from item in g
                    select new UserInRoleViewModel
                    {
                        UserInRoleId = uir.UserInRoleId,
                        UserId = uir.UserId,
                        UserRoleInApplicationId = uir.UserRoleInApplicationId
                    };

            if (items != null && items.Any())
            {
                results = new List<UserInRoleViewModel>();
                results = items.ToList();
            }

            return results;
           }