Share via


İlgili Varlıkları Yükleme

Entity Framework, ilgili verileri yüklemenin üç yolunu destekler: hevesle yükleme, gecikmeli yükleme ve açık yükleme. Bu konu başlığında gösterilen teknikler, gerek Code First gerekse EF Designer ile oluşturulan modellere için geçerlidir.

Hevesle Yükleniyor

İstekli yükleme, bir varlık türü için sorgunun sorgunun bir parçası olarak ilgili varlıkları da yüklediği işlemdir. İstekli yükleme, Include yöntemi kullanılarak elde edilir. Örneğin, aşağıdaki sorgular blogları ve her blogla ilgili tüm gönderileri yükler.

using (var context = new BloggingContext())
{
    // Load all blogs and related posts.
    var blogs1 = context.Blogs
                        .Include(b => b.Posts)
                        .ToList();

    // Load one blog and its related posts.
    var blog1 = context.Blogs
                       .Where(b => b.Name == "ADO.NET Blog")
                       .Include(b => b.Posts)
                       .FirstOrDefault();

    // Load all blogs and related posts
    // using a string to specify the relationship.
    var blogs2 = context.Blogs
                        .Include("Posts")
                        .ToList();

    // Load one blog and its related posts
    // using a string to specify the relationship.
    var blog2 = context.Blogs
                       .Where(b => b.Name == "ADO.NET Blog")
                       .Include("Posts")
                       .FirstOrDefault();
}

Dekont

Include, System.Data.Entity ad alanındaki bir uzantı yöntemidir, bu nedenle bu ad alanını kullandığınızdan emin olun.

Birden çok düzeyi hevesle yükleme

Birden çok ilişkili varlık düzeyini hevesle yüklemek de mümkündür. Aşağıdaki sorgular, bunun hem koleksiyon hem de başvuru gezinti özellikleri için nasıl yapılacağını gösteren örnekler gösterir.

using (var context = new BloggingContext())
{
    // Load all blogs, all related posts, and all related comments.
    var blogs1 = context.Blogs
                        .Include(b => b.Posts.Select(p => p.Comments))
                        .ToList();

    // Load all users, their related profiles, and related avatar.
    var users1 = context.Users
                        .Include(u => u.Profile.Avatar)
                        .ToList();

    // Load all blogs, all related posts, and all related comments  
    // using a string to specify the relationships.
    var blogs2 = context.Blogs
                        .Include("Posts.Comments")
                        .ToList();

    // Load all users, their related profiles, and related avatar  
    // using a string to specify the relationships.
    var users2 = context.Users
                        .Include("Profile.Avatar")
                        .ToList();
}

Dekont

Şu anda hangi ilgili varlıkların yüklendiğini filtrelemek mümkün değildir. Dahil et her zaman tüm ilgili varlıkları getirir.

Geç Yükleme

Gecikmeli yükleme, varlık/varlıklara başvuran bir özelliğe ilk kez erişildiğinde bir varlık veya varlık koleksiyonu veritabanından otomatik olarak yüklendiği işlemdir. POCO varlık türleri kullanılırken, türetilmiş proxy türlerinin örnekleri oluşturularak ve ardından yükleme kancasını eklemek için sanal özellikleri geçersiz kılarak gecikmeli yükleme gerçekleştirilir. Örneğin, aşağıda tanımlanan Blog varlık sınıfı kullanılırken, Gönderiler gezinti özelliğine ilk kez erişildiğinde ilgili Gönderiler yüklenir:

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public string Tags { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

Serileştirme için gecikmeli yüklemeyi kapatma

Gecikmeli yükleme ve serileştirme iyi bir şekilde karışmaz ve dikkatli değilseniz, gecikmeli yükleme etkinleştirildiğinden veritabanınızın tamamı için sorgulama yapabilirsiniz. Çoğu serileştirici, türün bir örneğindeki her özelliğe erişerek çalışır. Özellik erişimi gecikmeli yüklemeyi tetikler, böylece daha fazla varlık serileştirilir. Bu varlıklarda özelliklere erişilir ve daha fazla varlık yüklenir. Bir varlığı seri hale getirmeden önce gecikmeli yüklemeyi kapatmak iyi bir uygulamadır. Aşağıdaki bölümlerde bunun nasıl yapacağı gösterilmektedir.

Belirli gezinti özellikleri için gecikmeli yüklemeyi kapatma

Postlar koleksiyonunun gecikmeli yüklenmesi, Postlar özelliğini sanal olmayan hale getirerek kapatılabilir:

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public string Tags { get; set; }

    public ICollection<Post> Posts { get; set; }
}

