İzlenen Varlıklara Erişme

bir tarafından DbContextizlenen varlıklara erişmek için dört ana API vardı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 , , Modifiedveya AddedDeletedbiridirUnchanged; 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 Addedizlemeye 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 , Attachveya Updateçağrısından Adddaha 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 Updatebaş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ğundan Deleted 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 Addedekleyerek 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 izlenmesine Added neden olur. (Varlık zaten oluşturulmuş bir anahtar değerine sahipse, bunun yerine izlenir Unchanged .)
  • Bir varlığın 'den DbSet.Local kaldırılması, varlığın olarak Deletediş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:

Ö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.