Web isteği başına bir DbContext… neden?


398

Entity Framework'ün nasıl ayarlanacağını açıklayan birçok makale okudum, DbContextböylece çeşitli DI çerçeveleri kullanarak HTTP web isteği başına yalnızca bir tane oluşturuldu ve kullanıldı.

Bu neden ilk etapta iyi bir fikir? Bu yaklaşımı kullanarak ne gibi avantajlar elde edersiniz? Bunun iyi bir fikir olacağı bazı durumlar var mı? DbContextHer depo yöntemi çağrısına örnek oluştururken yapamayacağınız bu tekniği kullanarak yapabileceğiniz şeyler var mı ?


9
Mehdi.me/ambient-dbcontext-in-ef6'daki Gueddari, depo yöntemi başına DbContext örneğini bir karşıt- madde çağrısı olarak adlandırır. Alıntı: "Bunu yaparak, Entity Framework'ün DbContext üzerinden sağladığı 1. seviye önbellek, kimlik haritası, iş birimi ve değişiklik izleme ve tembel yükleme yetenekleri dahil hemen hemen her özelliğini kaybediyorsunuz. ." DBContexts'in yaşam döngüsünü ele almak için mükemmel öneriler içeren mükemmel makale. Kesinlikle okumaya değer.
Christoph

Yanıtlar:


565

NOT: Bu yanıt Entity Framework'lerden bahseder DbContext, ancak SQL'lere LINQ DataContextve NHibernate'ler gibi her türlü İş Birimi uygulaması için geçerlidir ISession.

Ian'ı yankılayarak başlayalım: DbContextTüm uygulama için tek bir sahip olmak Kötü Bir Fikirdir. Bunun mantıklı olduğu tek durum, tek iş parçacıklı bir uygulamanız ve yalnızca o tek uygulama örneği tarafından kullanılan bir veritabanınız olmasıdır. İş DbContextparçacığı için güvenli değildir ve DbContextverileri önbelleğe aldığından, kısa bir süre içinde eski haline gelir. Bu, birden fazla kullanıcı / uygulama aynı anda bu veritabanında çalıştığında (bu çok yaygın bir durumdur) sizi her türlü sıkıntıya sokacaktır. Ama bunu zaten bilmenizi bekliyorum ve neden sadece yeni bir örneğini (yani geçici bir yaşam tarzı ile) DbContextihtiyaç duyan herkese enjekte etmeyeceğinizi bilmek istiyorum . (tek bir DbContext-veya iş parçacığı başına bağlamda bile - neden kötü olduğu hakkında daha fazla bilgi için bu yanıtı okuyun ).

DbContextGeçici olarak kaydolmanın işe yarayabileceğini söyleyerek başlayayım, ancak tipik olarak belirli bir kapsamda böyle bir iş biriminin tek bir örneğine sahip olmak istiyorsunuz. Bir web uygulamasında, bir web isteğinin sınırları üzerine böyle bir kapsam tanımlamak pratik olabilir; böylece Web Başına İstek yaşam tarzı. Bu, bir dizi nesnenin aynı bağlam içinde çalışmasına izin vermenizi sağlar. Başka bir deyişle, aynı ticari işlem dahilinde çalışırlar.

Aynı bağlamda bir dizi işlemin yürütülmesi hedefiniz yoksa, bu durumda geçici yaşam tarzı iyidir, ancak izlenmesi gereken birkaç şey vardır:

  • Her nesne kendi örneğini aldığından, sistemin durumunu değiştiren her sınıfın çağırması gerekir _context.SaveChanges()(aksi takdirde değişiklikler kaybolur). Bu, kodunuzu karmaşıklaştırabilir ve koda ikinci bir sorumluluk ekler (bağlamı kontrol etme sorumluluğu) ve Tek Sorumluluk İlkesinin ihlalidir .
  • [Tarafından yüklenen ve kaydedilen DbContext] varlıkların hiçbir zaman böyle bir sınıfın kapsamından ayrılmadığından emin olmanız gerekir , çünkü bunlar başka bir sınıfın bağlam örneğinde kullanılamaz. Bu, kodunuzu büyük ölçüde karmaşıklaştırabilir, çünkü bu varlıklara ihtiyacınız olduğunda, bunları kimlikle tekrar yüklemeniz gerekir; bu da performans sorunlarına neden olabilir.
  • Yana DbContextuygular IDisposable, muhtemelen hala tüm oluşturulan örneklerini imha etmek istiyorum. Bunu yapmak istiyorsanız, temel olarak iki seçeneğiniz vardır. Onları aradıktan hemen sonra aynı yöntemle atmanız gerekir context.SaveChanges(), ancak bu durumda iş mantığı dışarıdan aktarılan bir nesnenin sahipliğini alır. İkinci seçenek, oluşturulan tüm örnekleri Http İsteği sınırına atmaktır, ancak bu durumda kabın, bu örneklerin ne zaman Atılması gerektiğine dair bilgi vermesi için bir çeşit kapsam belirlemeye ihtiyacınız vardır.

