创建数据库生成的计算字段CodeFirst / EntityFramework

时间:2016-09-14 04:48:39

标签: c# entity-framework ef-code-first ef-migrations

我正在尝试通过类似于this guide的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; }

}

2 个答案:

答案 0 :(得分:0)

另一种方法:

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");

答案 1 :(得分:0)

您可以使用实体框架预期的名称而不是表格将实体链接到数据库视图:

Criteria cr = session.createCriteria(Recipe.class)
  .createAlias("listOfRecipe_Product", "listOfRecipe_Product")
  .createAlias("listOfRecipe_Product.id", "id")
  .createAlias("id.product", "product")
  .add(Restrictions.eq("product.name", "test"));

GROUP BY子句可能意味着您的视图不是updateable,在这种情况下,您需要有两个实体,其中一个是可更新的。或者您可以切换到使用存储过程并修改存储过程中的sql。

注意,这仍然是在数据库内部而不是在应用程序中进行计算。如果要将其存储在数据库中,则需要在创建,更新和删除事务时进行计算。