引用联结表引发ArgumentNullException'值不能为空'

时间:2018-10-02 22:08:49

标签: c# entity-framework linq .net-core entity-framework-core

我正在尝试通过食谱的配料表获取配料。

_context.RecipeIngredients
    .Include(rI => rI.Recipe)
        .ThenInclude(r => r.RecipeIngredients)
    .Where(rI => ingredients.Contains(rI.IngredientId))
    .GroupBy(rI => rI.Recipe)
    .Select(g => new
    {
        Recipe = g.Key,
        MatchingIngredients = (double)g.Count() / (double)g.Key.RecipeIngredients.Count(),
        g.Key.ComplexityTag,
        g.Key.TypeTag,
        g.Key.RecipeIngredients,
    })
    .OrderByDescending(r => r.MatchingIngredients)
    .Take(MaxAmountBestRecipes)
    .AsEnumerable()
    .Select(a => new RecipeDTO()
    {
        Title = a.Recipe.Title,
        Steps = a.Recipe.Steps,
        ComplexityTag = a.ComplexityTag?.Complexity,
        TypeTag = a.TypeTag?.Type,
        IngredientAmount = a.RecipeIngredients?.ToDictionary(rI => rI.Ingredient.Name, rI => rI.Quantity),
    })
    .ToList();

我发现它是由g.Key.RecipeIngredients引起的,但是我找不到任何解决方法来解决此问题。我尝试了eagar加载(如您所见)和延迟加载,两者均无效。我希望在linq中对db的一个查询中有解决方案。此外,更新后,它的工作原理是否与上一行相同:

IngredientAmount = a.RecipeIngredients?.ToDictionary(rI => rI.Ingredient.Name, rI => rI.Quantity)

编辑 我对linq查询进行了划分,在这里您遇到了以下引发ArgumentNullException的语句:

var tmp = _context.RecipeIngredients
            .Where(rI => ingredients.Contains(rI.IngredientId))
            .GroupBy(rI => rI.Recipe)
            .Select(g => new
            {
                Recipe = g.Key,
                MatchingIngredients = (double)g.Count() / (double)g.Key.RecipeIngredients.Count(),
                g.Key.ComplexityTag,
                g.Key.TypeTag,
                g.Key.RecipeIngredients
            })
            .ToList();

1 个答案:

答案 0 :(得分:0)

Include在您更改查询的形状时不起作用(例如,当您查询RecipeIngredient却投影到另一种类型时)。

我认为NULL唯一的问题是创建字典时的键选择器。由于Include不会为您做任何事情,因此ri.Ingredient将始终为NULL。在原始投影中添加Ingredient(并删除Include,因为它没有用):

_context.RecipeIngredients
    .Where( rI => ingredients.Contains( rI.IngredientId ) )
    .GroupBy( rI => rI.Recipe )
    .Select( g => new
    {
        Recipe = g.Key,
        MatchingIngredientCount = (double)g.Count() / (double)g.Key.RecipeIngredients.Count(),
        g.Key.ComplexityTag,
        g.Key.TypeTag,
        g.Key.RecipeIngredients,
        // this eager-loads the `Ingredient` entities
        //   EF will automatically wire them up to the `RecipeIngredient` entities
        //   if tracking is enabled
        Ingredients = g.Key.RecipeIngredients.Select( ri => ri.Ingredient ),
    } )
    .OrderByDescending(r => r.MatchingIngredients)
    .Take(MaxAmountBestRecipes)
    .ToArray()
    .Select( a = new ...
    {
        ...
        IngredientAmount = a.RecipeIngredients.ToDictionary(
            ri => ri.Ingredient.Name, // ri.Ingredient should now not be NULL
            ri => ri.Quantity )
    } );

编辑:如果在结果中不需要整个RecipeIngredientRecipe实体,只需在原始名称中投影所需的内容,并在第一个投影中使用RecipeIngredient s :

IngredientNamesAndQuantity = g.Key.RecipeIngredients.Select( ri => new
{
    ri.Quantity,
    ri.Ingredient.Name,
}

然后使用该投影来构建字典:

IngredientAmount = a.IngredientNamesAndQuantity.ToDictionary(
    at => at.Name,
    at => at.Quantity )