2012-02-23 16 views
11

エンティティを読み取り専用としてマークし、キーを指定しない方法はありますか?Entity Frameworkコード先頭の読み取り専用エンティティ

+0

コードファーストと読み出しのみを行うことができます種類の相互に排他的です。好奇心のために、主キーが必要ないのはなぜですか? – Brian

+1

Enttityがビューにマップされていて、更新/挿入が必要ではなく、キーもありません。 – Otake

+0

EFは既定でビューの更新を行いません。 –

答えて

11

コードファーストで読み取り専用を実行するためにできることはいくつかあります。最初に問い合わせるときにAsNoTracking()を使用します。

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

これは、あなたがSaveChanges()を呼び出すときに、これらのオブジェクトに対して行われた変更は永続化されませんこれらのエンティティへの変更を追跡しないように、コードファーストを伝えます。

あなたができることは、SaveChanges()を呼び出す前に状態をUnchangedに設定することです。

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

これは、コードエンティティに、そのエンティティに加えられた変更を無視するように指示します。

鍵を持たない限り、すべてのエンティティに鍵が必要です。これは、必ずしもデータベース内の主キーにマッピングされるとは限りませんが、「エンティティセット内のエンティティタイプインスタンスを一意に識別する必要があります」。

+2

こんにちはBrice、あなたの提案は私にとっては理想的な解決策ではありません(NHに存在する読み取り専用のエンティティをマークすることをお勧めします)が、EFでのきちんとした解決策はまだありません。 「すべてのエンティティにキーが必要です」ということで、私はあなたに同意しますが、いくつかのビューで作業しなければならない場合があります。キーを持っていない場合もあります。 。 – Otake

+0

実際には、ここで提案されているICacheableEntityインターフェイスに似たIReadOnlyEntityマーカーインターフェイスを使用することができます(これについてのブログ記事もありますが、もともとはコードが見つかりましたが見つかりませんでした)http://stackoverflow.com/a/ 6593261/34474あなたが考慮する必要があるそれらの間の関係を持ついくつかのつまらないものがあります(興味があれば私に教えてください)。最後に、私たちはブリスがより自動化された方法でしか提案していないことをやっています。 – Cohen

+0

ビューに自然キーがない場合は、EntityFrameworkのヘルプに追加することができます。ビュー定義で : [VirtualKey] ...実体の地図で として \t NEWIDを()SELECT: //主キー this.HasKey(トン=> t.VirtualKey); – Elton

8

EF6でコードファーストを使用して、ビューを反映するエンティティをいくつか作成しましたが、これは明らかに変更または保存すべきではありません。変更されてからエンティティを防ぐために、私は保護され、設定されたプロパティを使用:

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

Entity Frameworkのはまだこのプロパティを設定することが可能であるが、他の開発者が誤ってコンパイル時エラーなしでそれを行うことはできません。これはうまくいくが、トラッキングを完全になくす方が良い解決策になると思われる。 reggaeguitar's answer


おかげで、私からの私のコードを変更することができましたこれに対する答え(以下が役に立つ場合も、彼の答えを投票してください)、そこで表示されます。

public class MyContext : DbContext 
{ 
    public DbSet<TransplantCenterVeiw> 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(); } 
    } 
} 

ので勝利だ、私はこれまで任意の長所と短所を知りませんが、私の既存のコードは、任意の結びせずに作業を続けてきました。

+0

エンティティのトラッキングを無効にする方法については、私の答えを参照してください。 – reggaeguitar

+0

Devs _could_はまだMyContext.Set ()。DoAnyThing()を呼び出しています。 –

1

あなたは全体のエンティティが読み取り専用にしたい場合は、この

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

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

+4

DbSetをDbQueryに変更しました。上記のようにゲッターを変更しました。コンパイル済み。すべての良い。しかし、ビューからデータを読み込むページを実行すると、ランタイムエラーが発生します。「エンティティタイプのMyEntityNameは、現在のコンテキストのモデルの一部ではありません。」そこで、 'protected DbSet _hiddenMyEntitiesName {get;}を追加しました。 set;} 'そして、物事が働いた。上のコードにDbSet <>を追加して、人々が同じ混乱に遭遇しないようにすることは価値があります。しかし、私を正しい道につけてくれてありがとう。 –

+0

興味深い、私はそのエラーを取得しませんでした。私はテーブルではなくビューにマッピングしています。違いがありますか? – reggaeguitar

+0

Hmm ...だから、DbSet プロパティはコンテキストのどこにもありません。奇数...もバージョンの問題になる可能性があります。私はVS 2015とEF6に戻ります。 –

関連する問題