c# - Group Join 和 Orderby,同时保持之前的查询
问题描述
在处理一个问题时,我意识到我需要查询表“问题”中的数据依赖于另一个表“Upvotes”中主键“questions.Id”的计数,其中“questionId”是“问题”的外键。 Id”并且可以有多个条目。
所以我的系统是如何工作的,我将赞成票条目添加到赞成票表中,我可以简单地计算(特定问题 ID)和问题总数。
我一直在弄清楚如何获取所有问题的列表及其各自的赞成票。
示例问题表:
id(pk) question
1 "first quues"
2 "second ques"
3 "third ques"
投票表示例:
id(pk) questionid userid(user who upvoted)
1 2 "alpha"
2 2 "charlie"
3 1 "bravo"
4 2 "alpha"
预期输出:
id(question.id) question upvotecount
2 second ques 3
1 first ques 1
3 third ques 0
(注意顺序和数量)
到目前为止我尝试过的查询:
最接近我的输出但需要存储在单独的变量中:
var t = query
.Select(x => new
{
question = x.Id,
count = (from upvotes2 in model.Upvotes
where upvotes2.QuestionId == x.Id
select upvotes2).Count()
})
.OrderByDescending(c => c.count);
foreach (var a in t)
Console.WriteLine("" + a);
我想做什么
query = query
.Select(x => new Question
{
UpvoteCount = (from upvotes2 in model.Upvotes
where upvotes2.QuestionId == x.Id
select upvotes2).Count()
})
.OrderByDescending(c => c.UpvoteCount);
foreach (var a in query)
Console.WriteLine("" + a);
后者给了我:
System.NotSupportedException: '
mYpROEJT.DataAccess.CodeFirstModel.Question
无法在 LINQ to Entities 查询中构造实体或复杂类型。
而前者接近输出,即:
“查询”的类型是IQueryable<Question>
“问题”是从实体生成的一个类,我在[NotMapped] int UpvoteCount
那里添加了一个
{ question = 5, upcount = 2 }
{ question = 3, upcount = 1 }
{ question = 2, upcount = 0 }
{ question = 1, count = 0 }
{ question = 4, count = 0 }
编辑1:添加到原始帖子。我想返回问题列表和 Upvote 计数。
解决方案
所以你有一个集合Questions
。每个Question
都有零个或多个Upvotes
。每一个都Upvote
属于一个Question
,使用外键QuestionId
。这是标准的一对多关系。
Users 和 Upvotes 之间也存在一对多的关系:每个 User 都有零个或多个 Upvote,每个 Upvote 都使用外键完全属于一个用户。
如果您使用实体框架代码优先约定,您将设计这些类,类似于以下内容:
public class Question
{
public int Id {get; set;}
// every Question has zero or more Upvotes:
public virtual ICollection<Upvote> Upvotes {get; set;}
public string QuestionText {get; set;}
... // other properties and relations
}
public class Upvote
{
public int Id {get; set;}
// every Upvote belongs to exactly one Question using foreign key:
public int QuestionId {get; set;}
public virtual Question Question {get; set;}
// every Upvote was done by exactly one User using foreign key:
public int UserId {get; set;}
public virtual User User {get; set;}
... // other properties and relations
}
public class User
{
public int Id {get; set;}
// every User has zero or more Upvotes:
public virtual ICollection<Upvote> Upvotes {get; set;}
... // other properties and relations
}
为了 DbContext 的完整性:
public class MyDbContext : DbContext
{
public DbSet<Question> Questions {get; set;}
public DbSet<UpVote> Upvotes {get; set;}
public DbSet<User> Users {get; set;}
}
因为我坚持实体框架代码优先约定,所以这就是实体框架检测一对多关系所需知道的全部内容。您可能希望表或列有不同的标识符。在这种情况下,您需要使用流畅的 API 或属性。
以正确的实体框架方式设计您的类使您的查询变得非常简单和直观:
using (var dbContext = new MyDbContext())
{
var result = dbContext.Questions // take your table Questions
.Select(question => new // for every question in this table, make one new object
{
Id = question.Id,
Text = question.QuestionText,
UpvoteCount = question.Upvotes.Count,
});
}
因为我使用的是virtual ICollection<Upvote> Upvotes
,实体框架知道Questions
表和Upvotes
表之间需要一个 GroupJoin。在 Sql 中,这将成为一个inner join
后跟一个group by
.
如果您选择偏离标准的实体框架一对多设计,则不能使用ICollection.Count
,您必须自己进行 GroupJoin:
var result = dbContext.Questions.GroupJoin( // GroupJoin Questions with Upvotes
dbContext.Upvotes,
question => question.Id, // from every question take the Id,
upVote => upvote.QuestionId, // from every upvote take the QuestionId,
(question, upvotes) => new // for every question with its matching Upvotes
{ // make one new object
Id = question.Id,
Text = question.QuestionTxt,
UpvoteCount = upvotes.Count(),
});
最后,您想通过减少 UpvoteCount 来订购:
var finalResult = result.OrderByDescending(joinedItem => joinedItem.UpvoteCount);
推荐阅读
- twilio - 如何使用 twilio 记录呼入电话
- html - 可滚动高度忽略 Safari/Chrome 中可滚动 div 的最后一个子项的下边距
- r - 匹配特定列中的前一行并在 R 中执行计算
- spring-mvc - MyBatis 没有关闭 Prepared Statement
- flutter - MaterailApp 小部件没有优雅地缓动
- php - 在 Laravel 中调用字符串上的成员函数 any()
- python - MultiValueDictKeyError 请求方法:GET (Django)
- microsoft-graph-api - /groups 的 MS graph webhook 订阅,不包括成员资格更改?
- npm - package.json 中“npm:@user/package-name”版本的 NPM 等效项?
- laravel - 在 laravel 5.7.29 的本地主机上发送网格发送电子邮件失败