Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Code First ReadOnly Entity

Is there any way to mark an entity as read-only and not specify any key for it?

like image 384
Otake Avatar asked Feb 23 '12 14:02

Otake


3 Answers

There are a couple of things that you can do to enforce read-only in Code First. The first is to use AsNoTracking() when you query.

var readOnlyPeople = (from p in context.People
                        where p.LastName == "Smith"
                        select p).AsNoTracking();

This tells Code First to not track changes to these entities, so when you call SaveChanges() no changes made to these objects will be persisted.

The seccond thing you can do is set the state to Unchanged before calling SaveChanges().

context.Entry(person).State = EntityState.Unchanged;
context.SaveChanges();

This tells Code First to ignore any changes that have been made to that entity.

As far as not having a key, all entities must have a key. This may not necessarily map to a primary key in the database, but it "must uniquely identify an entity type instance within an entity set".

like image 139
bricelam Avatar answered Nov 07 '22 23:11

bricelam


Using code-first in EF6, I created some entities that reflect Views, which obviously shouldn't be modified or saved. To prevent the Entity from being changed, I used protected set properties:

public class TransplantCenterView
{
    public string TransplantsThisYear { get; protected set; }
}

Entity Framework is still able to set this property, but other developers can't accidentally do it without a compile-time error. This works great, but it seems the better solution would be to eliminate tracking completely.


Thanks to reggaeguitar's answer, it appears there is an answer to this (please also vote his answer up if the following is helpful), which has allowed me to change my code from:

public class MyContext : DbContext
{
    public DbSet<TransplantCenterView> TransplantCenterViews { get; set; }
}

To:

public class MyContext : DbContext
{
    // appears the DbSet is still needed to make Set<Entity>() work
    protected DbSet<TransplantCenterView> _transplantCenterViews { get; set; }
    // this .AsNoTracking() disables tracking for our DbSet.
    public DbQuery<TransplantCenterView> TransplantCenterViews
    {
        get { return Set<TransplantCenterView>().AsNoTracking(); }
    }
}

I don't know of any pros and cons to this, but my existing code has continued working without any hitches, so seems a win.

like image 37
Kevin Nelson Avatar answered Nov 08 '22 01:11

Kevin Nelson


If you want the entire entity to be read-only you can do this

/// Using a dbquery since this is readonly.
/// </summary>
public DbQuery<State> States
{
  get
  {
    // Don't track changes to query results
    return Set<State>().AsNoTracking();
 }
}

source http://www.adamtuliper.com/2012/12/read-only-entities-in-entity-framework.html

like image 2
reggaeguitar Avatar answered Nov 08 '22 00:11

reggaeguitar