查询需要在.ThenInclude之后使用.Where子句进行过滤

如何解决查询需要在.ThenInclude之后使用.Where子句进行过滤

我使用以下查询根据需要过滤我的BranchId。

String json = "{...}";
JSONObject object = (JSONObject) JSONValue.parse(jsonString2);        
readJSON(object);

上面的表达式创建了以下SQL,我认为var query = await _dbContext.TargetItems .Include(i => i.BranchTargetItem) .ThenInclude(i => i.BranchTarget) .Where(x=> x.BranchTargetItem.Any(x=> x.BranchTarget.Any(x=> x.BranchId.Equals("9417")))) .ToListAsync(cancellationToken); 导致了这些.Any()语句

Left Join

但是我想将SELECT * FROM PERF_TARGET_ITEMS "p" LEFT JOIN (SELECT * FROM PERF_BRANCH_TARGET_ITEMS "p0" LEFT JOIN PERF_BRANCH_TARGETS "p1" ON "p0".BTI_ID = "p1".BT_BRANCH_TARGET_ITEM_ID) "t" ON "p".TI_ID = "t".BTI_ITEM_TARGET_ITEM_ID WHERE EXISTS (SELECT 1 FROM PERF_BRANCH_TARGET_ITEMS "p2" WHERE ("p".TI_ID = "p2".BTI_ITEM_TARGET_ITEM_ID) AND EXISTS (SELECT 1 FROM PERF_BRANCH_TARGETS "p3" WHERE ("p2".BTI_ID = "p3".BT_BRANCH_TARGET_ITEM_ID) AND ("p3".BT_BRANCH_ID = N'9417'))) ORDER BY "p".TI_ID,"t".BTI_ID,"t".BT_ID 转换为Left Join,如下所示,

Inner Join

我想返回 SELECT * FROM WESTCORE.PERF_BRANCH_TARGET_ITEMS "p" INNER JOIN WESTCORE.PERF_PERIODS "p0" ON "p".BTI_ITEM_PERIOD_ID = "p0".P_ID INNER JOIN WESTCORE.PERF_TARGET_ITEMS "p1" ON "p".BTI_ITEM_TARGET_ITEM_ID = "p1".TI_ID LEFT JOIN (SELECT * FROM WESTCORE.PERF_BRANCH_TARGETS "p2" WHERE "p2".BT_BRANCH_ID = '9417') "t" ON "p".BTI_ID = "t".BT_BRANCH_TARGET_ITEM_ID WHERE ((SELECT COUNT(*) FROM WESTCORE.PERF_BRANCH_TARGETS "p3" WHERE ("p".BTI_ID = "p3".BT_BRANCH_TARGET_ITEM_ID) AND ("p3".BT_BRANCH_ID = '9417')) > 0) ORDER BY "p".BTI_ID,"p0".P_ID,"p1".TI_ID,"t".BT_ID 并包含其关系实体(TargetItems> BranchTargetItems> BranchTargets)

TargetItems

这是我的关系,

//TargetItem.cs
    ...
    public virtual ICollection<BranchTargetItem> BranchTargetItem { get; set; }
    ...

//BranchTargetItem.cs
    ...
    public virtual ICollection<BranchTarget> BranchTarget { get; set; }
    ...

//BranchTarget.cs
    ...
    public virtual BranchTargetItem BranchTargetItem { get; set; }
    ...

编辑:

我要将此过滤器//TargetItemConfiguration.cs builder.HasMany(x => x.BranchTargetItem).WithOne(x => x.TargetItem).HasForeignKey(x => x.ItemTargetItemId).IsRequired(); //BranchTargetItemConfiguration.cs builder.HasMany(x => x.BranchTarget).WithOne(x => x.BranchTargetItem).HasForeignKey(x => x.BranchTargetItemId).IsRequired(); 添加到以下查询中,

.ThenInclude( bti=> bti.BranchTarget).Where( bt=> bt.BranchId.Equals("9417"))

编辑:

我已使用以下查询解决了该问题,但我仍在寻找理想的解决方案

    var query = await _dbContext.TargetItems
        .Include(ti => ti.BranchTargetItem)
        .ThenInclude( bti=> bti.BranchTarget)
        .ToListAsync(cancellationToken);

编辑:

我也尝试过这种方法,在这里 var targetItems = await _dbContext.TargetItems .Include(ti => ti.BranchTargetItem) .ThenInclude(bti => bti.BranchTarget) .ToListAsync(cancellationToken); foreach (TargetItem ti in targetItems) { foreach (BranchTargetItem bti in ti.BranchTargetItem) { bti.BranchTarget = bti.BranchTarget.Where(bt => bt.BranchId.Equals(branchId)).ToList(); } } 的TargetItems实体与其自身具有一对多关系,当我在下面的代码中应用时,子节点为空。它只返回第一个节点。

[DataMember] public virtual ICollection<TargetItem> TargetItems { get; set; }

解决方法

您不必担心AnyAny-> EXISTS。您的问题是Include,它转换为LEFT OUTER JOIN。因此,您需要额外的过滤,如下所示:

