创建数据库生成计算字段CodeFirst/EntityFramework
本文关键字:CodeFirst EntityFramework 字段 计算 数据库 创建 | 更新日期: 2023-09-27 18:06:50
我正在尝试通过Initial: Migration文件在数据库中创建一个列,类似于遵循本指南。
有一个Transaction
表和一个Account
表。我试着生成Account
属性ReconciledBalance
。它应该计算IsReconciled
为真且IsActive
为真交易中所有余额的总和。
// Example of calculation
ReconciledBalance = Transactions.Where(t => t.IsActive == true && t.IsReconciled == true).Sum(x => x.Amount)
这就是我想在计算列中完成的。我在想我是否离目标越来越近了,或者我是否走在正确的方向上。任何帮助将不胜感激!
// Initial.cs file
public partial class Initial : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Accounts",
c => new
{
Id = c.Int(nullable: false, identity: true),
IsActive = c.Boolean(),
Name = c.String(),
Balance = c.Decimal(nullable: false, precision: 18, scale: 2),
//ReconciledBalance = c.Decimal(),
HouseholdId = c.Int(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Households", t => t.HouseholdId);
Sql("ALTER TABLE dbo.Accounts NOT SURE WHAT TO PUT HERE");
}
public override void Down()
{
//AlterColumn("dbo.Accounts", "ReconciledBalance", c => c.Decimal(nullable: false, precision: 18, scale: 2));
DropTable("dbo.Accounts");
}
}
//Account Model
public class Account
{
public Account()
{
this.Transactions = new HashSet<Transaction>();
}
public int Id { get; set; }
public bool IsActive { get; set; }
public string Name { get; set; }
[Range(double.MinValue, double.MaxValue)]
public decimal Balance { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[Range(double.MinValue, double.MaxValue)]
public decimal ReconciledBalance{ get; set; }
}
//FKs
public int HouseholdId { get; set; }
//Virtual Properties
public virtual Household Household { get; set; }// One to one
public virtual ICollection<Transaction> Transactions { get; set; }
}
// Account Transaction
public class Transaction
{
public Transaction()
{
}
public int Id { get; set; }
public bool IsActive { get; set; }
[DisplayFormat(DataFormatString = "{0:g}", ApplyFormatInEditMode = true)]
public DateTimeOffset Date { get; set; }
[StringLength(150, ErrorMessage ="Description cannot exceed 150 characters.")]
public string Description { get; set; }
[Range(double.MinValue, double.MaxValue)]
public decimal Amount { get; set; }
public bool IsReconciled { get; set; }
public bool IsExpense { get; set; }
[Range(double.MinValue, double.MaxValue)]
public decimal ReconciledAmount { get; set; }
//FKs
public int CategoryId { get; set; }
public string EnteredById { get; set; }
public int AccountId { get; set; }
//Virtual Properties
public virtual Category Category { get; set; }
public virtual ApplicationUser EnteredBy { get; set; }
public virtual Account Account { get; set; }
}
您可以将实体链接到具有实体框架所期望的名称的数据库视图,而不是表:
public override void Up()
{
CreateTable(
"dbo.Accounts_BackingTable",
c => new
{
Id = c.Int(nullable: false, identity: true),
IsActive = c.Boolean(),
Name = c.String(),
Balance = c.Decimal(nullable: false, precision: 18, scale: 2),
HouseholdId = c.Int(),
})
.PrimaryKey(t => t.Id)
Sql(@"EXECUTE('CREATE view dbo.Accounts
with schemabinding as (SELECT
a.id,
a.isactive,
a.name,
a.balance,
a.householdid,
SUM(t.amount) AS ReconciledBalance
FROM dbo.accounts_backingtable a
LEFT JOIN dbo.transactions t
ON t.accountid = a.id AND t.isactive = 1 AND t.isreconciled = 1
--It's not clear what logic you need for the join
--ON t.accountid = a.id AND (t.IsReconciled = 1 or t.IsActive = 1 or t.IsVoid=0)
)
GROUP BY a.id,
a.isactive,
a.name,
a.balance,
a.householdid')");
}
GROUP BY子句可能意味着您的视图是不可更新的,在这种情况下,您需要有两个实体,其中一个是可更新的。或者您可以切换到使用存储过程并修改存储过程中的sql。
注意,这仍然是在动态地进行计算,只是在数据库中而不是在应用程序中。如果您希望将其存储在数据库中,则需要在创建、更新和删除事务时进行计算。
另一种方法:
public class Account
{
public Account()
{
this.Transactions = new HashSet<Transaction>();
}
public int Id { get; set; }
public bool IsActive { get; set; }
public string Name { get; set; }
[Range(double.MinValue, double.MaxValue)]
public decimal Balance { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[Range(double.MinValue, double.MaxValue)]
public decimal ReconciledBalance
{
get
{
return Transactions.Where(t => t.IsActive == true && t.IsReconciled == true).Sum(x => x.Amount)
}
private set { /* needed for EF */ }
}
//FKs
public int HouseholdId { get; set; }
//Virtual Properties
public virtual Household Household { get; set; }// One to one
public virtual ICollection<Transaction> Transactions { get; set; }
}
希望你不需要重写Up()或Down()。(编辑:或者直接删除Sql("ALTER TABLE dbo.Accounts NOT SURE WHAT TO PUT HERE");
)