翻译的初衷以及为什么选择《Entity Framework 6 Recipes》来学习,请看本系列开篇

8-2  使用POCO加载关联实体

问题

  你想使用POCO预先加载关联实体。

解决方案

  假设你有如图8-3所示的模型。

图8-3. 一个包含实体Venue、Event和Competitor的模型

  实体使用POCO类,我们想预先加载关联实体(导航属性)。并使用上下文对象中的Include()方法来实现。代码清单8-4演示了使用Include()方法来实现我们的要求。

代码清单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的输出如下:

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

原理

  当为我们的模型使用实体框架生成的代码时,我们使用上下文对象中的Include()方法,查询并加载关联实体,这些关联实体可能是实体的列表,可能是一个单独的实体对象 。实体框架中一共有三种不同的方法来加载或查询关联实体: Eager Loading(预先加载), Lazy Loading(延迟加载)和Explicit Loading(显式加载)。示例中我们使用Include()方法演示预先加载关联实体。默认状态下,实体框架是开启延迟加载的,但是在这里,我们把它禁用了。为了使用POCO显式加载导航属性,需要使用DbContext中的Include()方法。

8-3  使用POCO延迟加载

问题

  你想使用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: , Total Cost: $175.00
MPH over the speed limit
Broken tail light
Ticket: , Total Cost: $35.00
Parking in a no parking zone

原理

  当生成一个实体数据模型时,延迟加载被默认设置。导航属性默认也被标记为virtual。使用延迟加载,你不需要显式地做任何事。

  在上面的控制台程序中,我们没有编写别的代码来加载Violation对象,它是Ticket对象的关联对象。当你在代码中访问关联实体时,延迟加载就生效了。它不需要上下文对象在第一次加载主实体时就加载关联实体,不需要像上一节中使用Include()方法显式加载关联实体。

实体框架交流QQ群:  458326058,欢迎有兴趣的朋友加入一起交流

谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/VolcanoCloud/

《Entity Framework 6 Recipes》中文翻译系列 (43) ------ 第八章 POCO之使用POCO加载实体的更多相关文章

  1. 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述

    微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...

  2. 《Entity Framework 6 Recipes》翻译系列(2) -----第一章 开始使用实体框架之使用介绍

    Visual Studio 我们在Windows平台上开发应用程序使用的工具主要是Visual Studio.这个集成开发环境已经演化了很多年,从一个简单的C++编辑器和编译器到一个高度集成.支持软件 ...

  3. 《Entity Framework 6 Recipes》翻译系列 (4) -----第二章 实体数据建模基础之从已存在的数据库创建模型

    不知道对EF感兴趣的并不多,还是我翻译有问题(如果是,恳请你指正),通过前几篇的反馈,阅读这个系列的人不多.不要这事到最后成了吃不讨好的事就麻烦了,废话就到这里,直奔主题. 2-2 从已存在的数据库创 ...

  4. 《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型

    第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...

  5. 《Entity Framework 6 Recipes》翻译系列 (5) -----第二章 实体数据建模基础之有载荷和无载荷的多对多关系建模

    2-3 无载荷(with NO Payload)的多对多关系建模 问题 在数据库中,存在通过一张链接表来关联两张表的情况.链接表仅包含连接两张表形成多对多关系的外键,你需要把这两张多对多关系的表导入到 ...

  6. 《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章  ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架 ...

  7. 《Entity Framework 6 Recipes》中文翻译系列 (21) -----第四章 ASP.NET MVC中使用实体框架之在页面中创建查询和使用ASP.NET URL路由过虑

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 4.2. 构建一个搜索查询 搜索数据是几乎所有应用的一个基本功能.它一般是动态的,因 ...

  8. 《Entity Framework 6 Recipes》中文翻译系列 (42) ------ 第八章 POCO之使用POCO

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第八章 POCO 对象不应该知道如何保存它们,加载它们或者过滤它们.这是软件开发中熟 ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (44) ------ 第八章 POCO之POCO中使用值对象和对象变更通知

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-4  POCO中使用值对象(Complex Type--也叫复合类型)属性 问题 ...

随机推荐

  1. SQL函数说明大全

    一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果.这些要求包括:执行计算与数学运算.转换数据.解析数值.组合值和聚合一个范围内的值等. 下表给出了T-SQL函数的类别和描 ...

  2. Nginx - 配置

    1 自动显示目录 autoindex on; 1.1 显示文件大小 autoindex_exact_size off; 默认为on,显示出文件的确切大小,单位是bytes. 改为off后,显示出文件的 ...

  3. (转)Lock和synchronized比较详解

    今天看了并发实践这本书的ReentantLock这章,感觉对ReentantLock还是不够熟悉,有许多疑问,所有在网上找了很多文章看了一下,总体说的不够详细,重点和焦点问题没有谈到,但这篇文章相当不 ...

  4. Android中轻松显示Gif图片

    android中现在没有直接显示gif的view,只能通过mediaplay来显示,且还常常不能正常显示出来,为此写了这个gifview,其用法和imageview一样使用方法:1-把GifView. ...

  5. 支付宝支付-APP支付服务端详解

    支付宝APP支付服务端详解 前面接了微信支付,相比微信支付,支付宝APP支付提供了支付分装类,下面将实现支付宝APP支付.订单查询.支付结果异步通知.APP支付申请参数说明,以及服务端返回APP端发起 ...

  6. http://devdocs.io/【文档收藏】

    http://devdocs.io http://bower.io/ www.bower.iobrowserify.org jsPlumb布局 https://github.com/lndb/jsPl ...

  7. bzoj1103树状数组水题

    (卧槽,居然规定了修改的两点直接相连,亏我想半天) 非常水的题,用dfs序(而且不用重复,应该是直接规模为n的dfs序)+树状数组可以轻松水 收获:树状数组一遍A(没啥好骄傲的,那么简单的东西) #i ...

  8. C# 中对 ArrayList 的排序

    ArrayList 元素 //目录条目类 public class FolderItem { public string filename; public string filetype; publi ...

  9. UBUNTU 16.04 编译 OPENJDK8

    参考了几篇文章,和错误查询,最后总结如下 一.下载 我比较倾向于使用mercurial来获取源代码,虽然你得挑网络稳定的时候更新,但是易更新. 从官网查找一下,可以通过以下步骤完成源代码的下载 1. ...

  10. 【ToolKit】轻量级JS库

    优点: 丢弃了一些不常用的方法(jQuery.fn):slideUp.fadeIn.animate等: 新增获取子节点的方法(ToolKit.fn):firstChild,lastChild等: 新增 ...