我应该如何访问Entity Framework Code First中的计算列?

时间:2011-08-04 16:16:58

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

我在ASP.NET MVC应用程序中使用Entity Framework Code First。我的一个类有几个相加的列。我通过在数据库初始化程序中运行alter table脚本将这些列存储为表中的计算列。让我们说这堂课看起来像:

public class Bond
{
        public decimal ParAmountOfIssuance { get; set; }
        public decimal AccruedInterest { get; set; }
        public decimal Premium { get; set; }
        public decimal OriginalIssueDiscount { get; set; }
}

alter script类似于:

alter table Bonds
add TotalSources as (ParAmountOfIssuance + AccruedInterest + Premium - OriginalIssueDiscount)

我想让Total Sources列可供在网络应用中查看。实现这一目标的最佳方法是什么? [DatabaseGenerated(DatabaseGeneratedOption.Computed)]属性不起作用,因为EF Code First在运行alter脚本之前从类创建表。

欢迎任何建议。

3 个答案:

答案 0 :(得分:12)

我有一些解决方法。

您只能在现有数据库中使用计算字段。

如果您将属性添加到CF对象:

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public decimal TotalSources { get; set; }

如果您在脚本中添加一行将删除有关该数据库生成的信息:

DELETE FROM [dbo].[EdmMetadata]

CF将假设它是现有数据库并且它将起作用,我刚刚尝试过。

更新我忘了,如果你像这样向你的邦德实体添加属性,那么在你的脚本中你需要改变它来计算它,而不是添加它:) 您甚至可以手动“同步”数据库和模型 - 在没有此字段的情况下将所有内容都工作的位置,将其添加到计算的模型中,并在计算的表中添加。当您从edm元数据表中删除哈希时,CF将无需尝试使用数据库重新生成模型。

答案 1 :(得分:6)

这是definitely not supported - 在自定义属性上定义Computed选项将引发异常。代码优先=代码中的逻辑。如果需要自定义计算属性,请先使用数据库。代码首先支持的唯一数据库逻辑是标识列和时间戳。

问题是您需要将列标记为已计算,但创建数据库将不允许该列。如果列未标记为计算,则它将是可更新的= EF将生成尝试更新此列的更新语句,这将在数据库中失败。

答案 2 :(得分:0)

我正在做CF(WinForms)中的计算列(我不知道它是否是最好的):

这是一个实体:

public class Result
{
    public int ResultId { get; set; }
    public int StudentId { get; set; }
    public Student Student { get; set; }
    public float Arabic { get; set; }
    public float English { get; set; }
    public float Math { get; set; }
    public float Science { get; set; }
    public float Total { get; set; }
}

这是Form2:

    private void Form2_Load(object sender, EventArgs e)
    {
        Model1 model = new Model1();//Model1 : DbContext
        model.Database.CreateIfNotExists();
        model.Database.ExecuteSqlCommand("alter table Results drop column Total; alter table Results add Total AS (Arabic + English + Math + Science)");

        var r1 = (from s in model.Students
                  join r in model.Results
                  on s.StudentId equals r.StudentId
                  select new { s.StudentName, r.Arabic, r.English, r.Science, r.Math, r.Total }).ToList();
        dataGridView1.DataSource = r1;
    }