Başka bir seçenek de hiç enjekte etmemekDbContext . Bunun yerine, DbContextFactoryyeni bir örnek oluşturabilecek bir tane enjekte edersiniz (geçmişte bu yaklaşımı kullanırdım). Bu şekilde iş mantığı bağlamı açık bir şekilde kontrol eder. Böyle görünebilirse:

public void SomeOperation()
{
    using (var context = this.contextFactory.CreateNew())
    {
        var entities = this.otherDependency.Operate(
            context, "some value");

        context.Entities.InsertOnSubmit(entities);

        context.SaveChanges();
    }
}

Bunun artı tarafı, DbContextaçıkça yaşamı yönetmeniz ve bunu ayarlamanızın kolay olmasıdır. Ayrıca, belirli bir kapsamda, tek bir iş işleminde kod çalıştırma ve varlıkların aynı kaynaktan geldiği için geçiş yapma gibi belirgin avantajlara sahip tek bir bağlam kullanmanıza izin verir DbContext.

Dezavantajı, DbContextyöntemden yönteme (Yöntem Enjeksiyonu olarak adlandırılır) geçmeniz gerekecek olmasıdır . Bir anlamda bu çözümün 'kapsamlı' yaklaşımla aynı olduğunu, ancak şimdi kapsamın uygulama kodunun kendisinde kontrol edildiğini (ve muhtemelen birçok kez tekrarlandığını) unutmayın. İş birimini oluşturmak ve atmaktan sorumlu olan uygulamadır. Yana DbContextbağımlılık grafiği yapımının ardından oluşturulan, Yapıcı Enjeksiyon resmin dışında olduğunu ve bir sınıftan diğerine bağlama geçmesi gerekiyor olduğunda Yöntem Enjeksiyon için ertelemek gerekir.

Yöntem Enjeksiyon o kadar da kötü değil, ancak iş mantığı daha karmaşık hale geldiğinde ve daha fazla sınıf dahil olduğunda, yöntemi çok yöntemle sınıftan sınıfa geçirmek zorunda kalacaksınız, bu da kodu çok karmaşık hale getirebilir (gördüm bu geçmişte). Basit bir uygulama için, bu yaklaşım iyi olur.

Dezavantajları nedeniyle, bu fabrika yaklaşımı daha büyük sistemler için vardır, başka bir yaklaşım yararlı olabilir ve bu, kabın veya altyapı kodunun / Kompozisyon Kökünün iş birimini yönetmesine izin verdiğiniz yaklaşımdır . Sorunuzun söz konusu olduğu stil bu.

Konteynerin ve / veya altyapının bunu halletmesine izin vererek, uygulama mantığınız iş mantığını basit ve temiz (yalnızca Tek Sorumluluk) tutan bir UoW ​​örneği oluşturmak, (isteğe bağlı olarak) oluşturmak ve imha etmek zorunda kalmadan kirlenmez. Bu yaklaşımla ilgili bazı zorluklar vardır. Örneğin, vakayı taahhüt ettiniz mi ve imha ettiniz mi?

Bir iş biriminin imha edilmesi, web isteğinin sonunda yapılabilir. Bununla birlikte, birçok insan yanlış bir şekilde , bunun aynı zamanda iş birimini yürütmenin yeri olduğunu varsayar. Ancak, uygulamada bu noktada, iş biriminin gerçekten işlenmesi gerektiğinden emin olamazsınız. Örneğin, iş katmanı kodu çağrı kaydında daha fazla yakalanan bir istisna atarsa, kesinlikle İşlem yapmak istemezsiniz.

Gerçek çözüm yine bir tür kapsamı açıkça yönetmek, ancak bu sefer Kompozisyon Kökü içinde yapın. Komut / işleyici deseninin arkasındaki tüm iş mantığını soyutlayarak, bunu yapmanıza izin veren her komut işleyicisinin etrafına sarılabilen bir dekoratör yazabilirsiniz. Misal:

class TransactionalCommandHandlerDecorator<TCommand>
    : ICommandHandler<TCommand>
{
    readonly DbContext context;
    readonly ICommandHandler<TCommand> decorated;

    public TransactionCommandHandlerDecorator(
        DbContext context,
        ICommandHandler<TCommand> decorated)
    {
        this.context = context;
        this.decorated = decorated;
    }

    public void Handle(TCommand command)
    {
        this.decorated.Handle(command);

        context.SaveChanges();
    } 
}

Bu, bu altyapı kodunu yalnızca bir kez yazmanızı sağlar. Herhangi bir katı DI kabı, böyle bir dekoratörü, tüm ICommandHandler<T>uygulamaların etrafına tutarlı bir şekilde sarılacak şekilde yapılandırmanıza izin verir .


2
Vay canına - kapsamlı cevap için teşekkürler. Eğer iki kez oy verseydim, yapardım. Yukarıda, "... bir dizi operasyonun aynı bağlam içinde çalışmasına izin vermek gibi bir niyet yok, bu durumda geçici yaşam tarzı gayet iyi ..." diyorsunuz. Özellikle "geçici" ile ne demek istiyorsun?
Andrew

14
@Andrew: 'Geçici' bir Bağımlılık Enjeksiyonu konseptidir, yani bir hizmet geçici olacak şekilde yapılandırılırsa, tüketiciye her enjekte edildiğinde hizmetin yeni bir örneği oluşturulur.
Steven

1
@ user981375: CRUD işlemleri için bir genel CreateCommand<TEnity>ve bir genel oluşturabilirsiniz CreateCommandHandler<TEntity> : ICommandHandler<CreateCommand<TEntity>>(ve Güncelleme ve Sil için de aynısını yapabilirsiniz ve tek bir GetByIdQuery<TEntity>sorgu vardı ). Yine de, kendinize bu modelin CRUD işlemleri için yararlı bir soyutlama olup olmadığını veya sadece karmaşıklık ekleyip eklemediğini sormalısınız. Yine de, bu modeli kullanarak kesişen endişeleri (dekoratörler aracılığıyla) kolayca ekleme olanağından yararlanabilirsiniz. Artıları ve eksileri tartmak zorunda kalacaksınız.
Steven

3
+1 Bu cevabı gerçekten okumadan önce yazdığımı düşünüyor musunuz? BTW IMO Sonunda DbContext'in Bertarafını tartışmanızın önemli olduğunu düşünüyorum (konteynır agnostik kalmanız harika olsa da)
Ruben Bartelink

