简体   繁体   English

实体框架:为什么使用虚拟关键字在DbContext中声明属性

[英]Entity Framework: Why virtual keyword used to declare properties in DbContext

i rare use EF. 我很少使用EF。 so i have a question. 所以我有一个问题。 if we do not use virtual keyword with dbset then lazy load will not work? 如果我们不将virtual关键字与dbset一起使用,那么延迟加载将不起作用?

i read a article from this link https://stackoverflow.com/a/24114284/5314244 they provide code like 我从此链接https://stackoverflow.com/a/24114284/5314244阅读了一篇文章,他们提供了类似的代码

public class AppContext : DbContext
{
    public AppContext()
    {
        Configuration.LazyLoadingEnabled = true;
    }

    public virtual DbSet<AccountType> AccountTypes { get; set; }
}

public class AccountType
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<AccountCode> AccountCodes { get; set; }
}

public class AccountCode
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public Guid AccountTypeId { get; set; }
    public virtual AccountType AccountType { get; set; }
}

they said : 他们说 :

The virtual keyword on the navigation properties are used to enable lazy loading mechanism, but the LazyLoadingEnabled property of the configuration must be enabled.

The virtual keyword on AccountType::AccountCodes navigation property will load all account codes the moment there is a programmatically access to that property while the db context are still alive

if we declare this code without virtual keyword public DbSet<AccountType> AccountTypes { get; set; } 如果我们声明此代码时没有虚拟关键字public DbSet<AccountType> AccountTypes { get; set; } public DbSet<AccountType> AccountTypes { get; set; } public DbSet<AccountType> AccountTypes { get; set; } then when this line execute var accountCodes = accountType.AccountCodes; public DbSet<AccountType> AccountTypes { get; set; }然后在此行execute var accountCodes = accountType.AccountCodes; what will happen? 会发生什么?

Error will thrown or null will be stored in accountCodes variable? 将抛出错误还是将null存储在accountCodes变量中?

second question what is default in EF---> lazy load or eager loading? 第二个问题是EF --->延迟加载或渴望加载中的默认设置是什么? how many type of loading option available ? 有多少种加载选项可用?

thanks 谢谢

The approach you want to achieve, lazy loading, means that the data provider, in your case Entity Framework, retrieves certain data at the time you need it. 延迟加载是您要实现的方法,这意味着数据提供程序(在您的情况下为Entity Framework)会在需要时检索某些数据。 If, for example, you access all account types you probably don't need to access all account codes for these account types thus retrieving them from the database would be unnecessary. 例如,如果您访问所有帐户类型,则可能不需要访问这些帐户类型的所有帐户代码,因此从数据库中检索它们是不必要的。

If you had to write the SQL yourself, you would most likely write a plain select statement without joining the child relations: 如果必须自己编写SQL,则很可能在不加入子关系的情况下编写普通的select语句:

SELECT * FROM AccountTypes;

Another use-case on the other hand might need access to this data so you would either end up with eagerly loading it which results in a join operation... 另一方面,另一个用例可能需要访问此数据,因此您要么会急于加载它,最终导致联接操作...

SELECT * FROM AccountTypes JOIN AccountCodes ON AccountCodes.AccountTypeId = AccountTypes.Id;

...or to rely on Entity Framework's lazy loading ability. ...或依靠Entity Framework的延迟加载功能。

The latter case requires Entity Framework to do the following: First, selecting all account types and then, at the time your user-code accesses the account codes, emitting another select statement to retrieve the codes for the respective account type. 在后一种情况下,Entity Framework需要执行以下操作:首先,选择所有帐户类型,然后在您的用户代码访问帐户代码时,发出另一个select语句以检索相应帐户类型的代码。 To do so, Entity Framework needs a hook, ie it must know when you access the navigation property, which is in general impossible because this would need additional code in the getter of this property: 为此,实体框架需要一个钩子,即它必须知道何时访问导航属性,这通常是不可能的,因为在此属性的getter中将需要其他代码:

public class AccountType
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<AccountCode> AccountCodes
    { 
        get { /* Load child data here */ }
        set { /* ... */ }
    }
}

Unfortunately Entity Framework is unable to alter the POCO class because it's your user-code , but what it can do is deriving from your class and overriding the property to inject it's magic. 不幸的是,Entity Framework无法更改POCO类,因为它是您的用户代码 ,但是它能做的是从您的类派生并重写该属性以注入魔力。 For this to work it creates what is called a proxy , ie it creates a class at runtime which derives from your POCO class, like: 为此,它创建了一个称为proxy的代理 ,即,它在运行时创建了一个从POCO类派生的类,例如:

public class AccountTypeProxy : AccountType
{
    public override ICollection<AccountCode> AccountCodes
    { 
        get { /* Load child data here */ }
        set { /* ... */ }
    }
}

So what you get when you retrieve the account types is actually a bunch of proxy instances, which you can confirm during debugging. 因此,检索帐户类型时得到的实际上是一堆代理实例,您可以在调试过程中进行确认。

If you would not add the virtual keyword to the navigation property or if you sealed the class, Entity Framework could not override the property or could not derive from the class at all and thus lazy loading would not work. 如果您不将virtual关键字添加到navigation属性,或者如果您密封了该类,则Entity Framework无法覆盖该属性或完全不能从该类派生,因此延迟加载将无法进行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实体框架属性中的虚拟关键字 - Virtual keyword in Entity Framework properties virtual关键字对Entity Framework 5中的实体属性有什么影响? - What effect does the virtual keyword have on entity properties in Entity Framework 5? 实体框架虚拟属性 - Entity Framework Virtual Properties 为什么在实体框架模型定义中对类属性使用“虚拟”? - Why use 'virtual' for class properties in Entity Framework model definitions? 如果我将virtual关键字添加到属性,我需要帮助解决为什么Entity Framework不会保存 - I need help solving why Entity Framework won't save if I add the virtual keyword to a property DbContext.Database.SqlQuery不会填充实体框架的额外属性 - Entity Framework extra properties are not populated by DbContext.Database.SqlQuery 实体框架导航属性未加载直到新的DbContext已建立 - Entity Framework Navigation Properties not loading til new DbContext is established 在依赖注入中使用 Entity Framework Core DbContext 时不调用 OnModelCreating - OnModelCreating is not called when Entity Framework Core DbContext is used in Dependency Injection 实体框架:为什么仍要尝试从DbContext中读取已删除的实体? - Entity Framework: why still trying to read from a removed entity in the DbContext? 实体框架-DBContext平等 - Entity Framework - DBContext Equality
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM