我有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;
}
答案 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;
}