Zaman uyumsuz sorgu ve kaydetme

Dekont

Yalnızca EF6'ya Doğru - Bu sayfada ele alınan özellikler, API'ler vb. Entity Framework 6'da sunulmuştur. Önceki bir sürümü kullanıyorsanız, bilgilerin bir kısmı veya tümü geçerli değildir.

EF6, .NET 4.5'te kullanıma sunulan zaman uyumsuz sorgu ve bekleme anahtar sözcüklerini kullanarak zaman uyumsuz sorgu ve kaydetme desteği sunar. Tüm uygulamalar zaman uyumsuzluktan yararlanamayabilir ancak uzun süre çalışan, ağ veya G/Ç'ye bağlı görevleri işlerken istemci yanıt hızını ve sunucu ölçeklenebilirliğini geliştirmek için kullanılabilir.

Zaman uyumsuz gerçekten ne zaman kullanılır?

Bu kılavuzun amacı, zaman uyumsuz ve zaman uyumlu program yürütme arasındaki farkı gözlemlemesini kolaylaştıracak şekilde zaman uyumsuz kavramları tanıtmaktır. Bu izlenecek yol, zaman uyumsuz programlamanın avantaj sağladığı temel senaryoların hiçbirini göstermek için tasarlanmamıştır.

Zaman uyumsuz programlama öncelikle yönetilen bir iş parçacığından işlem süresi gerektirmeyen bir işlemi beklerken diğer işleri yapmak için geçerli yönetilen iş parçacığını (.NET kodu çalıştıran iş parçacığı) boşaltmaya odaklanır. Örneğin, veritabanı altyapısı bir sorguyu işlerken .NET kodu tarafından yapılacak bir şey yoktur.

İstemci uygulamalarında (WinForms, WPF vb.) zaman uyumsuz işlem gerçekleştirilirken kullanıcı arabiriminin yanıt vermesini sağlamak için geçerli iş parçacığı kullanılabilir. Sunucu uygulamalarında (ASP.NET vb.) iş parçacığı diğer gelen istekleri işlemek için kullanılabilir- bu, bellek kullanımını azaltabilir ve/veya sunucunun aktarım hızını artırabilir.

Zaman uyumsuz kullanan uygulamaların çoğunda fark edilebilir bir avantajı olmaz ve hatta zarar verebilir. İşlemeden önce belirli bir senaryonuzda zaman uyumsuzun etkisini ölçmek için testleri, profil oluşturmayı ve sağduyuyu kullanın.

Zaman uyumsuz hakkında daha fazla bilgi edinmek için aşağıda daha fazla kaynak bulabilirsiniz:

Modeli oluşturma

Modelimizi oluşturmak ve veritabanını oluşturmak için İlk Kod iş akışını kullanacağız ancak zaman uyumsuz işlevsellik, EF Tasarım Aracı ile oluşturulanlar da dahil olmak üzere tüm EF modelleriyle çalışır.

  • Konsol Uygulaması oluşturma ve AsyncDemo olarak çağırma
  • EntityFramework NuGet paketini ekleme
    • Çözüm Gezgini'da AsyncDemo projesine sağ tıklayın
    • NuGet Paketlerini Yönet... öğesini seçin .
    • NuGet Paketlerini Yönet iletişim kutusunda Çevrimiçi sekmesini seçin ve EntityFramework paketini seçin
    • Yükle'ye tıklayın
  • Aşağıdaki uygulamayla bir Model.cs sınıfı ekleyin
    using System.Collections.Generic;
    using System.Data.Entity;

    namespace AsyncDemo
    {
        public class BloggingContext : DbContext
        {
            public DbSet<Blog> Blogs { get; set; }
            public DbSet<Post> Posts { get; set; }
        }

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

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

        public class Post
        {
            public int PostId { get; set; }
            public string Title { get; set; }
            public string Content { get; set; }

            public int BlogId { get; set; }
            public virtual Blog Blog { get; set; }
        }
    }

 

Zaman uyumlu program oluşturma

Artık bir EF modelimiz olduğuna göre, veri erişimi gerçekleştirmek için bu modeli kullanan bazı kodlar yazalım.

  • Program.cs dosyasının içeriğini aşağıdaki kodla değiştirin
    using System;
    using System.Linq;

    namespace AsyncDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                PerformDatabaseOperations();

                Console.WriteLine("Quote of the day");
                Console.WriteLine(" Don't worry about the world coming to an end today... ");
                Console.WriteLine(" It's already tomorrow in Australia.");

                Console.WriteLine();
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }

            public static void PerformDatabaseOperations()
            {
                using (var db = new BloggingContext())
                {
                    // Create a new blog and save it
                    db.Blogs.Add(new Blog
                    {
                        Name = "Test Blog #" + (db.Blogs.Count() + 1)
                    });
                    Console.WriteLine("Calling SaveChanges.");
                    db.SaveChanges();
                    Console.WriteLine("SaveChanges completed.");

                    // Query for all blogs ordered by name
                    Console.WriteLine("Executing query.");
                    var blogs = (from b in db.Blogs
                                orderby b.Name
                                select b).ToList();

                    // Write all blogs out to Console
                    Console.WriteLine("Query completed with following results:");
                    foreach (var blog in blogs)
                    {
                        Console.WriteLine(" " + blog.Name);
                    }
                }
            }
        }
    }

