İzlenen Varlıklara Erişme
bir tarafından DbContextizlenen varlıklara erişmek için dört ana API vardır:
- DbContext.Entry belirli bir EntityEntry<TEntity> varlık örneği için bir örnek döndürür.
- ChangeTracker.Entries tüm izlenen varlıklar için veya belirli bir türe ait tüm izlenen varlıklar için örnekleri döndürür EntityEntry<TEntity> .
- DbContext.Find, DbContext.FindAsync, DbSet<TEntity>.Findve DbSet<TEntity>.FindAsync birincil anahtara göre tek bir varlık bulun; önce izlenen varlıklara bakın ve gerekirse veritabanını sorgulayın.
- DbSet<TEntity>.Local DbSet tarafından temsil edilen varlık türünün varlıkları için gerçek varlıkları (EntityEntry örnekleri değil) döndürür.
Bunların her biri aşağıdaki bölümlerde daha ayrıntılı olarak açıklanmıştır.
Bahşiş
Bu belgede varlık durumlarının ve EF Core değişiklik izlemenin temellerinin anlaşıldığı varsayılır. Bu konular hakkında daha fazla bilgi için EF Core'daki Değişiklik İzleme bakın.
Bahşiş
GitHub’dan örnek kodu indirerek bu belgedeki tüm kodları çalıştırabilir ve hataları ayıklayabilirsiniz.
DbContext.Entry ve EntityEntry örneklerini kullanma
Her izlenen varlık için Entity Framework Core (EF Core) şunları izler:
- Varlığın genel durumu. Bu , ,
Modified
veyaAdded
Deleted
biridirUnchanged
; daha fazla bilgi için EF Core'da Değişiklik İzleme bakın. - İzlenen varlıklar arasındaki ilişkiler. Örneğin, gönderinin ait olduğu blog.
- Özelliklerin "geçerli değerleri".
- Bu bilgiler kullanılabilir olduğunda özelliklerin "özgün değerleri". Özgün değerler, varlık veritabanından sorgulandığında var olan özellik değerleridir.
- Sorgulandıktan sonra hangi özellik değerlerinin değiştirildiği.
- Değerin geçici olup olmadığı gibi özellik değerleriyle ilgili diğer bilgiler.
Bir varlık örneğinin geçirilmesi DbContext.Entry , verilen varlık için bu bilgilere erişim sağlanmasına neden EntityEntry<TEntity> olur. Örnek:
using var context = new BlogsContext();
var blog = context.Blogs.Single(e => e.Id == 1);
var entityEntry = context.Entry(blog);
Aşağıdaki bölümlerde varlık durumuna erişmek ve bu durumu işlemek için EntityEntry'nin nasıl kullanılacağı ve varlığın özelliklerinin ve gezintilerinin durumu gösterilmektedir.
Varlıkla çalışma
öğesinin en yaygın kullanımı EntityEntry<TEntity> , bir varlığın geçerlisine EntityState erişmektir. Örnek:
var currentState = context.Entry(blog).State;
if (currentState == EntityState.Unchanged)
{
context.Entry(blog).State = EntityState.Modified;
}
Entry yöntemi, henüz izlenmemiş varlıklarda da kullanılabilir. Bu , varlığı izlemeye başlamaz; varlığın durumu hala Detached
şeklindedir. Ancak, döndürülen EntityEntry daha sonra varlık durumunu değiştirmek için kullanılabilir ve bu noktada varlık belirtilen durumda izlenir. Örneğin, aşağıdaki kod bir Blog örneğini şu şekilde Added
izlemeye başlar:
var newBlog = new Blog();
Debug.Assert(context.Entry(newBlog).State == EntityState.Detached);
context.Entry(newBlog).State = EntityState.Added;
Debug.Assert(context.Entry(newBlog).State == EntityState.Added);
Bahşiş
EF6'nın aksine, tek bir varlığın durumunu ayarlamak tüm bağlı varlıkların izlenmesine neden olmaz. Bu, durumun bu şekilde ayarlanmasını, varlık grafiğinin tamamında çalışan , Attach
veya Update
çağrısından Add
daha düşük düzeyli bir işlem yapar.
Aşağıdaki tabloda, varlığın tamamıyla çalışmak için EntityEntry kullanmanın yolları özetlenir:
EntityEntry üyesi | Tanım |
---|---|
EntityEntry.State | Varlığın öğesini EntityState alır ve ayarlar. |
EntityEntry.Entity | Varlık örneğini alır. |
EntityEntry.Context | DbContext Bu varlığı izleyen. |
EntityEntry.Metadata | IEntityType varlık türü için meta veriler. |
EntityEntry.IsKeySet | Varlığın anahtar değerinin ayarlanıp ayarlanmadığı. |
EntityEntry.Reload() | Veritabanından okunan değerlerle özellik değerlerinin üzerine yazar. |
EntityEntry.DetectChanges() | Yalnızca bu varlık için değişikliklerin algılanması zorlar; Bkz. Değişiklik Algılama ve Bildirimler. |
Tek bir özellik ile çalışma
çeşitli aşırı yüklemeleri, bir varlığın EntityEntry<TEntity>.Property tek bir özelliği hakkındaki bilgilere erişime izin verir. Örneğin, kesin türe sahip, akıcı bir API kullanarak:
PropertyEntry<Blog, string> propertyEntry = context.Entry(blog).Property(e => e.Name);
Bunun yerine özellik adı dize olarak geçirilebilir. Örnek:
PropertyEntry<Blog, string> propertyEntry = context.Entry(blog).Property<string>("Name");
Döndürülen PropertyEntry<TEntity,TProperty> daha sonra özelliği hakkındaki bilgilere erişmek için kullanılabilir. Örneğin, bu varlık üzerindeki özelliğin geçerli değerini almak ve ayarlamak için kullanılabilir:
string currentValue = context.Entry(blog).Property(e => e.Name).CurrentValue;
context.Entry(blog).Property(e => e.Name).CurrentValue = "1unicorn2";
Yukarıda kullanılan Özellik yöntemlerinin her ikisi de kesin olarak türü belirlenmiş bir genel PropertyEntry<TEntity,TProperty> örnek döndürür. Bu genel türün kullanılması tercih edilir çünkü kutulama değer türleri olmadan özellik değerlerine erişime izin verir. Ancak, derleme zamanında varlık veya özellik türü bilinmiyorsa, bunun yerine genel PropertyEntry olmayan bir elde edilebilir:
PropertyEntry propertyEntry = context.Entry(blog).Property("Name");
Bu, kutulama değeri türleri karşılığında türü ne olursa olsun herhangi bir özelliğin özellik bilgilerine erişim sağlar. Örnek:
object blog = context.Blogs.Single(e => e.Id == 1);
object currentValue = context.Entry(blog).Property("Name").CurrentValue;
context.Entry(blog).Property("Name").CurrentValue = "1unicorn2";
Aşağıdaki tabloda PropertyEntry tarafından kullanıma sunulan özellik bilgileri özetlemektedir:
PropertyEntry üyesi | Tanım |
---|---|
PropertyEntry<TEntity,TProperty>.CurrentValue | Özelliğin geçerli değerini alır ve ayarlar. |
PropertyEntry<TEntity,TProperty>.OriginalValue | Özelliğin varsa özgün değerini alır ve ayarlar. |
PropertyEntry<TEntity,TProperty>.EntityEntry | Varlık için öğesine EntityEntry<TEntity> geri başvuru. |
PropertyEntry.Metadata | IProperty özelliği için meta veriler. |
PropertyEntry.IsModified | Bu özelliğin değiştirilmiş olarak işaretlenip işaretlenmediğini gösterir ve bu durumun değiştirilmesine izin verir. |
PropertyEntry.IsTemporary | Bu özelliğin geçici olarak işaretlenip işaretlenmediğini gösterir ve bu durumun değiştirilmesine izin verir. |
Notlar:
- Bir özelliğin özgün değeri, varlık veritabanından sorgulandığında özelliğin sahip olduğu değerdir. Ancak, varlığın bağlantısı kesildiyse ve daha sonra veya gibi
Attach
Update
başka bir DbContext'e açıkça eklenmişse özgün değerler kullanılamaz. Bu durumda, döndürülen özgün değer geçerli değerle aynı olacaktır. - SaveChanges yalnızca değiştirilmiş olarak işaretlenen özellikleri güncelleştirir. EF Core'un belirli bir özellik değerini güncelleştirmesini zorlamak için true olarak ayarlayın IsModified veya EF Core'un özellik değerini güncelleştirmesini önlemek için false olarak ayarlayın.
- Geçici değerler genellikle EF Core değer oluşturucuları tarafından oluşturulur. Bir özelliğin geçerli değerini ayarlamak geçici değeri verilen değerle değiştirir ve özelliği geçici değil olarak işaretler. Bir değeri açıkça ayarlandıktan sonra bile geçici olmaya zorlamak için true olarak ayarlayın IsTemporary .
Tek bir gezintiyle çalışma
çeşitli , ve EntityEntry<TEntity>.CollectionEntityEntry.Navigation aşırı yüklemeleri EntityEntry<TEntity>.Referencetek bir gezinti hakkındaki bilgilere erişime izin verir.
Tek bir ilgili varlığa başvuru gezintilerine yöntemler aracılığıyla Reference erişilir. Başvuru gezintileri, bire çok ilişkilerin "bir" kenarlarını ve bire bir ilişkilerin her iki tarafını işaret eder. Örnek:
ReferenceEntry<Post, Blog> referenceEntry1 = context.Entry(post).Reference(e => e.Blog);
ReferenceEntry<Post, Blog> referenceEntry2 = context.Entry(post).Reference<Blog>("Blog");
ReferenceEntry referenceEntry3 = context.Entry(post).Reference("Blog");
Gezintiler, bire çok ve çoka çok ilişkilerinin "çok" tarafları için kullanıldığında ilgili varlıkların koleksiyonları da olabilir. Collection Yöntemler, koleksiyon gezintilerine erişmek için kullanılır. Örnek:
CollectionEntry<Blog, Post> collectionEntry1 = context.Entry(blog).Collection(e => e.Posts);
CollectionEntry<Blog, Post> collectionEntry2 = context.Entry(blog).Collection<Post>("Posts");
CollectionEntry collectionEntry3 = context.Entry(blog).Collection("Posts");
Bazı işlemler tüm gezintilerde yaygındır. Bunlar, yöntemi kullanılarak EntityEntry.Navigation hem başvuru hem de koleksiyon gezintileri için erişilebilir. Tüm gezintilere birlikte erişirken yalnızca genel olmayan erişimin kullanılabildiğini unutmayın. Örnek:
NavigationEntry navigationEntry = context.Entry(blog).Navigation("Posts");
Aşağıdaki tabloda , CollectionEntry<TEntity,TRelatedEntity>ve NavigationEntrykullanma ReferenceEntry<TEntity,TProperty>yolları özetlemektedir:
NavigationEntry üyesi | Tanım |
---|---|
MemberEntry.CurrentValue | Gezintinin geçerli değerini alır ve ayarlar. Bu, koleksiyon gezintileri için koleksiyonun tamamıdır. |
NavigationEntry.Metadata | INavigationBase gezinti meta verileri. |
NavigationEntry.IsLoaded | İlgili varlığın veya koleksiyonun veritabanından tamamen yüklenip yüklenmediğini belirten bir değer alır veya ayarlar. |
NavigationEntry.Load() | veritabanından ilgili varlığı veya koleksiyonu yükler; bkz . İlgili Verilerin Açıkça Yüklenmesi. |
NavigationEntry.Query() | EF Core sorgusu, bu gezintiyi daha fazla oluşturulabilecek bir IQueryable gezinti olarak yüklemek için kullanır; bkz . İlgili Verilerin Açıkça Yüklenmesi. |
Varlığın tüm özellikleriyle çalışma
EntityEntry.Propertiesvarlığın PropertyEntry her özelliği için bir IEnumerable<T> döndürür. Bu, varlığın her özelliği için bir eylem gerçekleştirmek için kullanılabilir. Örneğin, herhangi bir DateTime özelliğini olarak ayarlamak için DateTime.Now
:
foreach (var propertyEntry in context.Entry(blog).Properties)
{
if (propertyEntry.Metadata.ClrType == typeof(DateTime))
{
propertyEntry.CurrentValue = DateTime.Now;
}
}
Ayrıca, EntityEntry tüm özellik değerlerini aynı anda almak ve ayarlamak için çeşitli yöntemler içerir. Bu yöntemler, bir özellik koleksiyonunu ve değerlerini temsil eden sınıfını kullanır PropertyValues . PropertyValues, geçerli veya özgün değerler için veya veritabanında şu anda depolandığı gibi değerler için alınabilir. Örnek:
var currentValues = context.Entry(blog).CurrentValues;
var originalValues = context.Entry(blog).OriginalValues;
var databaseValues = context.Entry(blog).GetDatabaseValues();
Bu PropertyValues nesneleri kendi başlarına çok kullanışlı değildir. Ancak, varlıkları düzenlerken gereken yaygın işlemleri gerçekleştirmek için birleştirilebilirler. Bu, veri aktarımı nesneleriyle çalışırken ve iyimser eşzamanlılık çakışmalarını çözerken kullanışlıdır. Aşağıdaki bölümlerde bazı örnekler gösterilmektedir.
Bir varlıktan veya DTO'dan geçerli veya özgün değerleri ayarlama
Bir varlığın geçerli veya özgün değerleri, başka bir nesneden değerler kopyalanarak güncelleştirilebilir. Örneğin, varlık türüyle aynı özelliklere sahip bir BlogDto
veri aktarım nesnesi (DTO) düşünün:
public class BlogDto
{
public int Id { get; set; }
public string Name { get; set; }
}
Bu, kullanılarak PropertyValues.SetValuesizlenen bir varlığın geçerli değerlerini ayarlamak için kullanılabilir:
var blogDto = new BlogDto { Id = 1, Name = "1unicorn2" };
context.Entry(blog).CurrentValues.SetValues(blogDto);
Bu teknik bazen bir varlığı bir hizmet çağrısından veya n katmanlı bir uygulamadaki bir istemciden alınan değerlerle güncelleştirirken kullanılır. Kullanılan nesnenin, adları varlığın özellikleriyle eşleşen özelliklere sahip olduğu sürece varlıkla aynı türde olması gerekmediğini unutmayın. Yukarıdaki örnekte, izlenen Blog
bir varlığın geçerli değerlerini ayarlamak için DTO BlogDto
örneği kullanılmıştır.
Özelliklerin yalnızca değer kümesi geçerli değerden farklıysa değiştirilmiş olarak işaretleneceğini unutmayın.
Sözlükten geçerli veya özgün değerleri ayarlama
Önceki örnek, bir varlık veya DTO örneğinden değerleri ayarlar. Özellik değerleri bir sözlükte ad/değer çiftleri olarak depolandığında da aynı davranış kullanılabilir. Örnek:
var blogDictionary = new Dictionary<string, object> { ["Id"] = 1, ["Name"] = "1unicorn2" };
context.Entry(blog).CurrentValues.SetValues(blogDictionary);
Veritabanından geçerli veya özgün değerleri ayarlama
Bir varlığın geçerli veya özgün değerleri, geçerli veya özgün değerleri veya her ikisini birden ayarlamak için çağrılarak GetDatabaseValues() veya GetDatabaseValuesAsync döndürülen nesne kullanılarak veritabanından en son değerlerle güncelleştirilebilir. Örnek:
var databaseValues = context.Entry(blog).GetDatabaseValues();
context.Entry(blog).CurrentValues.SetValues(databaseValues);
context.Entry(blog).OriginalValues.SetValues(databaseValues);
Geçerli, özgün veya veritabanı değerlerini içeren kopyalanmış nesne oluşturma
Kullanarak varlığın PropertyValues.ToObject()bir kopyasını oluşturmak için CurrentValues, OriginalValues veya GetDatabaseValues'tan döndürülen PropertyValues nesnesi kullanılabilir. Örnek:
var clonedBlog = context.Entry(blog).GetDatabaseValues().ToObject();
ToObject
DbContext tarafından izlenmemiş yeni bir örnek döndürdüğünü unutmayın. Döndürülen nesnenin diğer varlıklarla ayarlanmış hiçbir ilişkisi de yoktur.
Kopyalanan nesne, özellikle belirli bir türdeki nesnelere veri bağlama sırasında veritabanındaki eşzamanlı güncelleştirmeler ile ilgili sorunları çözmek için yararlı olabilir. Daha fazla bilgi için bkz . iyimser eşzamanlılık .
Varlığın tüm gezintileriyle çalışma
EntityEntry.Navigationsvarlığın her gezintisi NavigationEntry için bir IEnumerable<T> döndürür. EntityEntry.References ve EntityEntry.Collections aynı şeyi yapar, ancak sırasıyla başvuru veya koleksiyon gezintileriyle sınırlıdır. Bu, varlığın her gezintisinde bir eylem gerçekleştirmek için kullanılabilir. Örneğin, tüm ilgili varlıkların yüklenmesini zorlamak için:
foreach (var navigationEntry in context.Entry(blog).Navigations)
{
navigationEntry.Load();
}
Varlığın tüm üyeleriyle çalışma
Normal özellikler ve gezinti özellikleri farklı durum ve davranışa sahiptir. Bu nedenle, yukarıdaki bölümlerde gösterildiği gibi gezintileri ve olmayan gezintileri ayrı ayrı işlemek yaygın bir durumdur. Ancak, bazen varlığın herhangi bir üyesiyle, normal bir özellik veya gezintiden bağımsız olarak bir şey yapmak yararlı olabilir. EntityEntry.Member ve EntityEntry.Members bu amaçla sağlanır. Örnek:
foreach (var memberEntry in context.Entry(blog).Members)
{
Console.WriteLine(
$"Member {memberEntry.Metadata.Name} is of type {memberEntry.Metadata.ClrType.ShortDisplayName()} and has value {memberEntry.CurrentValue}");
}
Bu kodun örnekten bir blogda çalıştırılması aşağıdaki çıkışı oluşturur:
Member Id is of type int and has value 1
Member Name is of type string and has value .NET Blog
Member Posts is of type IList<Post> and has value System.Collections.Generic.List`1[Post]
Bahşiş
Değişiklik izleyicisi hata ayıklama görünümü aşağıdaki gibi bilgileri gösterir. Değişiklik izleyicisinin tamamı için hata ayıklama görünümü, izlenen her varlığın bireysel EntityEntry.DebugView öğesinden oluşturulur.
Bul ve BulAsync
DbContext.Find, DbContext.FindAsync, DbSet<TEntity>.Findve DbSet<TEntity>.FindAsync birincil anahtarı bilindiğinde tek bir varlığın verimli bir şekilde aranma amacıyla tasarlanmıştır. Önce varlığın zaten izlenip izlenmediğini denetler ve izlenirse varlığı hemen döndürür. Veritabanı sorgusu yalnızca varlık yerel olarak izlenmiyorsa yapılır. Örneğin, aynı varlık için Bul'u iki kez çağıran bu kodu göz önünde bulundurun:
using var context = new BlogsContext();
Console.WriteLine("First call to Find...");
var blog1 = context.Blogs.Find(1);
Console.WriteLine($"...found blog {blog1.Name}");
Console.WriteLine();
Console.WriteLine("Second call to Find...");
var blog2 = context.Blogs.Find(1);
Debug.Assert(blog1 == blog2);
Console.WriteLine("...returned the same instance without executing a query.");
SQLite kullanılırken bu kodun çıkışı (EF Core günlüğü dahil) şöyledir:
First call to Find...
info: 12/29/2020 07:45:53.682 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (1ms) [Parameters=[@__p_0='1' (DbType = String)], CommandType='Text', CommandTimeout='30']
SELECT "b"."Id", "b"."Name"
FROM "Blogs" AS "b"
WHERE "b"."Id" = @__p_0
LIMIT 1
...found blog .NET Blog
Second call to Find...
...returned the same instance without executing a query.
İlk çağrının varlığı yerel olarak bulmadığını ve bu nedenle bir veritabanı sorgusu yürüttüğüne dikkat edin. Buna karşılık, ikinci çağrı zaten izlendiğinden veritabanını sorgulamadan aynı örneği döndürür.
Verilen anahtara sahip bir varlık yerel olarak izlenmiyorsa ve veritabanında yoksa Find null döndürür.
Bileşik anahtarlar
Bul, bileşik anahtarlarla da kullanılabilir. Örneğin, sipariş kimliği ve ürün kimliğinden oluşan bileşik anahtara sahip bir varlığı göz önünde bulundurun OrderLine
:
public class OrderLine
{
public int OrderId { get; set; }
public int ProductId { get; set; }
//...
}
Bileşik anahtar, anahtar parçalarını ve bunların sırasını tanımlamak için içinde DbContext.OnModelCreating yapılandırılmalıdır. Örnek:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<OrderLine>()
.HasKey(e => new { e.OrderId, e.ProductId });
}
Anahtarın OrderId
ilk bölümü ve ProductId
anahtarın ikinci bölümü olduğuna dikkat edin. Bu sıra, anahtar değerleri Bul'a geçirildiğinde kullanılmalıdır. Örnek:
var orderline = context.OrderLines.Find(orderId, productId);
İzlenen tüm varlıklara erişmek için ChangeTracker.Entrys kullanma
Şu ana kadar tek seferde yalnızca bir taneye EntityEntry erişebildik. ChangeTracker.Entries() DbContext tarafından izlenen her varlık için bir EntityEntry döndürür. Örnek:
using var context = new BlogsContext();
var blogs = context.Blogs.Include(e => e.Posts).ToList();
foreach (var entityEntry in context.ChangeTracker.Entries())
{
Console.WriteLine($"Found {entityEntry.Metadata.Name} entity with ID {entityEntry.Property("Id").CurrentValue}");
}
Bu kod aşağıdaki çıkışı oluşturur:
Found Blog entity with ID 1
Found Post entity with ID 1
Found Post entity with ID 2
Hem bloglar hem de gönderiler için girdilerin döndürüldüğünü fark edin. Bunun yerine sonuçlar, genel aşırı yükleme kullanılarak belirli bir varlık türüne ChangeTracker.Entries<TEntity>() filtrelenebilir:
foreach (var entityEntry in context.ChangeTracker.Entries<Post>())
{
Console.WriteLine(
$"Found {entityEntry.Metadata.Name} entity with ID {entityEntry.Property(e => e.Id).CurrentValue}");
}
Bu kodun çıktısı yalnızca gönderilerin döndürüldüğünü gösterir:
Found Post entity with ID 1
Found Post entity with ID 2
Ayrıca, genel aşırı yüklemenin kullanılması genel EntityEntry<TEntity> örnekleri döndürür. Bu örnekte özelliğine akıcı bir şekilde erişmesini Id
sağlayan budur.
Filtreleme için kullanılan genel türün eşlenmiş bir varlık türü olması gerekmez; bunun yerine eşlenmemiş bir temel tür veya arabirim kullanılabilir. Örneğin, modeldeki tüm varlık türleri anahtar özelliklerini tanımlayan bir arabirim uyguluyorsa:
public interface IEntityWithKey
{
int Id { get; set; }
}
Daha sonra bu arabirim, izlenen herhangi bir varlığın anahtarıyla kesin olarak türlenmiş bir şekilde çalışmak için kullanılabilir. Örnek:
foreach (var entityEntry in context.ChangeTracker.Entries<IEntityWithKey>())
{
Console.WriteLine(
$"Found {entityEntry.Metadata.Name} entity with ID {entityEntry.Property(e => e.Id).CurrentValue}");
}
İzlenen varlıkları sorgulamak için DbSet.Local kullanma
EF Core sorguları her zaman veritabanında yürütülür ve yalnızca veritabanına kaydedilmiş varlıkları döndürür. DbSet<TEntity>.Local yerel, izlenen varlıklar için DbContext'i sorgulamak için bir mekanizma sağlar.
DbSet.Local
İzlenen varlıkları sorgulamak için kullanıldığından, varlıkları DbContext'e yüklemek ve ardından bu yüklü varlıklarla çalışmak normaldir. Bu özellikle veri bağlama için geçerlidir, ancak diğer durumlarda da yararlı olabilir. Örneğin, aşağıdaki kodda veritabanı ilk olarak tüm bloglar ve gönderiler için sorgulanır. Load Uzantı yöntemi, doğrudan uygulamaya döndürülmeden bağlam tarafından izlenen sonuçlarla bu sorguyu yürütmek için kullanılır. (Veya benzerini kullanmak ToList
aynı etkiye sahiptir, ancak burada gerekli olmayan döndürülen listeyi oluşturma yüküyle birlikte.) Örnek daha sonra yerel olarak izlenen varlıklara erişmek için kullanır DbSet.Local
:
using var context = new BlogsContext();
context.Blogs.Include(e => e.Posts).Load();
foreach (var blog in context.Blogs.Local)
{
Console.WriteLine($"Blog: {blog.Name}");
}
foreach (var post in context.Posts.Local)
{
Console.WriteLine($"Post: {post.Title}");
}
aksineChangeTracker.Entries()DbSet.Local
, varlık örneklerini doğrudan döndürdüğüne dikkat edin. Bir EntityEntry elbette, döndürülen varlık için her zaman çağrılarak DbContext.Entryelde edilebilir.
Yerel görünüm
DbSet<TEntity>.Local , bu varlıkların geçerli EntityState durumunu yansıtan yerel olarak izlenen varlıkların görünümünü döndürür. Bu, özellikle şu anlama gelir:
Added
varlıklar dahil edilir. Varlıklar henüz veritabanında olmadığından ve bu nedenle veritabanı sorgusu tarafından hiçbir zaman döndürülmediğinden,Added
normal EF Core sorguları için bu durumun geçerli olmadığını unutmayın.Deleted
varlıklar dışlanır. Varlıklar veritabanında hala var olduğundanDeleted
ve veritabanı sorguları tarafından döndürüldiğinden, normal EF Core sorguları için bu durumun yine böyle olmadığını unutmayın.
Tüm bunlar, DbSet.Local
varlık grafiğinin Added
geçerli kavramsal durumunu yansıtan veriler üzerinde görünüm anlamına gelir ve varlıklar dahil edilir ve Deleted
varlıklar hariç tutulur. Bu, SaveChanges çağrıldıktan sonra beklenen veritabanı durumuyla eşleşir.
Bu genellikle veri bağlama için ideal bir görünümdür, çünkü uygulama tarafından yapılan değişikliklere göre verileri kullanıcıya anladığı şekilde sunar.
Aşağıdaki kod, bir gönderiyi olarak Deleted
işaretleyip yeni bir gönderi Added
ekleyerek bunu gösterir:
using var context = new BlogsContext();
var posts = context.Posts.Include(e => e.Blog).ToList();
Console.WriteLine("Local view after loading posts:");
foreach (var post in context.Posts.Local)
{
Console.WriteLine($" Post: {post.Title}");
}
context.Remove(posts[1]);
context.Add(
new Post
{
Title = "What’s next for System.Text.Json?",
Content = ".NET 5.0 was released recently and has come with many...",
Blog = posts[0].Blog
});
Console.WriteLine("Local view after adding and deleting posts:");
foreach (var post in context.Posts.Local)
{
Console.WriteLine($" Post: {post.Title}");
}
Bu kodun çıktısı şu şekildedir:
Local view after loading posts:
Post: Announcing the Release of EF Core 5.0
Post: Announcing F# 5
Post: Announcing .NET 5.0
Local view after adding and deleting posts:
Post: What’s next for System.Text.Json?
Post: Announcing the Release of EF Core 5.0
Post: Announcing .NET 5.0
Silinen gönderinin yerel görünümden kaldırıldığına ve eklenen gönderinin eklendiğine dikkat edin.
Varlık eklemek ve kaldırmak için Yerel'i kullanma
DbSet<TEntity>.Local öğesinin bir örneğini LocalView<TEntity>döndürür. Bu, varlıklar eklendiğinde ve koleksiyondan kaldırıldığında bildirimler oluşturan ve bunlara yanıt veren bir uygulamasıdır ICollection<T> . (Bu, ile aynı kavramdır ObservableCollection<T>, ancak bağımsız bir koleksiyon olarak değil, mevcut EF Core değişiklik izleme girdileri üzerinde bir projeksiyon olarak uygulanır.)
Yerel görünümün bildirimleri DbContext değişiklik izlemesine bağlanarak yerel görünümün DbContext ile eşitlenmiş durumda kalmasını sağlar. Özellikle:
- Yeni bir varlık eklemek
DbSet.Local
, genellikle durumunda dbContext tarafından izlenmesineAdded
neden olur. (Varlık zaten oluşturulmuş bir anahtar değerine sahipse, bunun yerine izlenirUnchanged
.) - Bir varlığın 'den
DbSet.Local
kaldırılması, varlığın olarakDeleted
işaretlenmesine neden olur. - DbContext tarafından izlenen bir varlık koleksiyonda
DbSet.Local
otomatik olarak görünür. Örneğin, daha fazla varlığın otomatik olarak getirilmesi için bir sorgunun yürütülmesi yerel görünümün güncelleştirilmiş olmasına neden olur. - olarak
Deleted
işaretlenmiş bir varlık, yerel koleksiyondan otomatik olarak kaldırılır.
Bu, yerel görünümün izlenen varlıkları yalnızca koleksiyona ekleyip kaldırarak işlemek için kullanılabileceğini gösterir. Örneğin, yerel koleksiyona gönderi eklemek ve kaldırmak için önceki örnek kodu değiştirelim:
using var context = new BlogsContext();
var posts = context.Posts.Include(e => e.Blog).ToList();
Console.WriteLine("Local view after loading posts:");
foreach (var post in context.Posts.Local)
{
Console.WriteLine($" Post: {post.Title}");
}
context.Posts.Local.Remove(posts[1]);
context.Posts.Local.Add(
new Post
{
Title = "What’s next for System.Text.Json?",
Content = ".NET 5.0 was released recently and has come with many...",
Blog = posts[0].Blog
});
Console.WriteLine("Local view after adding and deleting posts:");
foreach (var post in context.Posts.Local)
{
Console.WriteLine($" Post: {post.Title}");
}
Yerel görünümde yapılan değişiklikler DbContext ile eşitlendiği için çıkış önceki örnekten farklı kalır.
Windows Forms veya WPF veri bağlaması için yerel görünümü kullanma
DbSet<TEntity>.Local EF Core varlıklarına veri bağlamanın temelini oluşturur. Ancak, hem Windows Forms hem de WPF, beklediğiniz bildirim koleksiyonunun belirli türüyle kullanıldığında en iyi şekilde çalışır. Yerel görünüm şu koleksiyon türlerinin oluşturulmasını destekler:
- LocalView<TEntity>.ToObservableCollection() WPF veri bağlaması için bir ObservableCollection<T> döndürür.
- LocalView<TEntity>.ToBindingList() , Windows Forms veri bağlaması için bir BindingList<T> döndürür.
Örnek:
ObservableCollection<Post> observableCollection = context.Posts.Local.ToObservableCollection();
BindingList<Post> bindingList = context.Posts.Local.ToBindingList();
EF Core ile WPF veri bağlama hakkında daha fazla bilgi için bkz . WPF ile Çalışmaya Başlama ve EF Core ile Windows Forms veri bağlama hakkında daha fazla bilgi için Windows Forms ile Çalışmaya Başlama.
Bahşiş
Belirli bir DbSet örneğinin yerel görünümü ilk erişildiğinde ve sonra önbelleğe alındığında gevşek bir şekilde oluşturulur. LocalView oluşturma işlemi hızlıdır ve önemli bellek kullanmaz. Ancak, çok sayıda varlık için yavaş olabilecek DetectChanges'i çağırır. ve tarafından ToObservableCollection
ToBindingList
oluşturulan koleksiyonlar da gevşek bir şekilde oluşturulur ve ardından önbelleğe alınır. Bu yöntemlerin her ikisi de yavaş olabilecek ve binlerce varlık söz konusu olduğunda çok fazla bellek kullanabilen yeni koleksiyonlar oluşturur.