查找一个列表中具有与另一个对象列表中的属性匹配的属性的所有对象

Posted

技术标签:

【中文标题】查找一个列表中具有与另一个对象列表中的属性匹配的属性的所有对象【英文标题】:Find all objects in one list that have a property that matches a property in another list of objects 【发布时间】:2020-06-09 09:47:54 【问题描述】:

问题

我正在尝试使用另一个表(基于 ModelB)查询一个表(基于 ModelA)。对于此示例,这些模型进行了简化。我需要将结果保留为IQueryable,因此更改为EnumerableList 不是选项。不过,我尝试添加.ToList(),但得到了同样的错误。

MyIds 从一个列表中拉到一个字符串列表中(以便使用Contains())不是一种选择,因为可能有太多MyIds(> 40k)会导致错误指示资源耗尽的操作,我猜是指 RAM。

错误

InvalidOperationException:无法翻译 LINQ 表达式 ...。以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估。

模型A

public class ModelA

    public string MyId  get; set; 
    public string MyName  get; set; 

模型B

public class ModelB

    public string MyId  get; set; 
    public string MyName  get; set; 

尝试

var results = context.ModelA
            .Where(a => ModelB.All(b => b.MyId == a.MyId));

什么方法可以成功?

【问题讨论】:

var results = context.ModelA.Where(a => ModelB.Any(b => b.MyId == a.MyId)); 是的,Any 是正确的方法。谢谢。 【参考方案1】:

您可以尝试检查第二个列表是否包含匹配 ID 的“Any()”

var results = context.ModelA
        .Where(a => ModelB.Where(b => b.MyId == a.MyId).Any());

或者您可能想尝试加入

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/join-clause

var results = context.ModelA
    .Where(a => ModelB.
            Any(b => b!= null  && b.id != null 
                  && a!=null && a.id!==null && 
                  b.MyId == a.MyId));

我有 Select 而不是 Where 并且我检查了空值

【讨论】:

两个选项都有效,但Join 选项比Where 慢,所以我选择了更快的选项。我必须为ModelB 创建一个视图,以便可以从与ModelA 相同的上下文访问它(它们位于不同的数据库中)。从一开始就选择你的答案。【参考方案2】:

有一些方法可以实现,这里有两种方法供大家参考:

var result = (from a in context.ModelA
                      join b in context.ModelB
                      on a.MyId equals b.MyId
                      select a);

或者你可以试试这个方法:

 var result = context.ModelA.Join(_context.ModelB,
                        x => x.MyId,
                        y => y.MyId,
                       (x, y) => x);

您可以参考this link了解更多详情。

【讨论】:

谢谢,我试过Join,它成功了。由于某种原因,它比Where 慢一点。我还必须为ModelB 创建一个视图,以便可以从与ModelA 相同的上下文访问它(它们位于不同的数据库中)。【参考方案3】:

你可以试试这个:

var results = ctx
    .ModelAs
    .Where(ma => ctx.ModelBs.Any(mb => mb.MyId == ma.MyId));

我用过你的模型,这是我的DbContext

public class MockContext : DbContext

    public MockContext(DbContextOptions<MockContext> options)
        : base(options)
     

    public DbSet<ModelA> ModelAs  get; set; 
    public DbSet<ModelB> ModelBs  get; set; 

我用来测试的数据是:

模型A:

MyId | MyName

1 Nettie Koch 
2 Karl Kuvalis 
3 Marcus Weissnat 
4 Shannon Hettinger 
5 Wilma Kuvalis 
6 Benny Brown 
7 Amanda Maggio 
8 Claude Kohler 
9 Dawn Ritchie 
10 Alan Ruecker

模型B:

MyId | MyName

5 Francis Konopelski 
6 Mandy Yost 
7 Marsha Parisian 
8 Crystal Mayer 
9 Sergio Crona 
10 Kenny Rice 
11 Levi Gutkowski 
12 Brandon Haley 
13 Jan Kunze 
14 Rafael Blanda 

结果:

MyId | MyName

5 Wilma Kuvalis 
6 Benny Brown 
7 Amanda Maggio 
8 Claude Kohler 
9 Dawn Ritchie 
10 Alan Ruecker 

【讨论】:

很好,彻底的答案,谢谢。我必须为ModelB 创建一个视图,以便可以从与ModelA 相同的上下文访问它(它们位于不同的数据库中)。【参考方案4】:

您可能正在查看Any(),如下所示

var results = context.ModelA.Where(a => ModelB.Any(b => b.MyId == a.MyId));

【讨论】:

正如我在评论部分提到的。您可以使用Any() 来实现它。如果对你有帮助,别忘了接受我的回答。

以上是关于查找一个列表中具有与另一个对象列表中的属性匹配的属性的所有对象的主要内容,如果未能解决你的问题,请参考以下文章

Grails:查找具有列表属性的对象,其中包含具有给定属性值的对象

在 Python 元组列表中查找重复项

根据匹配的对象属性从列表创建列表

需要 c# 正则表达式将逗号列表中的任何单词与另一个字符串中的任何单词匹配

Java,在对象列表中搜索?

AngularJS - 在下拉列表中设置选定值,其中值与另一个对象匹配