Skip to content

Foreign keys recreated each time a migration is added, principal object not accessible from the dependent object #4257

@ghost

Description

Hi. I created a very simple model with a principal entity (Author) and a dependent entity (Book) with a foreign key. I observe two strange behaviours (bug? or bad understanding of EF usage from my part?) :

  • The first migration is performed correctly, but any subsequent execution of dnx ef migrations add results in a new migration that recreates the foreign key.
  • EntityFramework returns null when I perform a book.Author query (even though the author actually exists in the database - cf. test case 1 below), except if I have already previously loaded the author, manually, within the same instance of the DbContext (cf. test case 2 below).

I'm using Entity Framework 7.0.0-rc1-final with Microsoft SQL Server 2014. DNX version : 1.0.0-rc1-update1. See my project.json below.

My model:

    public class Author
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class Book
    {
        public int Id { get; set; }
        public string Title { get; set; }

        public int AuthorId { get; set; }
        public Author Author { get; set; }
    }

    public class EssaisContext : DbContext
    {
        public DbSet<Author> Authors { get; set; }
        public DbSet<Book> Books { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Data Source=localhost;Integrated Security=true;Initial Catalog=Essais");
        }
    }

My test cases:

        public static void Main(string[] args)
        {
            // Populate database
            const string BOOK_TITLE = "Fables";
            const string AUTHOR_NAME = "La Fontaine";

            using (var db = new EssaisContext())
            {
                var author = db.Authors.Where(q => q.Name == AUTHOR_NAME).FirstOrDefault();
                if (author == null)
                {
                    author = new Author { Name = AUTHOR_NAME };
                    db.Authors.Add(author);
                }

                if (! db.Books.Any(q => q.Title == BOOK_TITLE))
                    db.Books.Add(new Book { Author = author, Title = BOOK_TITLE });

                db.SaveChanges();
            }

            // Test case 1 (fails)
            using (var db = new EssaisContext())
            {
                var book = db.Books.Where(q => q.Title == BOOK_TITLE).FirstOrDefault();
                Console.WriteLine("1) book.Author: " + (book.Author != null ? "not null <== OK" : "null <== NOT OK"));

                // Writes: 1) author.Book: null <== NOT OK
            }

            // Test case 2 (succeeds)
            using (var db = new EssaisContext())
            {
                var author = db.Authors.Where(q => q.Name == AUTHOR_NAME).FirstOrDefault();

                var book = db.Books.Where(q => q.Title == BOOK_TITLE).FirstOrDefault();
                Console.WriteLine("2) book.Author: " + (book.Author != null ? "not null <== OK" : "null <== NOT OK"));

                // Writes: 2) author.Book: not null <== OK
            }

            Console.WriteLine("Press any key to terminate...");
            Console.ReadKey();
        }

Every execution of dnx ef migrations add MIGRATION_NAME (after the initial migration) produces the following migration:

    public partial class MIGRATION_NAME : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropForeignKey(name: "FK_Book_Author_AuthorId", table: "Book");
            migrationBuilder.AddForeignKey(
                name: "FK_Book_Author_AuthorId",
                table: "Book",
                column: "AuthorId",
                principalTable: "Author",
                principalColumn: "Id",
                onDelete: ReferentialAction.Cascade);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropForeignKey(name: "FK_Book_Author_AuthorId", table: "Book");
            migrationBuilder.AddForeignKey(
                name: "FK_Book_Author_AuthorId",
                table: "Book",
                column: "AuthorId",
                principalTable: "Author",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);
        }
    }

My project.json:

    {
      "version": "1.0.0-*",

      "compilationOptions": {
        "emitEntryPoint": true
      },

      "dependencies": {
        "EntityFramework.Core": "7.0.0-rc1-final",
        "EntityFramework.Relational": "7.0.0-rc1-final",
        "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
        "EntityFramework.Commands": "7.0.0-rc1-final"
      },

      "commands": {
        "EFFK": "EFFK",
        "ef": "EntityFramework.Commands"
      },

      "frameworks": {
        "dnx451": { },
        "dnxcore50": {
          "dependencies": {
            "Microsoft.CSharp": "4.0.1-beta-23516",
            "System.Collections": "4.0.11-beta-23516",
            "System.Console": "4.0.0-beta-23516",
            "System.Linq": "4.0.1-beta-23516",
            "System.Threading": "4.0.11-beta-23516"
          }
        }
      }
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions