AutoDetectChangesEnabled = true
MSDN der ki; Ayarladaki bir değişimi otomatik olarak algılar.
Patrick Desjardin'in blogunda der ki; DbSet'in Add, Attach, Find, Local, Remove metotlarını çağırırken aynı zamanda DbContext'in GetValidationErrors, Entry, SaveChanges metotlarında da çağırılır. DbSet metotlarının çağırlıdığı anda nesnenin veritabanına gitmeden önce değişim geçirip geçirmediği kontrolleri yapılan
public virtual void DetectChanges(bool force = false) { if (this.AutoDetectChangesEnabled || force) { this.ObjectContext.DetectChanges (); } }metoduna gidilir. Bu da yüklü VT işlemi yaparken gereksiz bir performans kaybına neden olacağı için AutoDetectChangesEnabled özelliği false yapılır. Patrick tecrübesine dayanarak 100den az nesne için yapılan işlemlerde performans kaybı çok değilken 100'ün üstündeki işlemlerde hissedilir olacağıdır.
Arthur'un dediğine göre ise:
When using most POCO("plain-old" CLR objects) entities the determination of how an entity has changed (and therefore which updates need to be sent to the database) is made by detecting the differences between the current property values of the entity and the original property values that are stored in a snapshot when the entity was queried or attached.POCO nesneleri VT ye gitmeden önce değişimlere bakılarak hangi nesnenin VT'ye gidip gitmeyeceğine karar verildiği bu DetectChanges metodunu şu kodla (bir dizi[bulk] işlem yaparken) verimli hale getirebilirsiniz:
using (var context = new UnicornsContext()) { try { context.Configuration.AutoDetectChangesEnabled = false; // Make many calls in a loop foreach (var unicorn in myUnicorns) { context.Unicorns.Add(unicorn); } } finally { context.Configuration.AutoDetectChangesEnabled = true; } }
Arthur'un makalesinden yine döndüm dolaştım MSDN0'e geldim. Çünkü alternatif bir yol önermiş:
An alternative to disabling and re-enabling is to leave automatic detection of changes turned off at all times and either call context.ChangeTracker.DetectChanges explicitly or use change tracking proxies diligently. Both of these options are advanced and can easily introduce subtle bugs into your application so use them with care.
Devam etmeden önce Lazy Loading nedir?
Lazy loading is the ability for an entity to perform a query for related entities whenever a navigation property is accessed.Yani siz nesneyi oluşturduğunuzda tüm bağlantılı diğer nesneleri bind olmasın ve sadece bağlantılı özelliğini çağırdığınızda değerleri bağlansın isterseniz "tembel yükleme" etkin olmalı. Elbette tüm context içinde bunu açıp kapatmanız mümkünken sadece sınıf bazlıda yapabilirsiniz. Aşağıda detaylarından bahsedeceğim.
MSDN derki: Eğer Lazy Loading ve POCO'larının değişimlerini takip etmek isterseniz, EF POCO'larınız için çalışma zamanında PROXY oluşturacaktır. Eğer Lazy Loading proxy istersen değişim takibine sahip olmadan yapabilirsin. Ama değişim takibi istersen Lazy Loading ister istemez proxylerinde gelecektir.
Proxy yaratılması için:
- Data sınıfı public erişimde olmalı.
- Data sınıfı sealed veya abstract tanımlanmamalı
- Data sınıfı parametresiz public veya protected yapıcı metoda sahip olmalı. Parametresiz protected yapıcı metodu CreateObject metodu kullanarak POCO'larınız için proxy oluşturmak istediğinizde kullanılabilir. CreateObject metodu proxy oluşturmayı garantilemez.
- Sınıfınız IEntityWithChangeTracker veya IEntityWithRelationships arayüzlerini uygulamaz çünkü PROXY sınıfları bu arayüzleri uygulayacaklardır.
- The ProxyCreationEnabled option must be set to true.(E yani.. Şöyleki: context.ContextOptions.ProxyCreationEnabled = true; )
public class Kisi { public virtual ICollectionve bunun peşine dinamik olarak proxy sınıfınız aşağıdaki gibi üretilir:Adresler { get; set; } }
public class EFKisiProxy : Kisi { public override ICollectionAdresler { get { DoLazyLoad(); return base.Adresler; } set { base.Adresler= value; } } }
Lazy Loading için:
Her bağlantı özelliği ("Her kurumun bir adresi vardır" demek Kurum sınıfı Adres tipinde bir özelliğe sahiptir demektir. Kurum içinde Adres sınıfına bir bağlantı verilecektir) public ve virtual tanımlanmalı ve get metodu mühürlenmiş olmamalı.
Değişim Takibi için:
- Bağlantı olarak kullanılan her özellik Data Model içinde mühürlenmiş olmamalı, public ve virtual olmalı.
- Eğer birden çok adresi olacaksa bir kurum nesnesinin o halde ICollection<Adres> olarak bu ilişki gösterilmeli.
- Eğer nesnen ile birlikte proxy tipini yaratmak istersen ObjectContext içindeki CreateObject metodunu her yeni nesne oluştururken "new" operatörü yerine kullanmalısın.
1:32(am) ve bu arada şunu dinliyorum ;)
Ne diyordu MSDN? Hah, eğer senin CreateObject metot çağrın proxy oluşturamazsa doğrudan POCO'ndan bir nesne yaratır ve sana verir. Bunu anlamak için üretilen nesnenin tipine bakarsın. Tipler aynı değilse bu proxy nesnesidir ve en azından Lazy Loading özelliği vardır. Detaylar How to: Identify that a POCO Entity is a Proxy adresinde.
Yatma saatini geçirdim ama konu konu açtı ve gördümki bu da güzel bir bağlantı olacak CreateObject ya da Create metodu kullanılarak yaratılmış nesnelerin hem alt ilişkileri(public virtual ... ile tanımlı özellikleri için) hemde bu nesnelerin VT ye işlenmeleri ile ilgili. Kaynak stackoverflow ve soru: Create<object> vs new <object> in Entity Framework. Cevaplar güzel ve derlerki: Eğer CreateObject ya da Create metotları ile bir nesne yaratırsan bu nesneler ObjectContext içinde olmayacaklardır. Bunları ObjectContext içine almak istersen Attach etmelisin.
using (var ctx = new MyDbContext()) { var user = ctx.Users.Create(); user.Id = 1; ctx.Users.Attach(user); var roles = user.Roles; }Create ile yarattığın ve Attach ile contexte iliştirdiğin için
user.Roles
gelecektir. Ama sen new operatörü ile yapsaydınusing (var ctx = new MyDbContext()) { var user = new User { Id = 1 }; ctx.Users.Attach(user); var roles = user.Roles; }Roles özelliğine asla erişemeyecektin. Tam bu noktada Attaching and Detaching Objects başlıklı MSDN makalesine baktım ve özetle şunları gördüm: Sen bu hariçten nesne yaratma ihtiyacını çeşitli hallerde isteyebilirsin. Mesela normal bir sorgu ile elde edeceğin nesneler object context içindedirler ve yönetilmeleri ve izlenmeleri object context tarafından yapılırken harici bir sorguyla elde ettiğin nesneler context harici oldukları için yönetimleri senin elinde olacaklar. Ya da senin ASP.NET viewstate içinde sakladığın, remote metot veya web servisi çağrısıyla elde ettiğin nesnelerin olabilir. Tüm bunları
- System.Data.Objects.ObjectSet.AddObject(...) veya System.Data.Objects.ObjectContext.AddObject(...)
- System.Data.Objects.ObjectSet.Attach(...) veya System.Data.Objects.ObjectContext.Attach(System.Data.Objects.DataClasses.IEntityWithKey)ve AttachTo
İkinci resmimde altı kırmızıyla çizili satırları biraz izah etmiş biraz çevrisiyle kendime notumu almış oldum.
Devamı MSDN'de...