如何在EF核心中将表与其自身连接?

时间:2019-04-26 09:51:07

标签: c# entity-framework linq-to-entities

我有一个表(“ ProductParameter”)将两个表(“ Product”和“ Parameter”)链接在一起,它具有字段Id,ProductId,ParameterId,Value,每个ParameterId都有一组[Value]我需要过滤

一一过滤一个ParameterId(其中pp.ParameterId = 4)后,首先由两个ParameterId(其中pp.ParameterId = 4或pp1.ParameterId = 2和pp1.Value ='Standard')收集。

示例:

+---------+-------------+------------+---------+
|     ID  |  ProductId  |ParameterId | Value   | 
+---------+-------------+------------+---------+
|     25  |    14       |    2       | Standard|
|     26  |    14       |    3       |  CK45   |
|     27  |    14       |    4       |   63    |
|     28  |    15       |    2       |   XXX   |
|     29  |    15       |    3       |  CK45   |
|     30  |    15       |    4       |   70    |
|     34  |    17       |    2       | Standard|
|     35  |    17       |    3       |  CK45   |
|     36  |    17       |    4       |   40    |
|     37  |    25       |    2       | Standard|
|     38  |    25       |    3       |  CK45   |
|     39  |    25       |    4       |   20    |     
+---------+-------------+------------+---------+-

应返回:

+-------+
| Value |  
+-------+
|   63  |   
|   40  | 
|   20  | 
+-------+

查询的逻辑如下:

 select distinct pp.Value from ProductParameters pp
 join ProductParameters pp1 on pp1.ProductId = pp.ProductId and 
 pp1.ParameterId = 2 and pp1.Value = 'Standard'
 where pp.ParameterId = 4

这是我在EF核心中的查询:

public async Task<IEnumerable<ProductParameter>> GetProductDiameters(long id, string param = "Standard")
{
    var value = await _context.ProductParameters
        .Include(p => p.Product)
        .ThenInclude(p => p.ProductParameters.Where(i => i.Value == param))
        .Where(p => p.ParameterId == id)
        .Distinct()
        .ToListAsync();

    return value;
}

引发异常:

  

ArgumentException:ThenInclude属性lambda表达式'p => {来自p.ProductParameters中的ProductParameter i,其中[[i] .Value == __param_0)选择[i]}'无效。该表达式应表示属性访问:“ t => t.MyProperty”。要定位在派生类型上声明的导航,请指定目标类型的显式键入的lambda参数,例如'(派生d)=> d.MyProperty'。

哪里出了错?

1 个答案:

答案 0 :(得分:0)

EF抱怨是因为您试图在。ThenInclude(..)语句中进行过滤

var value = await _context.ProductParameters
    .Include(p => p.Product)
    .ThenInclude(p => p.ProductParameters.Where(i => i.Value == param)) //<-- here
    .Where(p => p.ParameterId == id)
    .Distinct()
    .ToListAsync();

这是个问题,因为EF会使用EF内部的函数来确定应该紧急加载的表Include(..)ThenInclude(..)中的这些函数应该始终指向相关的表,并且没有其他:)

正确的查询方式如下:

var value = await _context.ProductParameters
    .Include(p => p.Product)
    .ThenInclude(p => p.ProductParameters) // <- removed the Where clause from here
    .Where(p => p.ParameterId == id)
    .Where(p => p.ProductParameters.Value == param)) //<- and added it here
    .Distinct()
    .ToListAsync();