c# – 实体框架中的异步查询和延迟加载
我们正在使用Entity Framework 4.2和模型第一种方法以及DbContext代码生成.
假设我们在实体框架中有以下数据模型: class Person { public string Name { get; set; } public Address Address { get; set; } } class Address { public string City; { get; set; } } 方案如下: > ViewModel想要从数据库加载一些数据 在第3阶段,人员按以下方式加载: using (DatabaseContext context = new DatabaseContext()) { Person person = from p in context.Persons.FirstOrDefault(); return person; } 好的,我知道(理论上)我可以通过两种方式强制加载Address对象: context.Persons.Include("Address").FirstOrDefault(); 2)当数据库上下文仍然存在时访问Person.Address,因为这将强制加载地址 Person person = context.Persons.FirstOrDefault(); Address address = person.Address; return person; 当然第一个是首选的解决方案,因为它不像第二个那样难看(只是访问属性以强制加载数据然后丢弃结果很难看).此外,在收集(例如人员名单)的情况下,我将不得不循环收集并分别为每个人访问地址.第一个解决方案的问题是只有DbSet具有Include方法,而从查询返回的所有其他集合都没有.所以,假设我有以下数据库结构 class Resource {} class Person : Resource { public Address Address { get; set; } } class Appointment { public IList<Resource> Resources { get; set; } } 我想加载所有特定的约会,并在每个人的资源中包含地址,我遇到麻烦(或者至少我无法想办法为它编写查询).这是因为context.Appointments.Resources不是DbSet类型,而是ICollection没有Include方法. (好吧,也许在这种情况下,我可以从context.Persons而不是context.Appointments以某种方式编写一个查询,以便我可以使用Include,但有很多场景,这是不可能的) 基本上问题是: >这是首先进行异步数据库访问的正确方法吗? 解决方法
您可以在启动应用程序或测试时设置包含策略的实现.
首先定义一个Extension方法:Include定义实际的包含机制(默认情况下不做任何操作) /// <summary> /// Extension methods specifically for include since this is essential for DomainContext but not part of IQueryable by default /// </summary> public static class QueryableIncludeExtensions { public static IIncluder Includer = new NullIncluder(); public static IQueryable<T> Include<T,TProperty>(this IQueryable<T> source,Expression<Func<T,TProperty>> path) where T : class { return Includer.Include(source,path); } public interface IIncluder { IQueryable<T> Include<T,TProperty>(IQueryable<T> source,TProperty>> path) where T : class; } internal class NullIncluder : IIncluder { public IQueryable<T> Include<T,TProperty>> path) where T : class { return source; } } } 然后创建一个EF特定的包含器实现,如: internal class DbIncluder : QueryableIncludeExtensions.IIncluder { public IQueryable<T> Include<T,TProperty>> path) where T : class { return DbExtensions.Include(source,path); } } 最后,将DbIncluder实现挂钩到你需要它的项目中,在我的例子中我做到了: public class DomainContext : DbContext,IDomainContext { static DomainContext() { // register the DbIncluder for making sure the right call to include is made (standard is null) QueryableIncludeExtensions.Includer = new DbIncluder(); } 现在IQueryable总是有扩展方法:Include available.如果需要,可以将其扩展为IEnumerable.实际的实现只是由QueryableIncludeExtensions.Includer设置 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |