天天看點

Entity Framework 6 Recipes 2nd Edition(13-3)譯 -> 為一個隻讀的通路擷取實體

問題

你想有效地擷取隻是用來顯示不會更新的操作的實體.另外,你想用CodeFirst的方式來實作

解決方案

一個非常常見行為,尤其是網站,就是隻是讓使用者浏覽資料.大多數情況下,使用者不會更新資料.在這種情況下,你可以通過避開上下文的緩存和修改跟蹤來提高代碼性能,你可以非常簡單地使用AsNoTracking方法來實作.

讓我們假設你一個應用程式來管理doctor(醫生)的appointments(預約),你的模型如下圖Figure 13-5.

Entity Framework 6 Recipes 2nd Edition(13-3)譯 -> 為一個隻讀的通路擷取實體

Figure 13-5. A model for managing doctors and their appointments

         首先,這個例子用EF的CodeFirst方式來實作.,在Listing 13-6建立我們的實體類, Company, Doctor, 和Appointment.

Listing 13-6. The Company, Doctor,and Appointment.Entity Object

   public class Company

    {

        public Company()

        {

            Doctors = new HashSet<Doctor>();

        }

        public int CompanyId { get; set; }

        public string Name { get; set; }

        public virtual ICollection<Doctor> Doctors { get; set; }

    }

    public class Doctor

        public Doctor()

            Appointments = new HashSet<Appointment>();

        public int DoctorId { get; set; }

        public virtual ICollection<Appointment> Appointments { get; set; }

        public virtual Company Company { get; set; }

    public class Appointment

        public int AppointmentId { get; set; }

        public System.DateTime AppointmentDate { get; set; }

        public string Patient { get; set; }

        public virtual Doctor Doctor { get; set; }

}

接下來,在Listing 13-7,我們建立用CodeFirst方式時通路EF的途徑,DbContext對象

Listing 13-7. DbContext Object

    public class Recipe3Context : DbContext

        public Recipe3Context()

            : base("Recipe3ConnectionString")

            // Disable Entity Framework Model Compatibility

            Database.SetInitializer<Recipe3Context>(null);

        protected override void OnModelCreating(DbModelBuilder modelBuilder)

            modelBuilder.Entity<Appointment>().ToTable("Chapter13.Appointment");

            modelBuilder.Entity<Company>().ToTable("Chapter13.Company");

            modelBuilder.Entity<Doctor>().ToTable("Chapter13.Doctor");

        public DbSet<Appointment> Appointments { get; set; }

        public DbSet<Company> Companies { get; set; }

        public DbSet<Doctor> Doctors { get; set; }

接下來我們在項目中添加App.Config,并把下列Listing 13-8的代碼加入到ConnectionString節下

Listing 13-8. Connection String

<connectionStrings>

<add name="Recipe3ConnectionString"

connectionString="Data Source=.;

Initial Catalog=EFRecipes;

Integrated Security=True;

MultipleActiveResultSets=True"

providerName="System.Data.SqlClient" />

</connectionStrings>

為了擷取Doctors和Companies并使他們不添加到上下文對象中,我們把AsNoTracking方法連結到擷取實體的查詢中,如Listing 13-9 那樣.

Listing 13-9. Doing a Simple Query Using the AsNoTracking Method

   using (var context = new Recipe3Context())

            {

                var company = new Company { Name = "Paola Heart Center" };

                var doc1 = new Doctor { Name = "Jill Mathers", Company = company };

                var doc2 = new Doctor { Name = "Robert Stevens", Company = company };

                var app1 = new Appointment

                {

                    AppointmentDate = DateTime.Parse("3/18/2010"),

                    Patient = "Karen Rodgers",

                    Doctor = doc1

                };

                var app2 = new Appointment

                    AppointmentDate = DateTime.Parse("3/20/2010"),

                    Patient = "Steven Cook",

                    Doctor = doc2

                context.Doctors.Add(doc1);

                context.Doctors.Add(doc2);

                context.Appointments.Add(app1);

                context.Appointments.Add(app2);

                context.Companies.Add(company);

                context.SaveChanges();

            }

            using (var context = new Recipe3Context())

                Console.WriteLine("Entities tracked in context for Doctors...");

                // 用AsNoTracking() 方法執行查詢

                context.Doctors.Include("Company").AsNoTracking().ToList();

                Console.WriteLine("Number of entities loaded into context with AsNoTracking: {0}",

                context.ChangeTracker.Entries().Count());//輸出:0

                // 不用AsNoTracking() 方法執行查詢

                context.Doctors.Include("Company").ToList();

                Console.WriteLine("Number of entities loaded into context without AsNoTracking: {0}",

                context.ChangeTracker.Entries().Count());//輸出:3

輸出結果如下:

Entities tracked in context for Doctors...

Number of entities loaded into context with AsNoTracking: 0

Number of entities loaded into context without AsNoTracking: 3

它是如何工作的

當我們把AsNoTracking方法連結上你的查詢,從查詢傳回的結果不會被上下文跟蹤.在我們的例子中,我們顯示地Include了Doctor的Comanpies.

預設情況下,你的查詢結果會被上下文跟蹤,這使得更新和删除更容易,但是代價是付出更多的記憶體和CPU負載.為應用程式串連更多的對象,比如在電子商務網站上浏覽産品,使用AsNoTracking選項,能節省更多的資源,使應用程式性能更高.

         沒有緩存一個查詢結果,你每次都得為查詢執行個體化.通常地,使修改跟蹤可用,EF将不需要為一個上下文中已經存在的執行個體再執行個體化.

         當你包含AsNoTracking選項(如我們的Listing 13-9),它隻影響目前查詢的實體.它不會影響後面的不包含AsNoTracking選項的查詢,如Listing 13-9 示範的

kid1412聲明:轉載請把此段聲明完整地置于文章頁面明顯處,并保留個人在部落格園的連結:http://www.cnblogs.com/kid1412/(可點選跳轉)。