EF代码优先计算栏

我需要在我的数据库中有一列由数据库计算(行的总和) – (行的总和)。 我使用代码优先模型来创build我的数据库。

这是我的意思:

public class Income { [Key] public int UserID { get; set; } public double inSum { get; set; } } public class Outcome { [Key] public int UserID { get; set; } public double outSum { get; set; } } public class FirstTable { [Key] public int UserID { get; set; } public double Sum { get; set; } // This needs to be calculated by DB as // ( Select sum(inSum) FROM Income WHERE UserID = this.UserID) // - (Select sum(outSum) FROM Outcome WHERE UserID = this.UserID) } 

我如何在EF CodeFirst中实现这一点?

您可以在数据库表中创build计算列 。 在EF模型中,您只需使用DatabaseGenerated属性注释相应的属性:

 [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public double Summ { get; private set; } 

或者stream利的映射:

 modelBuilder.Entity<Income>().Property(t => t.Summ) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed) 

正如Matija Grcic所build议的,在一个评论中,将属性private setprivate set是一个好主意,因为您可能永远都不想在应用程序代码中设置它。 entity framework与私人设置者没有问题。

 public string ChargePointText { get; set; } public class FirstTable { [Key] public int UserID { get; set; } [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public string Summ { get { return /* do your sum here */ } private set { /* needed for EF */ } } } 

参考文献:

  • EF 4.1 DatabaseGeneratedOption.Computed中的错误
  • entity framework代码第一次迁移中的计算列
  • 使用计算列

一种方法是用LINQ来做:

 var userID = 1; // your ID var income = dataContext.Income.First(i => i.UserID == userID); var outcome = dataContext.Outcome.First(o => o.UserID == userID); var summ = income.inSumm - outcome.outSumm; 

你可以在你的POCO对象public class FirstTable做到这public class FirstTable ,但我不会build议,因为我认为这不是好的devise。

另一种方法是使用SQL视图。 你可以像Entity Framework一样读取一个视图。 在视图代码中,你可以做计算或任何你想要的。 只要创build一个像

 -- not tested SELECT FirstTable.UserID, Income.inCome - Outcome.outCome FROM FirstTable INNER JOIN Income ON FirstTable.UserID = Income.UserID INNER JOIN Outcome ON FirstTable.UserID = Outcome.UserID 

我会通过使用视图模型来解决这个问题。 例如,而不是有FirstTable类作为一个数据库实体,你会不会更好只有一个视图模型类称为FirstTable,然后有一个函数,用于返回此类将包括计算的总和? 比如你的class级只是:

 public class FirstTable { public int UserID { get; set; } public double Sum { get; set; } } 

然后你会有一个你调用的函数返回计算的总和:

 public FirsTable GetNetSumByUserID(int UserId) { double income = dbcontext.Income.Where(g => g.UserID == UserId).Select(f => f.inSum); double expenses = dbcontext.Outcome.Where(g => g.UserID == UserId).Select(f => f.outSum); double sum = (income - expense); FirstTable _FirsTable = new FirstTable{ UserID = UserId, Sum = sum}; return _FirstTable; } 

基本上和SQL视图和@Linus一样,我不认为把计算值保存在数据库中是一个好主意。 只是一些想法。

当试图让一个带有string列“Slug”的EF Code First模型从另一个string列“Name”派生时,我偶然发现了这个问题。 我采取的方法略有不同,但工作出色,所以我会在这里分享。

 private string _name; public string Name { get { return _name; } set { _slug = value.ToUrlSlug(); // the magic happens here _name = value; // but don't forget to set your name too! } } public string Slug { get; private set; } 

这种方法有什么好处是你得到自动slu generation一代,而从不暴露slu set者。 .ToUrlSlug()方法不是这篇文章的重要部分,你可以使用任何东西来完成你需要完成的工作。 干杯!