Как получить доступ к вычисляемому столбцу в Entity Framework Code First?

Я использую Entity Framework Code First в моем приложении ASP.NET MVC. Один из моих классов имеет несколько столбцов, которые объединены вместе. Я храню эти столбцы в виде вычисляемых столбцов в таблицах, запустив в инициализатор базы данных таблицу изменений script. Скажем, класс выглядит следующим образом:

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

Альтернативный script выглядит примерно так:

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

Я хочу, чтобы столбец Total Sources был доступен для просмотра в веб-приложении. Какой лучший способ это сделать? Атрибут [DatabaseGenerated(DatabaseGeneratedOption.Computed)] не работает, потому что EF Code First создает таблицу из класса перед запуском alter script.

Любые предложения приветствуются.

Ответ 1

У меня есть обходное решение.

Вы можете использовать только рассчитанное поле в существующей базе данных.

Если вы добавляете свое свойство в объект CF как:

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

и если вы добавите строку в свой script, которая удалит информацию о генерации этой базы данных:

DELETE FROM [dbo].[EdmMetadata]

CF предположит, что это существующая база данных, и она будет работать, я только что попробовал.

ОБНОВЛЕНИЕ. Я забыл, если вы добавите свойство в свой объект Bond, как это, тогда в вашем script вам нужно изменить его, чтобы он был рассчитан, а не добавлять его:) Вы даже можете вручную "синхронизировать" базу данных и модель - в точке, где у вас все работает без этого поля, добавьте его в модель как рассчитанную, а в таблицу - как рассчитанную. Когда вы удаляете хэш из таблицы метаданных edm, CF будет работать, не пытаясь восстановить модель с базой данных.

Ответ 2

Это определенно не поддерживается - определение опции Computed в пользовательском свойстве приведет к исключению. Код first = логический код. Если вам нужны пользовательские вычисленные свойства, сначала используйте базу данных. Единственной логикой базы данных, поддерживаемой первым кодом, является столбец идентификатора и временная метка.

Проблема в том, что вам нужен столбец, который будет помечен как вычисленный, но создание базы данных не позволит этого. Если столбец не помечен как вычисленный, он будет updatable = EF будет генерировать операторы обновления, пытающиеся обновить этот столбец, который не будет работать в базе данных.

Ответ 3

Я делаю вычисляемые столбцы в 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;
    }