Gönderiler koleksiyonunun yüklenmesi yine de eager yükleme (bkz. Yukarıdaki Hevesle Yükleniyor) veya Load yöntemi kullanılarak (aşağıdaki Açıkça Yükleniyor bölümüne bakın).

Tüm varlıklar için gecikmeli yüklemeyi kapatma

Configuration özelliğinde bir bayrak ayarlanarak bağlamdaki tüm varlıklar için gecikmeli yükleme kapatılabilir. Örnek:

public class BloggingContext : DbContext
{
    public BloggingContext()
    {
        this.Configuration.LazyLoadingEnabled = false;
    }
}

İlgili varlıkların yüklenmesi yine de istekli yükleme (yukarıdaki Hevesle Yükleniyor bölümüne bakın) veya Load yöntemi kullanılarak yapılabilir (aşağıdaki Açıkça Yükleniyor bölümüne bakın).

Açıkça Yükleniyor

Gecikmeli yükleme devre dışı bırakılsa bile, ilgili varlıkların yavaş yüklenmesi mümkündür, ancak bunun açık bir çağrıyla yapılması gerekir. Bunu yapmak için ilgili varlığın girişinde Load yöntemini kullanırsınız. Örnek:

using (var context = new BloggingContext())
{
    var post = context.Posts.Find(2);

    // Load the blog related to a given post.
    context.Entry(post).Reference(p => p.Blog).Load();

    // Load the blog related to a given post using a string.
    context.Entry(post).Reference("Blog").Load();

    var blog = context.Blogs.Find(1);

    // Load the posts related to a given blog.
    context.Entry(blog).Collection(p => p.Posts).Load();

    // Load the posts related to a given blog
    // using a string to specify the relationship.
    context.Entry(blog).Collection("Posts").Load();
}

Dekont

Bir varlığın başka bir tek varlığa gezinti özelliği olduğunda Reference yöntemi kullanılmalıdır. Öte yandan, bir varlığın diğer varlıklar koleksiyonunda gezinti özelliği olduğunda Collection yöntemi kullanılmalıdır.

Query yöntemi, Entity Framework'ün ilgili varlıkları yüklerken kullanacağı temel sorguya erişim sağlar. Ardından LINQ kullanarak sorguyu Yürütmeden önce ToList, Load gibi bir LINQ uzantısı yöntemine çağrı yaparak filtre uygulayabilirsiniz. Sorgu yöntemi hem başvuru hem de koleksiyon gezinti özellikleriyle kullanılabilir, ancak koleksiyonun yalnızca bir bölümünü yüklemek için kullanılabildiği koleksiyonlar için en kullanışlı yöntemdir. Örnek:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);

    // Load the posts with the 'entity-framework' tag related to a given blog.
    context.Entry(blog)
           .Collection(b => b.Posts)
           .Query()
           .Where(p => p.Tags.Contains("entity-framework"))
           .Load();

    // Load the posts with the 'entity-framework' tag related to a given blog
    // using a string to specify the relationship.
    context.Entry(blog)
           .Collection("Posts")
           .Query()
           .Where(p => p.Tags.Contains("entity-framework"))
           .Load();
}

Sorgu yöntemini kullanırken genellikle gezinti özelliği için gecikmeli yüklemeyi kapatmak en iyisidir. Bunun nedeni, aksi takdirde filtrelenen sorgu yürütülmeden önce veya sonra tüm koleksiyonun gecikmeli yükleme mekanizması tarafından otomatik olarak yüklenebilmesidir.

Dekont

İlişki lambda ifadesi yerine dize olarak belirtilebilir, ancak döndürülen IQueryable bir dize kullanıldığında genel değildir ve bu nedenle genellikle yararlı bir şey yapılabilmesi için önce Cast yöntemi gerekir.

Bazen, veritabanındaki başka bir varlıkla ilişkili varlık sayısını bilmek, bu varlıkların tümünü yükleme maliyetine neden olmadan yararlı olabilir. Bunu yapmak için LINQ Count yöntemine sahip Query yöntemi kullanılabilir. Örnek:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);

    // Count how many posts the blog has.
    var postCount = context.Entry(blog)
                           .Collection(b => b.Posts)
                           .Query()
                           .Count();
}