Entity Framework 6 Recipes 2nd Edition(13-10)译 -> 显式创建代理

时间:2024-01-03 17:03:38

问题

你有一个POCO实体,原本在执行一个查询时动态创建代理,现在你不想EF延迟创建代理带来的代价.

解决方案

假设你有一个如图Figure13-15的模型

Entity Framework 6 Recipes 2nd Edition(13-10)译 ->  显式创建代理

Figure 13-15. A model for CDs and music titles

对应的POCO类如代码Listing 13-27.注:每个属性用virtual关键字和每个引用属性为Icoolection类,EF会动态为实体创建跟踪代理(更多信息,请查看Recipe 13-5 ).

Listing 13-27. The POCO Classes Along with Our Object Context

public partial class CD

{

public CD()

{

this.Tracks = new HashSet<Track>();

}

public int CDId { get; set; }

public string Title { get; set; }

public virtual ICollection<Track> Tracks { get; set; }

}

public partial class Track

{

public string Title { get; set; }

public string Artist { get; set; }

public int CDId { get; set; }

}

为了让EF在有需要前(一个实体被装载前)创建代理,我们需要使用ObjectContext的CreateProxyTypes()方法,如代码Listing 13-28.

Listing 13-28. Generating the tracking proxies before loading the entities

using (var context = new EFRecipesEntities())

{

// 为了触发代理创建,我们需要深入到底层的ObjectContext,因为DbContext没有暴露CreateProxyTypes() 方法

var objectContext = ((IObjectContextAdapter)context).ObjectContext;

objectContext.CreateProxyTypes(new Type[] { typeof(CD), typeof(Track) });

var proxyTypes = ObjectContext.GetKnownProxyTypes();

Console.WriteLine("{0} proxies generated!", ObjectContext.GetKnownProxyTypes().Count());

var cds = context.CDs.Include("Tracks");

foreach (var cd in cds)

{

Console.WriteLine("Album: {0}", cd.Title);

foreach (var track in cd.Tracks)

{

Console.WriteLine("\t{0} by {1}", track.Title, track.Artist);

}

}

}

输出结果如下:

2 proxies generated!

Album: Abbey Road

Come Together by The Beatles

Album: Cowboy Town

Cowgirls Don't Cry by *s & Dunn

Album: Long Black Train

In My Dreams by Josh Turner

Jacksonville by Josh Turner

它是如何工作的

动态代理仅在它们被需要的时候创建,这就是说负载发生在第一个查询时,这种延迟创建方式在多数情况下工作得很好.然而你可以在实体第一个被装载前创建代理,通过调用CreateProxyTypes()方法.

CreateProxyTypes()方法以类型数组(实体类型)做为参数,它会创建相对应的实体代理,一旦创建,代理的生命周期与应用程序域的生命周期相同,注意它是被绑定到应用程序域,而不是上下文对象,我们可以释放上下文对象,然后重新创建一个上下文对象,但代理不会被释放,你可以从应用程序域中用上下文对象的静态方法GetKnowProxyTypes()重新获取.

我注:性能篇完结