在解决问题时,我意识到我需要查询表“ questions”中的数据取决于另一个表“ Upvotes”中主键“ questions.Id”的数量,其中“ questionId”是外键“ questions.Id”,并且可以有多个条目。
所以我的系统是如何工作的,我将upvotes条目添加到upvote表中,我可以简单地计算(特定问题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:'无法在LINQ to Entities查询中构造实体或复杂类型
mYpROEJT.DataAccess.CodeFirstModel.Question
。
而前者接近输出,即:
“查询”的类型为IQueryable<Question>
“问题”是从Entity生成的类,我在其中添加了[NotMapped] int UpvoteCount
{ question = 5, upcount = 2 }
{ question = 3, upcount = 1 }
{ question = 2, upcount = 0 }
{ question = 1, count = 0 }
{ question = 4, count = 0 }
编辑1:要添加到原始帖子中。 我想返回问题列表和更新计数。
答案 0 :(得分:0)
因此,您有Questions
的集合。每个Question
都有零个或多个Upvotes
。每个Upvote
都使用外键Question
恰好属于一个QuestionId
。这是标准的一对多关系。
Users和Upvotes之间也存在一对多的关系:每个用户拥有零个或多个Upvotes,每个Upvote都使用外键完全属于一个User。
如果您使用entity-framework code-first conventions,则将设计类似于以下内容的此类:
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);