1
Ama bağlamı dekore edilmiş sınıfa geçirmiyorsunuz, dekore edilmiş sınıf nasıl geçiyordu TransactionCommandHandlerDecorator? örneğin, dekore edilmiş sınıf InsertCommandHandlersınıfsa içeriğe ekleme işlemini (EF'de DbContext) nasıl kaydedebilir?
Mesud

35

Microsoft'un birbiriyle çelişen iki önerisi var ve birçok kişi DbContexts'i tamamen farklı bir şekilde kullanıyor.

  1. Bir öneri "DbContexts mümkün olan en kısa sürede atın" çünkü bir DbContext Alive sahip db bağlantıları vb gibi değerli kaynakları kaplar ....
  2. Diğer devletler istek başına bir DbContext çok tavsiye

Bunlar birbirinize aykırı çünkü isteğiniz Db şeyler ile ilgisiz bir çok şey yapıyorsa, o zaman DbContext hiçbir nedenle tutulur. Bu nedenle, talebiniz sadece rastgele şeylerin yapılmasını beklerken DbContext'inizi canlı tutmak israftır ...

Kural 1'i izleyen pek çok kişi "Depo deseni" içinde DbContexts'e sahip olur ve Veritabanı Sorgusu başına yeni bir Örnek oluşturur , böylece İstek başına X * DbContext

Sadece verilerini alırlar ve ASAP bağlamını elden çıkarırlar. Bu, birçok kişi tarafından kabul edilebilir bir uygulama olarak kabul edilir. Bu, db kaynaklarınızı minimum süre boyunca işgal etmenin faydalarına sahip olsa da, EF'in sunduğu tüm UnitOfWork ve Caching şekerlerini açıkça feda eder .

DbContext'in çok amaçlı tek bir örneğini canlı tutmak , Önbelleğe Alma avantajlarını en üst düzeye çıkarır, ancak DbContext iş parçacığı için güvenli olmadığından ve her Web isteği kendi iş parçacığında çalıştığından, İstek başına bir DbContext en uzun sende kalabilir.

EF'in istek başına 1 Db Bağlamı kullanma konusundaki ekip önerisi, bir Web Uygulamasında büyük olasılıkla bir UnitOfWork'un bir istek içinde olacağı ve bu isteğin bir iş parçacığı olacağı gerçeğine dayanmaktadır. Yani istek başına bir DbContext UnitOfWork ve Caching'in ideal yararı gibidir.

Ancak çoğu durumda bu doğru değildir. Ben düşünün açılıyor böylece Sonrası Talep Günlüğü yeni DBContext içinde olan ayrı bir UnitOfWork zaman uyumsuz iş parçacığı tamamen kabul edilebilir

Son olarak, bir DbContext'in ömrünün bu iki parametre ile sınırlı olduğu anlaşılmaktadır. UnitOfWork ve İş Parçacığı


3
Adil olmak gerekirse, HTTP istekleriniz oldukça hızlı bir şekilde bitiyor olmalıdır (birkaç ms). Bundan daha uzun sürüyorlarsa, isteğin hemen geri dönebilmesi için harici bir iş zamanlayıcı gibi bir şeyle arka plan işleme yapmayı düşünmek isteyebilirsiniz. Bununla birlikte, mimarinizin de HTTP'ye gerçekten güvenmemesi gerekir. Genel olarak, iyi bir cevap olsa.
ezmek

34

Burada tek bir cevap aslında soruyu cevaplamaz. OP tek başına / uygulama başına DbContext tasarımı hakkında soru sormadı, per- (web) istek tasarımı ve hangi potansiyel faydaların olabileceğini sordu.

Mehdi harika bir kaynak olduğu için http://mehdi.me/ambient-dbcontext-in-ef6/ adresine başvuracağım :

Olası performans kazanımları.

Her DbContext örneği, veritabanından yüklenen tüm varlıkların birinci düzey önbelleğini tutar. Bir varlığı birincil anahtarıyla her sorguladığınızda, DbContext ilk olarak veritabanından sorgulamadan önce onu ilk düzey önbellekten almayı dener. Veri sorgu deseninize bağlı olarak, aynı DbContext'i birden çok ardışık iş işleminde yeniden kullanmak, DbContext birinci düzey önbellek sayesinde daha az veritabanı sorgusunun yapılmasına neden olabilir.

Tembel yüklemeyi mümkün kılar.

Hizmetleriniz kalıcı varlıklar döndürüyorsa (geri dönen görünüm modelleri veya diğer DTO'lar yerine) ve bu varlıklar üzerinde tembel yükleme işleminden yararlanmak istiyorsanız, bu varlıkların alındığı DbContext örneğinin kullanım ömrü ötesine geçmelidir ticari işlemin kapsamı. Hizmet yöntemi, dönmeden önce kullandığı DbContext örneğini atarsa, döndürülen varlıklar üzerinde tembel yükleme özellikleri girişimi başarısız olur (tembel yükleme kullanmanın iyi bir fikir olup olmadığı, içine girmeyeceğimiz tamamen farklı bir tartışmadır) buraya). Web uygulaması örneğimizde, tembel yükleme genellikle ayrı bir hizmet katmanı tarafından döndürülen varlıklar üzerindeki denetleyici eylem yöntemlerinde kullanılır. Bu durumda,

Eksileri de unutmayın. Bu bağlantı, konuyla ilgili okunacak diğer birçok kaynağı içerir.

Başka birinin bu soruya tökezlemesi ve soruyu gerçekten ele almayan cevaplarda emilmemesi durumunda bunu yayınlamanız yeterlidir.


İyi bağlantı! DBContext'i açıkça yönetmek en güvenli yaklaşıma benziyor.
aggsol

22

DbContext hiç iş parçacığı güvenli olmadığından eminim. Yani bir şeyi paylaşmak asla iyi bir fikir değildir.


Yani HTTP istekleri arasında paylaşmak asla iyi bir fikir değil mi?
Andrew

2
Evet Andrew demek istediği bu. Bağlamı paylaşmak yalnızca tek iş parçacıklı masaüstü uygulamaları içindir.
Elisabeth

10
Bir istek için bağlamı paylaşmaya ne dersiniz? Yani bir talep için farklı depolara erişebilir ve bir ve aynı bağlamı paylaşarak aralarında işlem yapabilir miyiz?
Lyubomir Velchev

16

Soruda veya tartışmada gerçekten ele alınmayan bir şey, DbContext'in değişiklikleri iptal edememesidir. Değişiklikler gönderebilirsiniz, ancak değişiklik ağacını temizleyemezsiniz, bu nedenle istek başına bağlam kullanırsanız, herhangi bir nedenle değişiklikleri atmanız gerekiyorsa şansınız kalmaz.

Şahsen ben gerektiğinde DbContext örnekleri oluşturmak - genellikle gerekirse içeriği yeniden oluşturma yeteneğine sahip iş bileşenleri bağlı. Bu şekilde, bana tek bir örnek zorlamak yerine süreç üzerinde kontrol sahibi olurum. Ayrıca, gerçekte kullanılıp kullanılmadığına bakılmaksızın her denetleyici başlangıcında DbContext oluşturmak zorunda değilim. Sonra yine de istek başına örnekleri olmasını istiyorsanız bunları CTOR'da (DI veya manuel olarak) oluşturabilir veya her denetleyici yönteminde gerektiği gibi oluşturabilirim. Şahsen genellikle DbContext örnekleri gerçekten gerekli olmadığında oluşturmaktan kaçınmak için ikinci yaklaşım alır.

Hangi açıdan baktığınıza da bağlıdır. Benim için istek başına örnek hiç mantıklı gelmedi. DbContext gerçekten Http isteğine ait mi? Davranış açısından yanlış yer burası. İşletme bileşenleriniz Http isteğini değil bağlamınızı oluşturuyor olmalıdır. Ardından, iş bileşenlerinizi gerektiği gibi oluşturabilir veya atabilir ve bağlamın ömrü hakkında asla endişelenmeyin.


1
Bu ilginç bir cevap ve sana kısmen katılıyorum. Bana göre, bir DbContext bir web isteğine bağlı olmak zorunda değil, ama her zaman olduğu gibi tek bir 'istek' yazılır: 'iş işlemi'. Bağlamı bir iş işlemine bağladığınızda, değişiklik iptali yapmak gerçekten garip hale gelir. Ancak web isteği sınırına sahip olmama, iş bileşenlerinin (BC) bağlamı oluşturması gerektiği anlamına gelmez; Bence bu onların sorumluluğu değil. Bunun yerine, BC'lerinizin çevresindeki dekoratörleri kullanarak kapsam belirleme uygulayabilirsiniz. Bu şekilde, herhangi bir kod değişikliği olmadan kapsam belirlemeyi bile değiştirebilirsiniz.
Steven

1
Bu durumda, iş nesnesine enjeksiyon, ömür boyu yönetimi ile ilgilenmelidir. Benim görüşüme göre iş nesnesi bağlama sahiptir ve bu nedenle yaşam süresini kontrol etmelidir.
Rick Strahl

Kısacası, "gerekirse içeriği yeniden oluşturma yeteneği" derken ne demek istersiniz? kendi geri alma yeteneğini mi yiyorsun? biraz detaylandırabilir misin?
tntwyckoff

2
Şahsen, orada bir DbContext zorlamak biraz zahmetli olduğunu düşünüyorum. Veritabanına bile vurmanız gerektiğine dair bir garanti yoktur. Belki de o taraftaki durumu değiştiren bir üçüncü taraf hizmeti çağırıyorsunuzdur. Ya da aslında aynı anda birlikte çalıştığınız 2 veya 3 veritabanınız var. Bunları kullanmanız durumunda, başlangıçta bir grup DbContexts oluşturmazsınız. İşletme, birlikte çalıştığı verileri bilir, dolayısıyla ona aittir. Gerekirse, başlangıçta bir TransactionScope koyun. Tüm aramaların bir taneye ihtiyacı olduğunu sanmıyorum. Kaynak alır.
Daniel Lorenz

Bu konteynerin dbcontext'in ömrünü kontrol etmesine izin verip vermediğiniz sorusu, daha sonra bazen ana denetimlerin ömrünü bazen gereksiz yere kontrol eder. Denetleyicilerime basit bir servis singletonu enjekte etmek istiyorsam, o zaman istek başına semantik nedeniyle constuctor enjeksiyonu kullanamayacağım.
davidcarr

10

Önceki görüşlere katılıyorum. DbContext'i tek bir iş parçacığı uygulamasında paylaşacaksanız, daha fazla belleğe ihtiyacınız olduğunu söylemek güzel. Örneğin, Azure'daki web uygulamam (bir ekstra küçük örnek) 150 MB'lık bir belleğe daha ihtiyaç duyuyor ve saatte yaklaşık 30 kullanıcım var. HTTP İsteğinde DBContext uygulama paylaşımı

İşte gerçek örnek resim: uygulama 12:00 'da konuşlandırıldı


Muhtemelen fikir, bir istek için bağlamı paylaşmaktır. Farklı depolara ve - DBSet sınıflarına erişirsek ve onlarla olan işlemlerin işlemsel olmasını istiyorsak, bu iyi bir çözüm olmalıdır. Açık kaynaklı projeye bir göz atın mvcforum.com Bunun, Unit Of Work tasarım modelinin uygulanmasında yapıldığını düşünüyorum.
Lyubomir Velchev

3

Ne gibi bu iş birimini (kullanıcı gördüğü gibi - yani bir sayfa gönderme) iş birimi ile ORM anlamda hizalar olmasıdır.

Bu nedenle, CRUD yöntemlerini her biri yeni bir içerik oluştururken göstermeniz durumunda yapamayacağınız tüm sayfa gönderimini işlemsel yapabilirsiniz.


3

Tek iş parçacıklı tek kullanıcılı bir uygulamada bile tek bir DbContext kullanmamanın bir başka önemli nedeni, kullandığı kimlik eşleme kalıbıdır. Bu, sorgu veya kimlik kullanarak her veri aldığınızda, alınan varlık örneklerini önbellekte tutacağı anlamına gelir. Aynı varlığı bir dahaki sefere aldığınızda, varsa, varlığın önbelleğe alınmış örneğini, varsa, aynı oturumda yaptığınız değişikliklerle size verecektir. SaveChanges yönteminin aynı veritabanı kayıtlarının birden çok farklı varlık örneği ile sonuçlanmaması için bu gereklidir; aksi takdirde bağlamın tüm bu varlık örneklerindeki verileri bir şekilde birleştirmesi gerekir.

Bir sorunun nedeni tek bir DbContext sonunda tüm veritabanı + bellekte .NET nesneleri yükü önbellek olabilir bir bomba olabilir.

Bu davranış, yalnızca .NoTracking()uzantısı yöntemiyle Linq sorguları kullanarak yolları vardır . Ayrıca bu gün bilgisayarlarda çok fazla RAM var. Ancak genellikle istenen davranış bu değildir.


Bu doğrudur, ancak Çöp Toplayıcı'nın çalışacağını varsaymalısınız ve bu sorunu gerçekten daha sanal hale getirin.
tocqueville

3
Çöp toplayıcı, etkin bir statik / tekli nesne tarafından tutulan herhangi bir nesne örneğini toplamayacaktır. Yığının gen 2'sine ulaşacaklar.
Dmitry

1

Entity Framework ile özellikle dikkat edilmesi gereken bir diğer konu, yeni varlıklar oluşturma, tembel yükleme ve daha sonra bu yeni varlıkları (aynı bağlamdan) kullanma kombinasyonudur. IDbSet.Create (yalnızca yeni gibi) kullanmıyorsanız, o varlığa tembel yükleme, oluşturulduğu bağlamdan alındığında çalışmaz. Örnek:

 public class Foo {
     public string Id {get; set; }
     public string BarId {get; set; }
     // lazy loaded relationship to bar
     public virtual Bar Bar { get; set;}
 }
 var foo = new Foo {
     Id = "foo id"
     BarId = "some existing bar id"
 };
 dbContext.Set<Foo>().Add(foo);
 dbContext.SaveChanges();

 // some other code, using the same context
 var foo = dbContext.Set<Foo>().Find("foo id");
 var barProp = foo.Bar.SomeBarProp; // fails with null reference even though we have BarId set.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.