【问题标题】:Using EF Core HasQueryFilter in entity configuration to map nullable db columns to non-nullable properties?在实体配置中使用 EF Core HasQueryFilter 将可为空的数据库列映射到不可为空的属性?
【发布时间】:2021-04-17 12:38:50
【问题描述】:

设置:

在 MS SQL Server 数据库中(注意:由外部提供商管理,我们无法更改架构)我们有一个可以为空的表列。同时,在我们的实体模型中,我们故意指定映射到该列的属性不可为空(因为我们想完全忽略该属性的所有null 情况,也不想在我们的代码)。

当然,在运行时,当 EF Core 尝试将可空数据映射到不可空属性时,这会在查询执行时导致异常。

因此我们认为,我们可以使用 EF Core 的 HasQueryFilter,它“指定一个 LINQ 谓词表达式,该表达式将自动应用于针对此实体类型的任何查询”。这个想法是,通过使用HasQueryFilter,我们可以忽略映射到该列的属性为空的所有情况。这样,在执行查询时,可以保证在 EF Core 进行映射之前,该列的所有具有空值的行都从结果集中剥离。

这是示例实体配置:

namespace Foo.Bar.Baz
{
  public class MyEntity : IEntityTypeConfiguration<MyEntity>
  {
    public int Id { get; set; }
    public int Foo { get; set; }

    public void Configure(EntityTypeBuilder<MyEntity> builder)
    {
      builder.ToTable("myTable");
      builder.HasKey(e => e.Id);
      builder.HasQueryFilter(e =>
        e.Foo != null // <-- ignoring any datasets with Foo being null
      );
    }
  }
}

问题:

当通过例如执行对该实体的查询时...

DbContext.Set<MyEntity>().ToList();

....HasQueryFilter 已执行,但 e.Foo != null 部分似乎已从 SQL 查询的 WHERE 部分中删除,因为 EF Core 的优化机制认为这是一个“始终为真”的表达式。

问题:

任何想法如何强制 EF Core 执行 .HasQueryFilter 的过滤器部分或如何配置实体以实现我们上面描述的内容?

附:请注意,我们知道我们可以添加另一个服务层来执行另一个映射,或者我们可以引入另一个属性来正确映射列。但我们想避免这种情况,并通过实体类型构建器配置透明地处理这种情况。

【问题讨论】:

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


    【解决方案1】:

    看起来 EF 将优化查询过滤器以删除对所需属性的任何非空检查。如果您从属性中删除 [Required] 属性并仅使用查询过滤器,它应该可以工作。或者保留[Required] 属性,以便您可以在运行时使用它,但在模型配置中覆盖它。

    builder.Property(e => e.Foo).IsRequired(false);
    

    【讨论】:

    • 感谢您的回答,不幸的是,我在启动应用程序时收到CLR/System.InvalidOperationException:实体类型“MyEntity”上的属性“Foo”不能标记为可为空/可选,因为该属性的类型是'int',它不是可空类型。任何属性都可以标记为不可空/必需,但只有可空类型且不属于主键的属性才能标记为可空/可选。'
    猜你喜欢
    • 2012-04-22
    • 1970-01-01
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2023-02-11
    • 2012-06-15
    相关资源
    最近更新 更多