实体框架属性根据另一个表中的条目计算

时间:2014-09-06 12:26:22

标签: c# entity-framework

假设我有一部电影租赁应用程序(DVD,Blueray或其他一些物理媒体),并且在用户返回电影后,他们可以对其进行评级。这是表格的简化版本:

Ratings
--------------------------------------------
| Id | UserId | MovieId | Rating (1 to 10) |
--------------------------------------------

Movies
------------------------------------------
| Id | Name | Computed rating (1 to 100) |
------------------------------------------

有没有办法配置Entity Framework来使用Ratings表中的条目计算电影的评级?因为在Movies表中有一个Rating字段会有点多余,我想知道Entity框架是否可以为我处理它而不必每次加载电影时都必须这样做。

我知道nHibernate可以将公式与属性相关联。

1 个答案:

答案 0 :(得分:1)

计算聚合值将通过SQL触发器完成。

要创建触发器,您需要覆盖初始值设定项中的Seed方法(CreateDatabaseIfNotExists似乎符合您的情况)。

例如,给定以下模型 -

public class Movie
{
    public string Name { get; set; }
    public int SumOfAllRatings { get; set; }

    public virtual Collection<Rating> Ratings { get; set; }
}

public class Rating
{
    public virtual Movie Movie { get; set; }
    public int Rating { get; set; }

}

和DbContext -

public class MyDbContext : DbContext
{
    public MyDbContext() : base()
    {
        Database.SetInitializer<MyDbContext>(new MyInitializer());
    }

    public DbSet<Movie> Movies { get; set; }
    public DbSet<Rating> Ratings { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Movie>().Property(m => m.SumOfAllRatings)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
    }
}

这是创建适当触发器的初始化程序 -

public class MyInitializer : CreateDatabaseIfNotExists<MyDbContext>
{
  string _sql = "create trigger T_Ratings_Change " +
       "on dbo.Ratings after insert, update as " +
       "update Movies set SumOfAllRatings = " +
       "(select SUM(Rating) from Ratings where MovieId = inserted.MovieId) " +
       "from Movies inner join inserted ON Movies.Id = inserted.MovieId";


  protected override void Seed(MyContext context)
  {
    context.Database.ExecuteSqlCommand(_sql);
  }
}