EF Code First Readonly столбец - PullRequest
       43

EF Code First Readonly столбец

22 голосов
/ 03 июля 2011

Сначала я использую код EF с подходом базы данных."with Database.SetInitializer (null);"

В моей таблице есть два столбца: дата и поправка.Они управляются SQL Server с использованием триггеров.Идея состоит в том, что когда происходит ввод данных, эти столбцы получают данные с помощью триггеров.

Теперь я хочу сделать это только для чтения с точки зрения EF Code.Т.е. я хочу, чтобы в моем приложении отображались даты создания и изменения дат, но я не хочу изменять эти данные.

Я пытался использовать частные модификаторы на сеттере, но безуспешно. Когда я пытаюсь добавить новые данные в таблицу, он пытался ввести DateTime.Max date в базу данных, которая выдает ошибку с сервера SQL.

Есть идеи?

Ответы [ 2 ]

36 голосов
/ 03 июля 2011

Вы не можете использовать частные модификаторы, потому что сам EF должен устанавливать ваши свойства, когда он загружает вашу сущность, и Code First может делать это только тогда, когда свойство имеет открытый установщик (в отличие от EDMX, где возможны частные установщики (1 ) , (2) ).

То, что вам нужно сделать, это пометить ваш для CreatedDate с DatabaseGeneratedOption.Identity и ваш AmendDate с DatabaseGeneratedOption.Computed. Это позволит EF правильно загружать данные из базы данных, перезагружать данные после вставки или обновления, чтобы сущность была актуальна в вашем приложении, и в то же время не позволит вам изменять значение в приложении, поскольку значение установлено в приложение никогда не будет передано в базу данных. С объектно-ориентированной точки зрения это не очень хорошее решение, но с точки зрения функциональности это именно то, что вам нужно.

Вы можете сделать это либо с аннотациями данных:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime CreatedDate { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime AmendDate { get; set; }

Или с беглым API в OnModelCreating переопределить в производном контексте:

modelBuilder.Entity<YourEntity>() 
            .Property(e => e.CreatedDate)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<YourEntity>()
            .Property(e => e.AmendDate)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
1 голос
/ 10 августа 2018

EF core 1.1 или более поздние версии да, вы можете использовать свойство только для чтения в классах poco. Что вам нужно сделать, это использовать backing-field.

public class Blog
{
    private string _validatedUrl;

    public int BlogId { get; set; }

    public string Url
    {
        get { return _validatedUrl; }
    }

    public void SetUrl(string url)
    {
        using (var client = new HttpClient())
        {
            var response = client.GetAsync(url).Result;
            response.EnsureSuccessStatusCode();
        }

        _validatedUrl = url;
    }
}

класс MyContext: DbContext { public DbSet Blogs {get; задавать; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Url)
        .HasField("_validatedUrl");
}

}

и беглый апи ...

modelBuilder.Entity<Blog>()
    .Property(b => b.Url)
    .HasField("_validatedUrl")
    .UsePropertyAccessMode(PropertyAccessMode.Field);

Взгляните сюда ..

...