【问题标题】:Entity Framework 7 Fluent API Doesn't Recognize IsOptional()Entity Framework 7 Fluent API 无法识别 IsOptional()
【发布时间】:2016-03-28 07:13:57
【问题描述】:

我目前正在使用实体框架 7 在我的 Asp.Net 5 项目中设置我的数据库,之前使用的是 EF 6,当我想让我的一些列可以为空时,我会使用:

modelBuilder.Entity<Article>().Property(t => t.ArticleDateModified).IsOptional();

但似乎IsOptional 不再是 EF7 的一部分,我想知道如何使用 EF7 实现相同的目标?

编辑: Marc 的回答确实是正确的,首先我认为它有效,因为我发现了类似IsOptional 的东西:

builder.Entity<Article>().Property(t => t.ArticleDateModified).IsRequired(false);

但是在没有它的情况下运行了一些测试后,它将数据库列设置为可为空,因为我在我的域模型中将其标记为可为空:

public DateTime? ArticleDateModified { get; set; }

另外值得注意的是,当我将DateTime 设为不可为空并使用IsRequired(false) 时,出现以下错误:

实体类型“Article”上的属性“ArticleDateModified”不能标记为可为空/可选,因为该属性的类型是“DateTime”,它不是可为空的类型。任何属性都可以标记为不可空/必需,但只有可空类型且不属于主键的属性才能标记为可空/可选。

所以,我想知道 IsRequired(false) 在这里有什么用处,如果我要做的就是让数据库列可以为空,就是让它在我的域类中可以为空?

【问题讨论】:

  • 我在下面回答了一些研究,但首先我应该问:您能否通过从 ArticleDateModified 中删除可空性并查看使用 IsRequired(false) 映射时数据库中生成的内容来测试假设?如果该列为空,无论他们在 10 月份做出什么决定,他们基于 6 月份的设计决定构建它的事实将胜过 10 月份的决定,至少在下一个主要版本发布之前,因为(技术上)RTM API 不会改变从 RC1 删除或禁用 API 将是一项重大更改。如果该列不为空,则它已被禁用。
  • @MarcL。我用答案编辑了问题。

标签: entity-framework entity-framework-core ef-fluent-api


【解决方案1】:

根据documentation page 中的注释,似乎取消了对以声明方式执行此操作的支持。也就是说:

不能将 CLR 类型不能包含 null 的属性配置为可选。实体框架将始终认为该属性是必需的。

从托管在 GitHub 上的项目的设计讨论中可以看出这是故意的,specifically

也就是说,标记为可空的属性支持空值,而标记为不可空的属性决不能包含空值。因此,将不允许将不可为空的 CLR 类型的属性标记为允许空值。 这与允许这样做的 EF6 行为不同。 [强调添加]


结果是,在 EF7 中,NULL 列严格意味着可以为空的映射属性。如果您的属性可以为空,则关联的列必须是 NULL,除非您使用 IsRequired 标记或配置它。


对 OP 编辑​​的回应

这很有趣,我最初没有看到关于 IsRequired(bool) API 的文档。我在某个六月的meeting notes 中发现了一个讨论点,指出这相当于EF6 的IsOptional()

.IsOptional() - 我们将通过调用 Required(false)
来提供此功能 .IsRequired() - 提供具有相同功能的Required()

尽管这是最初的意图,但取消支持的设计决定仍可追溯到 10 月。 (每次更新)尝试在不可为空的属性上设置 IsRequired(false) 会导致运行时错误,而不是被完全删除。

虽然现在是多余的,但如果不破坏有效代码就无法删除 API:它不是使用单独的 IsRequired(bool)IsRequired() 定义实现的,而是使用单个 IsRequired(bool required = true)。如果将其删除并替换为无参数版本,那将是一个重大更改。

【讨论】:

    【解决方案2】:

    Em... 将属性声明为可为空?

    class Article
    {
        public DateTime? ArticleDateModified {get;set;}
    }
    

    【讨论】:

      【解决方案3】:

      EntityFrameworkCore 中没有 IsOptional 但有 IsRequired 来做相反的事情。默认情况下,如果 C# 类型可以为空,则字段可以为空。

      此外,您不能使用 IsRequire(false) 方法设置作为另一个表的主键的外键。如果这样做,EntityframeworkCore 会抛出错误。

      public class User
      {
        public int Id {get; set;}
        public string Username {get;set}
        public byte Interest {get;set;}
        public Interest Interest {get;set;}
      }
      
      public class Interest
      {
        public byte Id {get;set;}
        public string Name {get;set;}
      }
      

      ApplicationDbContext

      protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
         base.OnModelCreating(modelBuilder);
      
         modelBuilder.Entity<User>()
           .property(u => u.InterestId)
           .isRequired(false);
      }
      

      错误

      实体类型“用户”上的属性“InterestId”不能标记为可空/可选,因为该属性的类型是“字节”,它不是可空类型。任何属性都可以标记为不可空/必需,但只有可空类型且不属于主键的属性才能标记为可空/可选。

      所以最好的方法是像这样使属性可以为空。

      public byte? InterestId {get; set;} 
      public Interest Interest {get; set;}
      

      【讨论】:

        猜你喜欢
        • 2014-07-28
        • 1970-01-01
        • 2017-04-04
        • 2017-05-23
        • 1970-01-01
        • 2018-02-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多