1

假设我们在 EfCore 中有这些实体......

public class Entity
{
    public int Id { get; set; }
    public decimal Rate { get; set; }
    // ... omitted for brevity
    public int? NavigationPropertyId { get; set; }
    public NavigationProperty? NavigationProperty { get; set; }
    // ... omitted for brevity
}

public class NavigationProperty
{
    public int Id { get; set; }
    public int AnotherNavigationPropertyId { get; set; }
    // ... omitted for brevity
}

...我们希望得到相同的平均值 RateEntitiesAnotherNavigationProperty

我尝试的 efcore 查询抛出“System.InvalidOperationException:Nullable 对象必须有一个值”。

from entity in _context.Entities
group entity by entity.NavigationProperty.AnotherNavigationPropertyId 
    into entitiesByAnotherNavigationProperty
orderby entitiesByAnotherNavigationProperty.Key
select new 
{
    AnotherNavigationPropertyId = entitiesByAnotherNavigationProperty.Key,
    AverageRate = entitiesByAnotherNavigationProperty.Average(a => a.Rate)
}

我知道 EfCoreToQueryString()在查询返回时已成功翻译

SELECT [p].[AnotherNavigationPropertyId], AVG([a].[Rate]) AS [AverageRate]
FROM [Entities] AS [a]
LEFT JOIN [NavigationProperties] AS [p] ON [a].[NavigationPropertyId] = [p].[Id]
GROUP BY [p].[AnotherNavigationPropertyId]
ORDER BY [p].[AnotherNavigationPropertyId]

在数据库上运行时正确返回我需要的结果

如何提示 EfCore 传播 null 导航属性?(因为表达式树不能包含空传播?.运算符)

4

1 回答 1

0

这是因为 C# 和 SQL 空语义之间的差异。

在 SQL 查询中,每个值都可以null,即使源列不允许null。事实上,没有可空或不可空类型之类的东西,只有not null约束。而在 LINQ 查询中,可空性由属性的静态类型确定。

很快,我们在 CLR 和 SQL 查询值类型之间发生了冲突。为了解决它,您必须让 CLR 知道表达式类型实际上是可以为空的,即使它推断的 CLR 类型不是。由于?.表达式树中不允许使用,因此您必须为此使用cast运算符。唯一的缺点是您需要知道确切的属性类型(不能使用正常的类型推断)。

话虽如此,在来自问题的示例查询中,这是int?在此处添加演员表的问题

group entity by (int?)entity.NavigationProperty.AnotherNavigationPropertyId
于 2020-09-26T09:22:29.393 回答