0

如下代码所示,API 会两次命中数据库,执行两次 Linq 查询。我不能通过只点击数据库一次来执行下面显示的操作吗?

var IsMailIdAlreadyExist = _Context.UserProfile.Any(e => e.Email == myModelUserProfile.Email);

var IsUserNameAlreadyExist = _Context.UserProfile.Any(x => x.Username == myModelUserProfile.Username);
4

4 回答 4

4

为了向数据库发出一个请求,您可以首先仅过滤相关值,然后再次检查查询结果中的特定值:

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()调用将对数据库执行一次查询并返回相关值

于 2019-01-21T11:49:07.040 回答
1

从...开始

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();
于 2019-01-21T12:17:22.063 回答
1

用一个小技巧是可能的,它是按一个常数分组的:

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您可以在一个查询中随时访问的所有 s。

并不是说我会像那样推荐它。该代码不是不言自明的,对我来说这似乎是一个过早的优化。

于 2019-01-21T21:06:15.607 回答
0

ValueTuple您可以使用LINQ 的.Aggregate()方法在一行中完成所有操作:

(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)));
于 2019-01-21T14:40:53.637 回答