[英]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
.您查询的数据几乎足够了,但它包含Document
和Position
的重复条目。 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,而是直接加入两个Document
和Position
,如下所示:
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).请注意,我假设您的Document
和Position
都有自己的Id
主键属性(根据您的实际设计调整)。 Finally, usually if your User
entity type exposes navigation collection properties to the Document
and Position
.最后,通常如果您的User
实体类型向Document
和Position
公开导航集合属性。 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() == userId
或Id.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.