实体框架4.1虚拟属性

时间:2011-10-12 10:34:37

标签: entity-framework-4.1

如果我在我的模型中声明实体关系为虚拟,则不需要在我的LINQ查询中使用Include语句,对吧? -

例如:这是我的模特课:

public class Brand
{
    public int BrandID { get; set; }
    public string BrandName { get; set; }
    public string BrandDesc { get; set; }
    public string BrandUrl { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

现在,对于上面的模型类,我不需要使用var brandsAndProduct = pe.Brands.Include("Products").Single(brand => brand.BrandID == 22);

相反,我可以使用简单的var brandsAndProduct = pe.Brands.Where(brand => brand.BrandID == 22);,我会在访问时自动提供相关实体。

我的理解是否正确?

另外,请告诉我在什么情况下我应该更喜欢一个?

1 个答案:

答案 0 :(得分:161)

你是正确的,但规则更复杂,使它真正按预期工作。如果您定义导航属性virtual,EF将在运行时创建一个从您的Brand类派生的新类(动态代理),并使用它。这个新动态创建的类包含第一次访问时加载导航属性的逻辑。此功能称为延迟加载(或更好的透明延迟加载)。

要使这项工作必须满足哪些规则:

  • 课程中的所有导航属性必须为virtual
  • 不得禁用动态代理创建(context.Configuration.ProxyCreationEnabled)。它默认启用。
  • 不得禁用延迟加载(context.Configuration.LazyLoadingEnabled)。它默认启用。
  • 必须附加实体(默认情况下,如果从数据库加载实体)到上下文并且不得处理上下文=延迟加载仅在用于从数据库加载它的生活上下文范围内(或者附加了代理实体)< / LI>

延迟加载的反义词称为预加载,这就是Include的作用。如果使用Include,则导航属性将与主实体一起加载。

延迟加载和急切加载的使用取决于您的需求和性能。 Include在单个数据库查询中加载所有数据,但在使用大量包含或加载大量实体​​时,可能会导致huge data set。如果您确定需要Brand和所有Products进行处理,则应使用预先加载。

如果您不确定需要哪种导航属性,则会使用延迟加载。例如,如果您加载100个品牌,但您只需要访问一个品牌的产品,则无需在初始查询中为所有品牌加载产品。延迟加载的缺点是每个导航属性的单独查询(数据库往返)=&gt;如果您加载100个没有包含的品牌,并且您将在每个Products实例中访问Brand属性,您的代码将生成另外100个查询以填充这些导航属性=热切加载将使用单个查询但延迟加载使用101查询(称为N + 1问题)。

在更复杂的情况下,您可以发现这些策略都不能按您的需要运行,您可以使用第三种策略(称为显式加载)或单独查询来加载品牌,而不是使用所需品牌的产品。

显式加载与延迟加载有类似的缺点,但您必须手动触发它:

context.Entry(brand).Collection(b => b.Products).Load();

显式加载的主要优点是过滤关系的能力。您可以在Query()之前使用Load()并使用任何过滤甚至急切加载嵌套关系。

相关问题