Bu kod, veritabanına yeni bir Blog kaydeden yöntemini çağırır PerformDatabaseOperations ve ardından veritabanından tüm Blogları alır ve konsola yazdırır. Bundan sonra, program konsola günün bir alıntısını yazar.

Kod zaman uyumlu olduğundan, programı çalıştırırken aşağıdaki yürütme akışını gözlemleyebiliriz:

  1. SaveChanges yeni Blogu veritabanına göndermeye başlar
  2. SaveChanges Tamamlayan
  3. Tüm Bloglar için sorgu veritabanına gönderilir
  4. Sorgu döndürür ve sonuçlar Konsol'a yazılır
  5. Günün alıntısı Konsol'a yazılır

Sync Output 

 

Zaman uyumsuz hale getirme

Artık programımızı çalıştırdığımıza göre, yeni zaman uyumsuz ve await anahtar sözcüklerini kullanmaya başlayabiliriz. Program.cs dosyasında aşağıdaki değişiklikleri yaptık

  1. 2. Satır: Ad alanının using deyimi System.Data.Entity , EF zaman uyumsuz uzantı yöntemlerine erişmemizi sağlar.
  2. 4. Satır: Ad alanının using deyimi System.Threading.Tasks , türünü kullanmamıza Task olanak tanır.
  3. Satır 12 & 18: Programın ilerleme durumunu PerformSomeDatabaseOperations izleyen (12. satır) ve ardından program için tüm çalışmalar tamamlandıktan sonra bu görevin program yürütmesini engelleyen bir görev olarak yakalıyoruz (18. satır).
  4. 25. Satır: olarak işaretlenecek ve döndürülecek şekilde asyncTaskgüncelleştirdikPerformSomeDatabaseOperations.
  5. 35. Satır: Şimdi zaman uyumsuz sürümünü SaveChanges çağırıyoruz ve tamamlanmasını bekliyoruz.
  6. 42. Satır: Şimdi Async sürümünü ToList çağırıyoruz ve sonucu bekliyoruz.

Ad alanında System.Data.Entity kullanılabilir uzantı yöntemlerinin kapsamlı bir listesi için sınıfına QueryableExtensions bakın. Ayrıca using deyimlerinize de eklemeniz using System.Data.Entity gerekir.

    using System;
    using System.Data.Entity;
    using System.Linq;
    using System.Threading.Tasks;

    namespace AsyncDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                var task = PerformDatabaseOperations();

                Console.WriteLine("Quote of the day");
                Console.WriteLine(" Don't worry about the world coming to an end today... ");
                Console.WriteLine(" It's already tomorrow in Australia.");

                task.Wait();

                Console.WriteLine();
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }

            public static async Task PerformDatabaseOperations()
            {
                using (var db = new BloggingContext())
                {
                    // Create a new blog and save it
                    db.Blogs.Add(new Blog
                    {
                        Name = "Test Blog #" + (db.Blogs.Count() + 1)
                    });
                    Console.WriteLine("Calling SaveChanges.");
                    await db.SaveChangesAsync();
                    Console.WriteLine("SaveChanges completed.");

                    // Query for all blogs ordered by name
                    Console.WriteLine("Executing query.");
                    var blogs = await (from b in db.Blogs
                                orderby b.Name
                                select b).ToListAsync();

                    // Write all blogs out to Console
                    Console.WriteLine("Query completed with following results:");
                    foreach (var blog in blogs)
                    {
                        Console.WriteLine(" - " + blog.Name);
                    }
                }
            }
        }
    }

Kod artık zaman uyumsuz olduğuna göre, programı çalıştırdığımızda farklı bir yürütme akışı gözlemleyebiliriz:

  1. SaveChanges yeni Blogu veritabanına göndermeye başlar
    Komut veritabanına gönderildikten sonra geçerli yönetilen iş parçacığında işlem süresi gerekmez. PerformDatabaseOperations yöntemi döndürür (yürütmeyi tamamlamamış olsa da) ve Main yöntemindeki program akışı devam eder.
  2. Günün alıntısı Konsol'a yazılır
    Main yönteminde yapılacak başka iş olmadığından, veritabanı işlemi tamamlanana kadar yönetilen iş parçacığı çağrıda Wait engellenir. İşlem tamamlandıktan sonra geri kalanımız PerformDatabaseOperations yürütülecek.
  3. SaveChanges Tamamlayan
  4. Tüm Bloglar için sorgu veritabanına gönderilir
    Sorgu veritabanında işlenirken yönetilen iş parçacığının başka işler yapması da serbesttir. Diğer tüm yürütmeler tamamlandığından, iş parçacığı Bekleme çağrısında durur.
  5. Sorgu döndürür ve sonuçlar Konsol'a yazılır

Async Output 

 

Paket servis

ARTıK EF'in zaman uyumsuz yöntemlerini kullanmanın ne kadar kolay olduğunu gördük. Basit bir konsol uygulamasında zaman uyumsuzluk avantajları çok belirgin olmasa da, uzun süre çalışan veya ağa bağlı etkinliklerin uygulamayı engelleyebileceği veya bellek ayak izini artırmak için çok sayıda iş parçacığına neden olabileceği durumlarda da bu stratejiler uygulanabilir.