EF 非规范化每个组加入的结果

EF denormalize result of each group join

我有一个用户和 his/her 学校之间的一对多关系。我经常想为用户获取小学(最高"Type"的那个)。这导致我想 运行 的每个查询都必须加入小学。用户的学校几乎不会改变。是否有关于如何执行此操作以避免不断加入的最佳实践?我应该对模型进行非规范化吗?如果是,怎么做?还有其他更好的方法吗?

谢谢。

public class User
{
   public int Id { get; set; }
   public virtual IList<UserSchool> UserSchools { get; set; }
   ...
}

public class UserSchool
{
   public int UserId { get; set; }
   public string Name { get; set; }
   public int Type { get; set; }
   ...
}

...

var schools = (from r in _dbcontext.UserSchools
               group r by r.UserId into grp
               select grp.OrderByDescending(x => x.Type).FirstOrDefault());

var results = (from u in _dbcontext.Users
               join us in schools on u.Id equals us.UserId
               select new UserContract
               {
                   Id = u.Id,
                   School = us.Name
               });

在过去的项目中,当我选择对数据进行非规范化时,我将其非规范化为单独的表,这些表由数据库本身在后台更新,并试图尽可能多地保留数据库软件中包含的过程,这更好地处理这些事情。请注意,任何类型的 "run every x seconds" 解决方案都会导致数据更新滞后。对于这样的事情,听起来数据变化并不频繁,所以过时几秒(或几分钟,或几天,听上去)并不是什么大问题。如果您正在考虑反规范化,那么检索速度肯定更为重要。

我从来没有 "hard and fast" 何时去规范化的标准,但通常数据必须是:

  1. 经常访问。就像每页经常加载多次一样。绝对地 通常对应用程序至关重要。检索时间必须是最重要的。
  2. 时间不敏感。如果您需要的数据一直在变化,并且您检索的数据是最新的这一点至关重要,那么非规范化的开销太大,无法为您带来太多好处。
  3. 要么是一个非常大的数据集,要么是一个相对复杂的查询的结果。简单的连接通常可以通过适当的索引处理,也可能是索引视图。
  4. 已经尽可能优化。我们已经尝试过索引视图、重组索引、重写底层查询等方法,但速度仍然太慢。

非规范化 可以 非常有帮助,但它会带来自己的麻烦,因此您需要非常确定在将其作为解决您的问题。