带有if的复杂查询
本文关键字:查询 复杂 if 带有 | 更新日期: 2023-09-27 18:00:16
我需要做一个类似getUsers(列表ID)的查询;我需要按ID进行搜索,如果找到了,则返回列表中有ID的用户,如果没有找到,则返回所有用户,或者如果只找到一个,则返回一个用户。
如何编写此查询?
我就是这样开始的:
public List<User> getUsers (List<int> ids)
{
using(var uow = _repository.CreateUnitOfWork())
{
var u = uow.GetEntities<User>().Where(c => c.Id in ids);
if (u == null)
u.ToList();
}
}
您的问题没有意义,因为函数的返回类型必须始终相同。它不能在某些时间返回List
,在其余时间返回User
。
我建议这样做:
public IEnumerable<User> GetUsersByIdOrAllUsers(IEnumerable<int> ids)
{
using (var uow = _repository.CreateUnitOfWork())
{
var users = uow.GetEntities<User>();
if (users.Any(c => ids.Contains(c.ID)))
{
return users.Where(c => ids.Contains(c.ID));
}
return users;
}
}
然后你可以测试你是否只找到一个用户:
var matchingUsers = GetUsersByIdOrAllUsers(ids);
if (matchingUsers.Any() && !matchingUsers.Skip(1).Any())
{
var singleUser = matchingUsers.Single();
// Do stuff with the single user...
}
请注意,IEnumerable
的使用会使操作变得懒惰,从而提高效率。如果您真的想要List
,只需执行:
var matchingUsersList = matchingUsers.ToList()
假设uow.GetEntities<User>()
返回IQueryable<User>
,当列表中有ID的用户时,所提出的解决方案包括执行两个昂贵的IN (...)
SQL查询,还构建两次ids
列表并将其传递到数据库,一次用于Any
,一次为Where
。
我宁愿用不同的方式来构建它。我会在ids.Contains
的基础上用Where
执行一个查询,并将结果具体化到内存中。然后,我会在本地检查它是否包含数据,如果是,将返回结果,其他人将执行第二个查询,而不使用过滤器,这应该会更有效率。
类似这样的东西:
public List<User> getUsers (List<int> ids)
{
using(var uow = _repository.CreateUnitOfWork())
{
var allUsers = uow.GetEntities<User>();
var matchingUsers = allUsers
.Where(user => ids.Contains(user.Id))
.ToList();
return matchingUsers.Any() ? matchingUsers : allUsers.ToList();
}
}
概括一下,您不能用一个数据库查询来执行您想要的操作。它至少需要执行两个查询,唯一的问题是使用最有效的方法。
一个简单的方法是使用Join
public List<User> getUsers (List<int> ids)
{
using(var uow = _repository.CreateUnitOfWork())
{
var u = uow.GetEntities<User>()
.Join(ids,x=>x.Id,y=>y,(x,y)=>x).ToList();
if (u.Count==0)
return uow.GetEntities<User>().ToList()
return u;
}
}
不确定是否有一种不那么健谈的方法可以做到这一点,但从逻辑上讲,可能是这样的?:
if (uow.GetEntities<User>().Any(u => ids.Contains(u.ID))
return uow.GetEntities<User>().Where(u => ids.Contains(u.ID)).ToList();
return uow.GetEntities<User>().ToList();
我在这里假设uow.GetEntities<User>()
只是返回一个可查询的,它本身不会从数据库中实现任何内容,也不会有任何显著的性能损失。如果不是这样,则可能需要将此操作的代码放在DAL中更深的位置。
public IList<User> getUsers (List<int > ids = null)
{
var query = _repository.GetEntities<User>();
if (ids == null)
return query.ToList();
if (ids.Count()==1)
{
var singleUser = query.FirstOrDefault(user => ids.Contains(user.Id));
if (singleUser!= null)
return new List<User>{ singleUser; };
return new List<User>();
}
return query.Where(user => ids.Contains(user.Id)).ToList();
}