在Entity Framework Core 1(EF7)中,与.HasOptional等效的内容是什么?

74

考虑两个类。

public class File
{
    [Key]
    public string Id { get; set; }

    public string Message_Id { get; set; }

    internal Message Message { get; set; }
}

public class Message 
{
    [Key]
    public string Id { get; set; }       
}

在EF6中,对于N:1..0关系,有这个流畅API。

modelBuilder.Entity<File>()
            .HasOptional(e => e.Message ).WithMany().HasForeignKey(e => e.Message_Id);

在Entity Framework Core 1中等效的是什么?

谢谢

3个回答

122

在EF 7中,你将无法找到一个等效的方法。按照惯例,如果CLR类型可以包含null,则属性将被配置为可选项。因此,决定关系是可选还是必填的是FK属性是否分别为可空

简而言之,由于你的Message_Id FK属性是string,它已经接受null值,所以如果你使用以下Fluent Api配置:

modelBuilder.Entity<File>()
            .HasOne(s => s.Message)
            .WithMany()
            .HasForeignKey(e => e.Message_Id)

EF会将您的关系配置为可选(或按要求的N:0..1)。

如果您的FK属性是值类型,例如int,则应将其声明为可空类型(int?)。

我还注意到您现在有一个访问修饰符为internal的导航属性。您应该始终将实体属性声明为public


只是补充一点观察:即使类型本身可为空,如果属性上有[Required]注释,EF也会将关系配置为必需的。 - davidmdem
1
抱歉,我会在未来采纳您的建议。 - ocuenca
4
你应该总是将实体属性声明为公共的,这是不正确的。如果你有一些东西不想在类外暴露,你可以将其声明为“protected internal”,这样Entity Framework仍然可以使用该属性,但它不能被其他任何东西访问。 - krillgar
1
HasOne()是HasOptional()的等价方法吗? - Karthic G
3
我发现在.Net 6.0和EF Core 7.0中使用int?对我没用,因为它总是创建一个非可空字段,尽管使用了可空的int。我不得不在配置实体时使用builder.Property(p => p.FieldName).IsRequired(false)来强制设置,并且这样做后它就可以工作了。 - Mark
显示剩余8条评论

16

在接受的答案补充一点,如果你的属性不能配置为可空(例如,如果你正在处理一个拆分表的情况,其中该属性是主键),添加IsRequired(false)将使连接变为可选(LEFT)。

像这样:

modelBuilder.Entity<File>()
    .HasOne(s => s.Message)
    .WithMany()
    .HasForeignKey(e => e.Message_Id)
    .IsRequired(false)

谢谢!我需要这个来将主键用作0..1关系的外键。我无法使主键可为空,所以这是我需要的解决方案。 - djalonso
谢谢。这应该是答案,因为它简单易懂。 - Thomas.Benz

12

在 EF Core 中,您可以使用两种方法来关联两个表:

  • OnModelCreating 中:

  • protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);            
    
        modelBuilder.Entity<File>()
                    .HasOne(c => c.Message)
                    .WithOne()
                    .HasForeignKey(c => c.MessageId)                           
    }
    
  • 创建新的类 FileConfiguration 并在 OnModelCreating 中调用它:

  • public class FileConfiguration : IEntityTypeConfiguration<File>
    {
        public void Configure(EntityTypeBuilder<File> builder)
        {           
            builder.ToTable("File");            
    
            // Id
            builder.HasKey(c => c.Id);
            builder.Property(c => c.Id)
                   .ValueGeneratedOnAdd();
    
            // Message
            builder.HasOne(c => c.Message)
                   .WithOne(c => c.File)
                   .HasForeignKey<Message>(c => c.MessageId)
                   .OnDelete(DeleteBehavior.Restrict);
        }
    }
    

    并且在 OnModelCreating 方法里添加以下代码:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    
        modelBuilder.ApplyConfiguration(new FileConfiguration());                                       
    }
    

我可以怎么做以进行自我引用。 - Kamran Shahid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接