gpt4 book ai didi

c# - 是否可以将复杂的 EF Core ".Include"调用重写为 "Join"调用?

转载 作者:行者123 更新时间:2023-12-05 02:45:54 25 4
gpt4 key购买 nike

我有两个名为 Service 和 ServiceBranch 的 EF Core 实体模型:

public class Service
{
public Guid ID { get; set; }
public Guid? ParentServiceID { get; set; } // foreign key to the same table
public string Name { get; set; }
public DateTime? DateDeleted { get; set; }

public virtual ICollection<Service> InverseParent { get; set; } // navigation property
public virtual ICollection<ServiceBranch> ServiceBranches { get; set; } // navigation property
}

public class ServiceBranch
{
public Guid ID { get; set; }
public Guid ServiceID { get; set; } // foreign key
public string Name { get; set; }
public DateTime? DateDeleted { get; set; }

public virtual Service Service { get; set; } // navigation property
}

为简单起见,假设父服务只能有一个级别的子服务。许多服务分支都引用了父子服务。

我想更新特定服务 ID 的 DateDeleted 字段并更新引用它的所有其他行中的 DateDeleted(如果该字段尚无值)。

目前我调用所有必需的实体如下所示:

var serviceEntity = _context.Set<Service>().Where(x => x.ID == neededID && x.DateDeleted == null)
.Include(x => x.ServiceBranches)
.Include(x => x.InverseParent)
.ThenInclude(InverseParent => InverseParent.ServiceBranches)
.FirstOrDefault();

我对主要实体使用 Where 子句,但遗憾的是我不能在 .Includes 中使用 Where,因为我们还没有升级到 EF Core 5.0(它支持在 .Includes 中进行过滤)。

因此我从数据库中获取了太多不需要的行(其中 DateDeleted 已经有一个值),然后通过将该字段与 null 进行比较来在 foreach 循环中过滤它们:

if (myentity.DateDeleted == null) myentity.DateDeleted = DateTime.Now;

我想重写我的查询,以便使用“join”而不是“.Include”,如下所示:

var serviceEntity = from service in _context.Set<Service>()
where service.ID == neededID && service.DateDeleted == null
join branches in _context.Set<ServiceBranch>() on service.ID equals branches.ServiceID
where branches.DateDeleted == null // filter which I cannot use with .Include-s
let // whatever, can't make it work
select // etc

我不知道如何重写它。或者甚至可以通过联接来实现。

最佳答案

在这种特殊情况下,您不需要连接,而是包含所需的 Service 实体及其所有子实体的平面列表。一般来说,这需要递归查询(LINQ/EF Core 不支持),但对于单层来说,这是一个简单的过滤器问题,比如

service.ID == neededID || service.ParentServiceID == neededID

然后您可以应用附加的 DateDeleted 条件。最后,要使用 DateDeleted 过滤器获取相关的 ServiceBranch 实体,而不是 Include,只需使用投影(Select)。

并且在处理返回数据时,使用投影实体并忽略它们的导航属性。例如

var itemsToUpdate = _context.Set<Service>()
.Where(service => (service.ID == neededID || service.ParentServiceID == neededID)
&& service.DateDeleted == null)
.Select(service => new
{
Service = service,
ServiceBrances = service.ServiceBranches
.Where(branch => branch.DateDeleted == null),
});

foreach (var item in itemsToUpdate)
{
item.Service.DateDeleted = DateTime.Now;
foreach (var branch in item.ServiceBrances)
branch.DateDeleted = DateTime.Now;
}

关于c# - 是否可以将复杂的 EF Core ".Include"调用重写为 "Join"调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65747968/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com