如下面的代码所示,API 将命中数据库两次以执行两次 Linq 查询。我不能通过只点击一次数据库来执行下面显示的操作吗?
var IsMailIdAlreadyExist = _Context.UserProfile.Any(e => e.Email == myModelUserProfile.Email);
var IsUserNameAlreadyExist = _Context.UserProfile.Any(x => x.Username == myModelUserProfile.Username);
为了向数据库发出一个请求,您可以先仅过滤相关值,然后再次检查查询结果中的特定值:
var selection = _Context.UserProfile
.Where(e => e.Email == myModelUserProfile.Email || e.Username == myModelUserProfile.Username)
.ToList();
var IsMailIdAlreadyExist = selection.Any(x => x.Email == myModelUserProfile.Email);
var IsUserNameAlreadyExist = selection.Any(x => x.Username == myModelUserProfile.Username);
此处的.ToList()
调用将对数据库执行一次查询并返回相关值
开头为
var matches = _Context
.UserProfile
.Where(e => e.Email == myModelUserProfile.Email)
.Select(e => false)
.Take(1)
.Concat(
_Context
.UserProfile
.Where(x => x.Username == myModelUserProfile.Username)
.Select(e => true)
.Take(1)
).ToList();
这将获得足够的信息来区分四种可能性(无匹配、电子邮件匹配、用户名匹配、两者匹配),单个查询最多返回不超过两行,并且不检索未使用的信息。因此,这样的查询可能很小。
完成此操作后:
bool isMailIdAlreadyExist = matches.Any(m => !m);
bool isUserNameAlreadyExist = matches.LastOrDefault();
可以通过一个小技巧来实现,它按常量分组:
var presenceData = _Context.UserProfile.GroupBy(x => 0)
.Select(g => new
{
IsMailIdAlreadyExist = g.Any(x => x.Email == myModelUserProfile.Email),
IsUserNameAlreadyExist = g.Any(x => x.Username == myModelUserProfile.Username),
}).First();
通过分组,您可以访问 1 个组,其中包含您可以在一个查询中
根据需要访问的所有UserProfile
。并不是说我会像那样推荐它。代码不是不言自明的,对我来说,这似乎是一个过早的优化。
ValueTuple
和 LINQ 的 .聚合() 方法:
(IsMailIdAlreadyExist, IsUserNameAlreadyExist) = _context.UserProfile.Aggregate((Email:false, Username:false), (n, o) => (n.Email || (o.Email == myModelUserProfile.Email ? true : false), n.Username || (o.Username == myModelUserProfile.Username ? true : false)));