var query = await _dbContext.TargetItems
.Include(i => i.BranchTargetItem)
.Where(e => e.BranchTargetItem != null) //added filtration
.ThenInclude(i => i.BranchTarget)
.Where(e => e.BranchTarget != null) //added filtration
.Where(x => x.BranchTargetItem.Any(x => x.BranchTarget.Any(x => x.BranchId.Equals("9417"))))
.ToListAsync(cancellationToken);
,

如果您需要INNER JOIN,则需要使用Join。可以优化预期的SQL查询,并将其简化为:

SELECT *
FROM 
    WESTCORE.PERF_BRANCH_TARGET_ITEMS p
INNER JOIN WESTCORE.PERF_PERIODS p0 ON p.BTI_ITEM_PERIOD_ID = p0.P_ID
INNER JOIN WESTCORE.PERF_TARGET_ITEMS p1 ON p.BTI_ITEM_TARGET_ITEM_ID = p1.TI_ID
INNER JOIN WESTCORE.PERF_BRANCH_TARGETS p2 ON p.BTI_ID = p2.BT_BRANCH_TARGET_ITEM_ID
WHERE 
    p2.BT_BRANCH_ID = '9417'
ORDER BY 
    p.BTI_ID,p0.P_ID,p1.TI_ID,p2.BT_BRANCH_TARGET_ITEM_ID

要应用此功能,您可以执行以下操作:

var query = await _dbContext.BranchTargetItem
            .Join(_dbContext.TargetItems,bti => bti.BranchId,ti  => ti.BranchId,(bti,ti) => new { TargetItems = ti,BranchTargetItem = bti })
            .Join(_dbContext.BranchTarget,ti => ti.TargetItems.BranchId,bt => bt.BranchId,BranchTarget = bt })           
            .Where(x=> x.TargetItems.BranchId.Equals("9417"))
            .ToListAsync(cancellationToken);

查询本身需要进行测试并调整为正确的实体。

,

如果仅希望与where子句匹配的BranchTarget,则需要使查询的主要详细信息记录为准,然后包括其父记录;

var query = await _dbContext.BranchTarget
    .Where(x => x.BranchId.Equals("9417"))
    .Include(t => t.BranchTargetItems)
    .ThenInclude(t => t.TargetItems)
    .ToListAsync(cancellationToken);
,

原始问题的答案

我使用以下查询根据需要过滤我的BranchId。

java -Xdock:name=Alfabet

但是我想将“左联接”转换为“内联接[...]

要解决您的原始问题,一个简单的解决方案是颠倒您的包含项的顺序:

var query = await _dbContext.TargetItems                
.Include(i => i.BranchTargetItem)
.ThenInclude(i => i.BranchTarget)                
.Where(x=> x.BranchTargetItem.Any(x=> x.BranchTarget.Any(x=> x.BranchId.Equals("9417"))))
.ToListAsync(cancellationToken);

这将使用var branchTargets = context.BranchTargets .Include(bt => bt.BranchTargetItem) .ThenInclude(bti => bti.TargetItem) .Where(bt => bt.BranchId == "9417") .ToList(); 并返回INNER JOIN实体,您可以从其中通过BranchTarget进入TargetItem实体:

branchTargets[0].BranchTargetItem.TargetItem

如果您不希望查询返回SELECT [p].[BT_BRANCH_TARGET_ITEM_ID],[p].[BT_BRANCH_ID ],[p].[BT_ID],[p0].[BTI_ID],[p0].[BTI_ITEM_TARGET_ITEM_ID],[p1].[TI_ID] FROM [PERF_BRANCH_TARGETS ] AS [p] INNER JOIN [PERF_BRANCH_TARGET_ITEMS] AS [p0] ON [p].[BT_ID] = [p0].[BTI_ID] INNER JOIN [PERF_TARGET_ITEMS] AS [p1] ON [p0].[BTI_ITEM_TARGET_ITEM_ID] = [p1].[TI_ID] WHERE [p].[BT_BRANCH_ID ] = N'9417' 作为根实体,则可以执行以下操作:

BranchTarget

这里是一个可以正常运行的示例控制台项目,它演示了这种方法:

var targetItems = context.BranchTargets                
    .Include(bt => bt.BranchTargetItem)
        .ThenInclude(bti => bti.TargetItem)                
    .Where(bt => bt.BranchId == "9417")
    .AsEnumerable()
    .Select(bt => bt.BranchTargetItem.TargetItem)
    .ToList();

有关递归导航属性的后续问题的答案

