2014-09-06 58 views
0

比方说,我有一个电影租赁应用程序(DVD,蓝光或其他物理媒体),并且在用户返回电影后,他们可以评价它。这是表的简化版本:从另一个表中的条目计算出的实体框架属性

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

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

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

我知道nHibernate可以将公式与属性联系起来。

+0

代码第一? http://geekswithblogs.net/DavidPaquette/archive/2012/09/23/calculated-columns-in-entity-framework-code-first-migrations.aspx否则将计算列添加到您的表中并使用'[DatabaseGenerated (DatabaseGeneratedOption.Computed)]' – spender 2014-09-06 12:28:48

+0

或者,为您的实体类添加一个'[NotMapped]'属性并在本地执行计算。 – spender 2014-09-06 12:31:49

+0

@spender我读过这篇文章。 “问题是,有没有办法在我的C#类中指定一个属性,该属性是包含同一类的两个属性的一些计算的结果。”这不是我要问的问题。 – Alternatex 2014-09-06 12:31:53

回答

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); 
    } 
} 
+0

这不是要更新Movies表中的Rating列吗?我正在寻找一种方法来避免在该表格中拥有该列,并在我从数据库中拉动电影时即时为我计算电影等级。 – Alternatex 2014-09-08 00:11:04

+0

另一种方法是创建一个get-only属性'Movie.SumOfAllRatings' - 'get {return Ratingss.Sum(r => r.Rating); }'并将其标记为[[NotMapped]'或'modelBuilder.Entity ().Ignore(m => m.SumOfAllRatings)''。但我理解你的陈述**为我处理它,而不必每次我加载电影**时都要这样做,这意味着你想要一个不同的解决方案。 – 2014-09-08 13:21:13

相关问题