我需要通过数据库(行的总和)来计算我的数据库有一列 - (rowsb的总和)。 我使用的代码,第一个模型的创建数据库。
这里是我的意思是:
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实现这一目标?
Answer 1:
您可以创建计算列在数据库中的表。 在EF模型,你只标注与相应的属性DatabaseGenerated
属性:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public double Summ { get; private set; }
或用流利的映射:
modelBuilder.Entity<Income>().Property(t => t.Summ)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
正如建议Matija葛契奇和评论,这是一个好主意,使物业private set
,因为你可能永远都不想将其设置在应用程序代码。 实体框架与私营制定者没有任何问题。
Answer 2:
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
- 在实体框架代码优先迁移计算列
- 使用计算列
Answer 3:
一种方式是使用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
,但我不会建议,因为我认为这不是好的设计。
另一种方法是使用SQL视图。 您可以阅读像实体框架表的视图。 和视图代码中,你可以做计算或任何你想要的。 只要创建像图
-- 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
Answer 4:
我会去这只要使用一个视图模型。 例如,而不是有FirstTable类作为分贝实体,你会不会更好仅仅有所谓FirstTable视图模型类,然后有一个用于返回这个类将包括所计算的和函数? 例如你的类也只是:
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提到的,我不认为这将是一个不错的主意保持在数据库中的计算值。 只是一些想法。
Answer 5:
截至2019年,EF核心可以让你有与流畅的API一个干净的方式计算列:
假设DisplayName
是要定义计算列,你必须定义属性像往常一样,可能有私人属性访问器,以防止它分配
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// this will be computed
public string DisplayName { get; private set; }
}
然后,在模型生成器,与列定义解决这个问题:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.Property(p => p.DisplayName)
// here is the computed query definition
.HasComputedColumnSql("[LastName] + ', ' + [FirstName]");
}
欲了解更多信息,看看MSDN 。
Answer 6:
我碰到这个问题,想有一个字符串列“弹头”的EF代码优先模式,可以从另一个字符串列“名称”导出时偶然发现。 我采取的方法也略有不同,但结果不错,所以我会在这里分享。
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; }
什么是对这种做法不错的就是你得到的自动生成塞,而从来没有露出塞二传手。 该.ToUrlSlug()方法是不是这个职位的重要组成部分,你可以使用任何在它的地方,你需要做的工作。 干杯!
文章来源: Calculated column in EF Code First