简体   繁体   English

在asp.net内核中查询

[英]Query in asp.net core

I have a query table like this, people let me ask how can I get the Positions data of the current user when I get the userid to query with the Document table.我有一个这样的查询表,人们让我问当我获取用户 ID 以使用 Document 表查询时,如何获取当前用户的 Positions 数据。

var claimsIdentity = _httpContextAccessor.HttpContext.User.Identity as ClaimsIdentity;
        var userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier)?.Value.ToString();
        var query = from c in _context.Documents
                    join u in _context.Users on c.UserID equals u.Id
                    join p in _context.Positions on u.Id equals p.UserID
                    where c.UserID.ToString() == userId
                    select new { c, u, p };

The data you query is almost enough, but it contains duplicate entries of Document and Position .您查询的数据几乎足够了,但它包含DocumentPosition的重复条目。 If you want the final query to be put in a single object like this:如果您希望将最终查询放入单个 object 中,如下所示:

{
    User = ...,
    Documents = ...,
    Positions = ...
}

You just need to project it using Linq-to-object (because all the data is loaded and ready for projection on the client):您只需要使用 Linq-to-object 进行投影(因为所有数据都已加载并准备好在客户端上投影):

var result = (from document in _context.Documents
             join user in _context.Users on document.UserID equals user.Id
             join position in _context.Positions on user.Id equals position.UserID
             where document.UserID.ToString() == userId
             select new { document, user, position }).AsEnumerable()
             .GroupBy(e => e.user.Id)
             .Select(g => new {
                 User = g.First().user,
                 Documents = g.GroupBy(e => e.document.Id)
                              .Select(e => e.First().document),
                 Positions = g.GroupBy(e => e.position.Id)
                              .Select(e => e.First().position)
             }).FirstOrDefault();

If you don't want to fetch the user info, you don't need to join that DbSet but instead join the two Document and Position directly like this:如果您不想获取用户信息,则不需要加入该 DbSet,而是直接加入两个DocumentPosition ,如下所示:

var result = (from document in _context.Documents
              join position in _context.Positions on document.UserID equals position.UserID
             where document.UserID.ToString() == userId
             select new { document, position }).AsEnumerable()
             .GroupBy(e => e.document.UserID)
             .Select(g => new {
                 Documents = g.GroupBy(e => e.document.Id)
                              .Select(e => e.First().document),
                 Positions = g.GroupBy(e => e.position.Id)
                              .Select(e => e.First().position)
             }).FirstOrDefault();

Note that I suppose your Document and Position both have its own primary key property of Id (adjust that to your actual design).请注意,我假设您的DocumentPosition都有自己的Id主键属性(根据您的实际设计调整)。 Finally, usually if your User entity type exposes navigation collection properties to the Document and Position .最后,通常如果您的User实体类型向DocumentPosition公开导航集合属性 We can have a better (but equal) query like this:我们可以有一个更好(但相等)的查询,如下所示:

var user = _context.Users
                   .Include(e => e.Documents)
                   .Include(e => e.Positions)
                   .FirstOrDefault(e => e.Id.ToString() == userId);

It's much simpler because all the joining internally translated by the EFCore.这要简单得多,因为所有连接都由 EFCore 内部翻译。 The magic is embedded right into the design of navigation collection properties .魔法嵌入到导航集合属性的设计中。

I would like to talk about the important note of the condition UserID.ToString() == userId or Id.ToString() == userId .我想谈谈条件UserID.ToString() == userIdId.ToString() == userId的重要说明。 You should avoid that because it would be translated into a query that breaks the using of index for filtering.您应该避免这种情况,因为它会被翻译成一个查询,从而破坏使用索引进行过滤。 Instead try parsing for an int userId first (looks like it's a string in your case) and use that parsed int directly for comparison in the query, like this:而是首先尝试解析int userId (在您的情况下看起来像是一个字符串)并直接使用解析后的int在查询中进行比较,如下所示:

if(!int.TryParse(userId, out var intUserId)){
    //return or throw exception
}
                           
//here we have an user id of int, use it directly in your query
var user = _context.Users
                   .Include(e => e.Documents)
                   .Include(e => e.Positions)
                   .FirstOrDefault(e => e.Id == intUserId);

That applies similarly to other queries as well.这同样适用于其他查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM