在获取父实体 EFCore 时加载子实体

Posted

技术标签:

【中文标题】在获取父实体 EFCore 时加载子实体【英文标题】:Load child entity on the fetch of the Parent entity EFCore 【发布时间】:2020-01-08 04:00:16 【问题描述】:

我有以下型号。在使用 find 方法从数据库中获取时,用子实体加载父实体的更好方法是什么?

父实体:

public class Client

    public int Id  get; set; 

    public string LastName  get; set; 

    public string Gender  get; set; 

    public DateTime DateOfBirth  get; set; 

    public Address Address  get; set; 

子实体:

public class Address

    public int Id  get; set; 

    public string FirstLine  get; set; 

    public string SecondLine  get; set; 

    public string Province  get; set; 

现在,当我尝试使用 Find 方法获取数据时,我的地址实体为空,但是当我签入 DB 数据时,该 ID 也存在于 Child 表中。

referenceContext.Clients.Find(client.Id);

有没有办法克服这个问题?当我获取父对象的同时,子实体的值也与父对象一起加载。

注意:到目前为止,如果我使用 Include(i => i.Address) 然后,然后,只有我能够加载子实体。

我已经使用了包含,但是如果我得到父实体,是否还有其他选项可以加载子实体。

referenceContext.Clients.Where(c => c.IsActive.Equals(true))
                        .Include(i => i.Address).ToList();

【问题讨论】:

【参考方案1】:

在 EF 中,有一个名为 Eager Loading 的概念使用 .Include

MS Docs - Loading Related Data - EF Core

.NET Fiddle

using MyContext context = new MyContext();

IList<Client> clients =
    context.Clients
        .Include(c => c.Address)
        .Where(c => c.LastName == "patel")
        .ToList();

【讨论】:

我忘了添加这个:使用 Microsoft.EntityFrameworkCore;【参考方案2】:

如你所说:

注意:到目前为止,如果我使用了 Include(i => i.Address),那么只有我能够加载子实体。

是的!这是在 EF Core 中加载相关数据的最佳方式。

你又说:

我已经使用了 Include,但是如果我得到父实体,是否还有其他选项可以加载子实体。

是的!有!这称为Lazy loading。要启用延迟加载,您必须将导航属性设置为虚拟,如下所示:

public class Client

    public int Id  get; set; 

    public string LastName  get; set; 

    public string Gender  get; set; 

    public DateTime DateOfBirth  get; set; 

    public virtual Address Address  get; set;  // <-- Here it is

您必须按如下方式注册您的DbConext

services.AddDbContext<BloggingContext>(
    b => b.UseLazyLoadingProxies() // <-- Here is it is
          .UseSqlServer(myConnectionString));

UseLazyLoadingProxies() 方法在 Microsoft.EntityFrameworkCore.Proxies nuget 包中可用。

注意:您不能为某个查询禁用延迟加载。所以使用Eager loading是在EF Core中加载相关数据的最佳方式。

【讨论】:

【参考方案3】:

您可以使用Include()

Linq 查询

using (var context = new DBEntities())

   var result = (from c in context.Client.Include("Address")
            where c.IsActive
            select c).ToList();

Lambda 表达式

using (var context = new DBEntities())

   var result = context.Client.Include(p => p.Address).Where(c => c.IsActive).ToList();

【讨论】:

以上是关于在获取父实体 EFCore 时加载子实体的主要内容,如果未能解决你的问题,请参考以下文章

elementUIel-tree搜索时加载子节点对应父节点父节点对应子节点树

elementUIel-tree搜索时加载子节点对应父节点父节点对应子节点树

如何通过 JPA 查询按子类实体值获取父实体?

[小技巧]EF Core中如何获取上下文中操作过的实体

在 CollectionType Admin 中获取父实体 ID

实体框架代码优先 - 通过主键将子实体添加到父实体