翻譯的初衷以及爲何選擇《Entity Framework 6 Recipes》來學習,請看本系列開篇html
問題框架
你想使用POCO預先加載關聯實體。ide
解決方案學習
假設你有如圖8-3所示的模型。ui
圖8-3. 一個包含實體Venue、Event和Competitor的模型this
實體使用POCO類,咱們想預先加載關聯實體(導航屬性)。並使用上下文對象中的Include()方法來實現。代碼清單8-4演示了使用Include()方法來實現咱們的要求。spa
代碼清單8-4. 使用Include()方法顯式加載導航屬性翻譯
class Program { static void Main(string[] args) { RunExample(); } static void RunExample() { using (var context = new EFRecipesEntities()) { var venue = new Venue { Name = "Sports and Recreational Grounds" }; var event1 = new Event { Name = "Inter-school Soccer" }; event1.Competitors.Add(new Competitor { Name = "St. Mary's School" }); event1.Competitors.Add(new Competitor { Name = "City School" }); venue.Events.Add(event1); context.Venues.Add(venue); context.SaveChanges(); } using (var context = new EFRecipesEntities()) { foreach (var venue in context.Venues.Include("Events").Include("Events.Competitors")) { Console.WriteLine("Venue: {0}", venue.Name); foreach (var evt in venue.Events) { Console.WriteLine("\tEvent: {0}", evt.Name); Console.WriteLine("\t--- Competitors ---"); foreach (var competitor in evt.Competitors) { Console.WriteLine("\t{0}", competitor.Name); } } } } using (var context = new EFRecipesEntities()) { foreach (var venue in context.Venues) { Console.WriteLine("Venue: {0}", venue.Name); context.Entry(venue).Collection(v => v.Events).Load(); foreach (var evt in venue.Events) { Console.WriteLine("\tEvent: {0}", evt.Name); Console.WriteLine("\t--- Competitors ---"); context.Entry(evt).Collection(e => e.Competitors).Load(); foreach (var competitor in evt.Competitors) { Console.WriteLine("\t{0}", competitor.Name); } } } } Console.WriteLine("Enter input:"); string line = Console.ReadLine(); if (line == "exit") { return; }; } } public partial class Competitor { public int CompetitorId { get; set; } public string Name { get; set; } public int EventId { get; set; } public virtual Event Event { get; set; } } public partial class Event { public Event() { this.Competitors = new HashSet<Competitor>(); } public int EventId { get; set; } public string Name { get; set; } public int VenueId { get; set; } public virtual ICollection<Competitor> Competitors { get; set; } public virtual Venue Venue { get; set; } } public partial class Venue { public Venue() { this.Events = new HashSet<Event>(); } public int VenueId { get; set; } public string Name { get; set; } public virtual ICollection<Event> Events { get; set; } } public partial class EFRecipesEntities : DbContext { public EFRecipesEntities() : base("name=EFRecipesEntities") {
this.Configuration.LazyLoadingEnabled = false; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } public DbSet<Competitor> Competitors { get; set; } public DbSet<Event> Events { get; set; } public DbSet<Venue> Venues { get; set; } }
代碼清單8-4的輸出以下:code
Venue: City Center Hall Event: All Star Boxing --- Competitors ---Big Joe Green Terminator Tim Venue: Sports and Recreational Grounds Event: Inter-school Soccer --- Competitors ---St. Mary's School City School
原理htm
當爲咱們的模型使用實體框架生成的代碼時,咱們使用上下文對象中的Include()方法,查詢並加載關聯實體,這些關聯實體多是實體的列表,多是一個單獨的實體對象 。實體框架中一共有三種不一樣的方法來加載或查詢關聯實體: Eager Loading(預先加載), Lazy Loading(延遲加載)和Explicit Loading(顯式加載)。示例中咱們使用Include()方法演示預先加載關聯實體。默認狀態下,實體框架是開啓延遲加載的,可是在這裏,咱們把它禁用了。爲了使用POCO顯式加載導航屬性,須要使用DbContext中的Include()方法。
問題
你想使用POCO延遲加載關聯實體。
解決方案
假設你有如圖8-4所示的模型。
圖8-4. 一個關於交通罰單、違規車輛和違規細節的模型
啓用延遲加載 ,你不須要作任何事。它是實體框架的默認行爲 。代碼清單8-5對此進行了演示。
代碼清單8-5. 實體類生成,屬性設置爲Virtual,這是實體框架的默認行爲
class Program { static void Main(string[] args) { RunExample(); } static void RunExample() { using (var context = new EFRecipesEntities()) { var vh1 = new Vehicle { LicenseNo = "BR-549" }; var t1 = new Ticket { IssueDate = DateTime.Parse("06/10/13") }; var v1 = new Violation { Description = "20 MPH over the speed limit", Amount = 125M }; var v2 = new Violation { Description = "Broken tail light", Amount = 50M }; t1.Violations.Add(v1); t1.Violations.Add(v2); t1.Vehicle = vh1; context.Tickets.Add(t1); var vh2 = new Vehicle { LicenseNo = "XJY-902" }; var t2 = new Ticket { IssueDate = DateTime.Parse("06/12/13") }; var v3 = new Violation { Description = "Parking in a no parking zone", Amount = 35M }; t2.Violations.Add(v3); t2.Vehicle = vh2; context.Tickets.Add(t2); context.SaveChanges(); } using (var context = new EFRecipesEntities()) { foreach (var ticket in context.Tickets) { Console.WriteLine(" Ticket: {0}, Total Cost: {1}", ticket.TicketId.ToString(), ticket.Violations.Sum(v => v.Amount).ToString("C")); foreach (var violation in ticket.Violations) { Console.WriteLine("\t{0}", violation.Description); } } } Console.WriteLine("Enter input:"); string line = Console.ReadLine(); if (line == "exit") { return; }; } } public partial class Ticket { public Ticket() { this.Violations = new HashSet<Violation>(); } public int TicketId { get; set; } public int VehicleId { get; set; } public System.DateTime IssueDate { get; set; } public virtual Vehicle Vehicle { get; set; } public virtual ICollection<Violation> Violations { get; set; } } public partial class Vehicle { public Vehicle() { this.Tickets = new HashSet<Ticket>(); } public int VehicleId { get; set; } public string LicenseNo { get; set; } public virtual ICollection<Ticket> Tickets { get; set; } } public partial class Violation { public int ViolationId { get; set; } public string Description { get; set; } public decimal Amount { get; set; } public int TicketId { get; set; } public virtual Ticket Ticket { get; set; } } public partial class EFRecipesEntities : DbContext { public EFRecipesEntities() : base("name=EFRecipesEntities") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } public DbSet<Ticket> Tickets { get; set; } public DbSet<Vehicle> Vehicles { get; set; } public DbSet<Violation> Violations { get; set; } }
代碼清單8-5的輸出以下:
Ticket: 1, Total Cost: $175.00 20 MPH over the speed limit Broken tail light Ticket: 2, Total Cost: $35.00 Parking in a no parking zone
原理
當生成一個實體數據模型時,延遲加載被默認設置。導航屬性默認也被標記爲virtual。使用延遲加載,你不須要顯式地作任何事。
在上面的控制檯程序中,咱們沒有編寫別的代碼來加載Violation對象,它是Ticket對象的關聯對象。當你在代碼中訪問關聯實體時,延遲加載就生效了。它不須要上下文對象在第一次加載主實體時就加載關聯實體,不須要像上一節中使用Include()方法顯式加載關聯實體。
實體框架交流QQ羣: 458326058,歡迎有興趣的朋友加入一塊兒交流
謝謝你們的持續關注,個人博客地址:http://www.cnblogs.com/VolcanoCloud/