使用传统方法时,通常有以下选择:

  • 如果您知道要查询递归结构的层次数,只需添加其他using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace IssueConsoleTemplate { public class TargetItem { public int TargetItemId { get; set; } public ICollection<BranchTargetItem> BranchTargetItem { get; set; } } public class BranchTargetItem { public int BranchTargetItemId { get; set; } public int ItemTargetItemId { get; set; } public TargetItem TargetItem { get; set; } public ICollection<BranchTarget> BranchTarget { get; set; } } public class BranchTarget { public int BranchTargetId { get; set; } public string BranchId { get; set; } public int BranchTargetItemId { get; set; } public BranchTargetItem BranchTargetItem { get; set; } } public class Context : DbContext { public DbSet<TargetItem> TargetItems { get; set; } public DbSet<BranchTargetItem> BranchTargetItems { get; set; } public DbSet<BranchTarget> BranchTargets { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer( @"Data Source=.\MSSQL14;Integrated Security=SSPI;Initial Catalog=So63636238") .UseLoggerFactory( LoggerFactory.Create( b => b .AddConsole() .AddFilter(level => level >= LogLevel.Information))) .EnableSensitiveDataLogging() .EnableDetailedErrors(); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<TargetItem>( entity => { entity.ToTable("PERF_TARGET_ITEMS"); entity.Property(e => e.TargetItemId) .HasColumnName("TI_ID"); entity.HasMany(x => x.BranchTargetItem) .WithOne(x => x.TargetItem) .HasForeignKey(x => x.ItemTargetItemId); entity.HasData( new TargetItem {TargetItemId = 1},new TargetItem {TargetItemId = 2},new TargetItem {TargetItemId = 3}); }); modelBuilder.Entity<BranchTargetItem>( entity => { entity.ToTable("PERF_BRANCH_TARGET_ITEMS"); entity.Property(e => e.BranchTargetItemId) .HasColumnName("BTI_ID"); entity.Property(e => e.ItemTargetItemId) .HasColumnName("BTI_ITEM_TARGET_ITEM_ID"); entity.HasMany(x => x.BranchTarget) .WithOne(x => x.BranchTargetItem) .HasForeignKey(x => x.BranchTargetItemId); entity.HasData( new BranchTargetItem {BranchTargetItemId = 11,ItemTargetItemId = 1},new BranchTargetItem {BranchTargetItemId = 22,ItemTargetItemId = 2},new BranchTargetItem {BranchTargetItemId = 33,ItemTargetItemId = 3},new BranchTargetItem {BranchTargetItemId = 41,ItemTargetItemId = 1}); }); modelBuilder.Entity<BranchTarget>( entity => { entity.ToTable("PERF_BRANCH_TARGETS "); entity.Property(e => e.BranchTargetItemId) .HasColumnName("BT_ID"); entity.Property(e => e.BranchId) .HasColumnName("BT_BRANCH_ID "); entity.Property(e => e.BranchTargetId) .HasColumnName("BT_BRANCH_TARGET_ITEM_ID"); entity.HasData( new BranchTarget {BranchTargetId = 100,BranchId = "9417",BranchTargetItemId = 11},new BranchTarget {BranchTargetId = 200,BranchTargetItemId = 41},new BranchTarget {BranchTargetId = 300,BranchId = "1234",BranchTargetItemId = 22}); }); } } internal static class Program { private static void Main() { using var context = new Context(); context.Database.EnsureDeleted(); context.Database.EnsureCreated(); // Your original query: // // var result = context.TargetItems // .Include(ti => ti.BranchTargetItem) // .ThenInclude(bti => bti.BranchTarget) // .Where(ti => ti.BranchTargetItem.Any(bti => bti.BranchTarget.Any(bt => bt.BranchId.Equals("9417")))) // .ToList(); // // Debug.Assert(result.Count == 2); // Debug.Assert(result[0].BranchTargetItem != null); // Debug.Assert(result[0].BranchTargetItem.Count == 2); // Debug.Assert(result[0].BranchTargetItem.First().BranchTargetItemId == 11); // Debug.Assert(result[0].BranchTargetItem.First().BranchTarget != null); // Debug.Assert(result[0].BranchTargetItem.First().BranchTarget.Count == 1); var result = context.BranchTargets .Include(bt => bt.BranchTargetItem) .ThenInclude(bti => bti.TargetItem) .Where(bt => bt.BranchId == "9417") .AsEnumerable() .Select(bt => bt.BranchTargetItem.TargetItem) .OrderBy(bt => bt.TargetItemId) .ToList(); Debug.Assert(result.Count == 2); Debug.Assert(result[0].BranchTargetItem != null); Debug.Assert(result[0].BranchTargetItem.Count == 2); Debug.Assert(result[0].BranchTargetItem.First().BranchTargetItemId == 11); Debug.Assert(result[0].BranchTargetItem.First().BranchTarget != null); Debug.Assert(result[0].BranchTargetItem.First().BranchTarget.Count == 1); } } } 子句即可。
  • 遍历返回的项目并执行其他查询。
  • 只是渴望加载所有.ThenInclude(ti => ti.TargetItems)实体。

以下完全正常工作的示例项目演示了几种方法:

TargetItem
,

您可以使用略有不同的语法(linq-to-sql):

var query = (
    from ti in _dbContext.TargetItems
    join bti in _dbContext.BranchTargetItem on ti.Id = bti.ItemTargetItemId
    join bt in _dbContext.BranchTarget on bti.Id = bt.BranchTargetItemId
    where bt.BranchId.Equals("9417")
    select new {
           ti,btis = ti.BranchTargetItem,bts  = ti.BranchTargetItem.SelectMany(x=> x.BranchTarget)
       }
).ToListAsync();

这将在单次调用db时加载任何所需内容,而不会包含魔术。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-