对实现投票系统的关系进行建模
本文关键字:关系 建模 系统 实现 | 更新日期: 2023-09-27 17:54:11
我对投票系统的实现感到困惑。我想知道一个帖子的投票赞成和投票反对的计数,也保存投票赞成或反对的选民。我使用下面的模型
public class Post : Entity
{
public string Title { get; set; }
public virtual User Owner { get; set; }
public virtual List<User> UpVoters { get; set; }
public virtual List<User> DownVoters { get; set; }
}
我觉得这个设计有点问题,因为如果我必须表示一个帖子的投票和投票计数,所以我认为我必须处理2个查询。使用导航属性计数会导致性能问题,如果我只是需要计数。我说的对吗?
下面的第二种方法也让我感到困惑,因为VoteUpCount和VoteDownCount应该总是由开发人员手动处理。当选民改变他的投票时,总是重新更新值,这看起来有点代码味。
public class Post : Entity
{
public string Title { get; set; }
public virtual User Owner { get; set; }
public int VoteUpCount { get; set; }
public int VoteDownCount { get; set; }
public virtual List<User> UpVoters { get; set; }
public virtual List<User> DownVoters { get; set; }
}
你能告诉我哪个更好吗?为什么更好呢?我还有别的选择吗?最后一个帖子持有3用户导航属性,这让我觉得有些东西可能是错误的。这段关系有什么问题吗?
本能地,我将创建一个Vote实体,因为您想保存有关投票的信息:
public class Vote : Entity
{
public User User {get;set;}
public int VoteDirection {get;set;} // 1 or -1
// any other info...
}
然后在Post类中添加Vote字段:
public class Post : Entity
{
public string Title { get; set; }
public virtual User Owner { get; set; }
public virtual List<Vote> Votes { get; set; }
}
然后计算每个Votes的VoteDirection的总和…
我不认为这里有什么问题。
我看你的第一个模型还不错。除非您能证明获取相关实体的计数会影响性能,否则我不会采用第二种方法。过早优化是万恶之源;-)。如果出于性能原因需要存储计数,那么第二个模型也可以。只需确保添加投票更新了count字段。
你的第一个模型是正确的,你不应该为了EF的缺点而牺牲你的模型,而且第二个版本不是很可维护——有太多的思考和手工工作。
当您想要检索计数时,实际上有一个EF物化所有相关实体的解决方案,语法不是很直观,但确实会产生正确的SQL查询:
var myPost = context.Posts.First();
int upvotersCount = context.Entry(myPost)
.Collection(p => p.UpVoters)
.Query()
.Count();
详细说明如下。
作为一般的经验法则,您应该在模型中使用ICollection<User>
而不是具体的List<User>
。
Using navigation properties counts would cause performance problems if i just need counts. Am i right?
-您心中有什么样的性能问题?
通常,添加count字段会在数据库中引入冗余,但这是一个明显的性能优化步骤。如果我是你,我会问自己在这种情况下是否需要提高表现。有多少帖子和投票将在数据库中?有多少用户将同时访问这些信息?等。如果您的应用程序需要真正的可伸缩,您可以添加额外的计数,并确保它们被正确更新。否则,你只需要记住这种可能性,而不是急于实现它。