【问题标题】:EF Core handle shadow foreign key DeleteBehaviourEF Core 处理影子外键 DeleteBehaviour
【发布时间】:2020-01-03 00:13:54
【问题描述】:

我希望能够在删除影子外键属性的相关实体时更改行为。

public class Author
{
    public int AuthorId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<Book> Books { get; set; }
}
public class Book
{
    public int BookId { get; set; }
    public string Title { get; set; }
}

此设置将在图书实体中创建一个影子属性“AuthorId”,并且可以根据需要为空。 现在我希望当我删除一个作者时,所有相关书籍都将“AuthorId”外键设置为null。我怎样才能做到这一点?

【问题讨论】:

    标签: c# entity-framework entity-framework-core


    【解决方案1】:

    只需在 DbContext 中配置删除行为:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    
        modelBuilder.Entity<Book>()
            .HasOne<Author>()
            .WithMany(a => a.Books)
            .HasForeignKey("AuthorId")
            .OnDelete(DeleteBehavior.SetNull);
    
        base.OnModelCreating(modelBuilder);
    }
    

    例如:

    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Diagnostics;
    using Microsoft.Extensions.Logging;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace EfCore3Test
    {
    
    
        public class Author
        {
            public int AuthorId { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public ICollection<Book> Books { get; } = new HashSet<Book>();
        }
        public class Book
        {
            public int BookId { get; set; }
            public string Title { get; set; }
        }
    
        public class Db : DbContext
        {
    
    
            public DbSet<Author> Authors { get; set; }
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
    
                modelBuilder.Entity<Book>()
                    .HasOne<Author>()
                    .WithMany(a => a.Books)
                    .HasForeignKey("AuthorId")
                    .OnDelete(DeleteBehavior.SetNull);
    
                base.OnModelCreating(modelBuilder);
            }
            public static readonly ILoggerFactory MyLoggerFactory
                = LoggerFactory.Create(builder => { builder.AddConsole(); });
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder.UseSqlServer("Server=localhost;Database=EFCore3Test;Integrated Security = true", a => a.UseRelationalNulls(true))
                              .ConfigureWarnings(c => c.Log((RelationalEventId.CommandExecuting, LogLevel.Information)))
                              .UseLoggerFactory(MyLoggerFactory);
                base.OnConfiguring(optionsBuilder);
            }
    
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                using (var db = new Db())
                {
                    db.Database.EnsureDeleted();
                    db.Database.EnsureCreated();
    
                    var a = new Author();
                    for (int i = 0; i < 10; i++)
                    {
    
                        var b = new Book();
                        a.Books.Add(b);
                    }
    
                    db.Authors.Add(a);
                    db.SaveChanges();
                }
    
    
    
    
    
                using (var db = new Db())
                {
                    var a = db.Authors.First();
                    db.Authors.Remove(a);
                    db.SaveChanges();
    
                }
            }
        }
    }
    

    对于 SQL Server,这是生成的 Book 表:

      CREATE TABLE [Book] (
          [BookId] int NOT NULL IDENTITY,
          [Title] nvarchar(max) NULL,
          [AuthorId] int NULL,
          CONSTRAINT [PK_Book] PRIMARY KEY ([BookId]),
          CONSTRAINT [FK_Book_Authors_AuthorId] FOREIGN KEY ([AuthorId]) REFERENCES [Authors] ([AuthorId]) ON DELETE SET NULL
      );
    

    【讨论】:

    • OnDelete(DeleteBehavior.SetNull),是EF置null还是使用关系数据库的级联删除机制?
    • 关系型数据库,至少对于支持 ON DELETE SET NULL 的 SQL Server 而言。
    • 谢谢,我太习惯了 lambda,我忘了我可以使用字符串。
    • 你好,@DavidBrowne-Microsoft,我有与 OP 完全相同的场景,但是当我尝试配置我的影子属性时,我收到一个错误,上面写着 You are configuring a relationship between 'File' and 'Rim' but have specified a foreign key on 'RimId'. The foreign key must be defined on a type that is part of the relationship. 你有什么想法吗?我收到这个错误?我正在使用 EF Core 5.0
    • 请在新问题中发布您的模型和错误详细信息。
    猜你喜欢
    • 2021-11-14
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-23
    • 2020-10-18
    • 1970-01-01
    相关资源
    最近更新 更多