EF Code First Readonly column
Asked Answered
G

2

29

I am using EF Code first with database first approach. "with Database.SetInitializer(null);"

My table has two columns createddate and amendddate. They are managed by SQL Server using triggers. The idea is that when data entry happens then these columns gets data via triggers.

Now What I want to do is to make this read only from EF Code first point of view. I.e. I want to be able to see the createddate and ameneded dates from my app but I dont want to amend these data.

I have tried using private modifiers on setter but no luck.When I try to add new data to the table it tried to enter DateTime.Max date to the database which throws error from SQL server.

Any idea?

Gayden answered 3/7, 2011 at 18:34 Comment(0)
B
43

You cannot use private modifiers because EF itself needs to set your properties when it is loading your entity and Code First can only do this when a property has public setter (in contrast to EDMX where private setters are possible (1), (2)).

What you need to do is mark your for CreatedDate with DatabaseGeneratedOption.Identity and your AmendDate with DatabaseGeneratedOption.Computed. That will allow EF to correctly load data from the database, reload data after insert or update so that entity is up to date in your application and at the same time it will not allow you to change the value in the application because the value set in the application will never be passed to the database. From an object oriented perspective it is not a very nice solution but from the functionality perspective it is exactly what you want.

You can do it either with data annotations:

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

Or with fluent API in OnModelCreating override in your derived context:

modelBuilder.Entity<YourEntity>() 
            .Property(e => e.CreatedDate)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<YourEntity>()
            .Property(e => e.AmendDate)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
Britnibrito answered 3/7, 2011 at 19:1 Comment(4)
Thanks for the quick reply. What is the difference between DatabaseGeneratedOption.Identity and DatabaseGeneratedOption.Computed ? I cant seems to find much details about this on the web. thx edit: Dont answer that I got my answer: msdn.microsoft.com/en-us/library/…. I'll let you know how it goes many thanksGayden
when i put [DatebaseGenerated(DatabaseGeneratedOption.Identity)] attribute for CreatedDate property I'm getting, Update-Database : Identity column 'CreatedDate' must be of data type int, bigint, smallint, tinyint, or decimal or numeric with a scale of 0, and constrained to be nonnullable.Fabrianne
I have same problem. Any solutions?Epiphragm
@Fabrianne - Don't use DatabaseGeneratedOption.Identity for date fields. Instead, use DatabaseGeneratedOption.Computed, which is what Ladislav suggested in his answer.Accrual
S
3

EF core 1.1 or later versions yes you can use read only property in poco classes. What you need to do is using 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;
    }
}

class MyContext : DbContext { public DbSet Blogs { get; set; }

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

}

and fluent api...

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

Take a look here..

Simonnesimonpure answered 10/8, 2018 at 11:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.