简体   繁体   中英

EF Core handle shadow foreign key DeleteBehaviour

I want to be able to change the behaviour when deleting a related entity for a shadow foreign key property.

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; }
}

This setup will create a shadow property "AuthorId" in the book entity and is nullable as I want. Now I'd like that when I delete an author, all the related books will set the "AuthorId" foreign key to null . How can I achieve this?

Just configure the delete behavior in the DbContext:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{

    modelBuilder.Entity<Book>()
        .HasOne<Author>()
        .WithMany(a => a.Books)
        .HasForeignKey("AuthorId")
        .OnDelete(DeleteBehavior.SetNull);

    base.OnModelCreating(modelBuilder);
}

eg:

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();

            }
        }
    }
}

For SQL Server this is the resulting Book table:

  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
  );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM