EF Core One-to-One relationship with Shadow properties as a Keys using Fluent API

c# entity-framework-core

Question

I can't resolve the One-to-One relationship between two classes using Shadow Properties as a Keys. Unfortunately I can't create real key properties into my classes due to I used 3rd party class library.

using Microsoft.EntityFrameworkCore;
using System;

namespace EFCoreTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Create database");
            using (var context = new ClassDbContext())
            {
                if (!context.Database.EnsureDeleted())
                {
                    Console.WriteLine(" => Can't delete database");
                }
                if (context.Database.EnsureCreated())
                {
                    context.SaveChanges();
                    Console.WriteLine(" => Done");
                }
                else
                {
                    Console.WriteLine(" => Can't create database");
                }
            }
            Console.WriteLine("End");
        }
    }
    public class ClassDbContext : DbContext
    {
        public virtual DbSet<ClassA> ClassA { get; set; }
        public virtual DbSet<ClassB> ClassB { get; set; }
        public ClassDbContext()
        {
        }
        public ClassDbContext(DbContextOptions<ClassDbContext> options) : base(options)
        {
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("Server=XXX.XXX.XXX.XXX;Database=XXXXX;User ID=XXXXX;Password=XXXXX");
            }
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<ClassA>().Property<int>("ClassAId");
            modelBuilder.Entity<ClassB>().Property<int>("ClassBId");
            modelBuilder.Entity<ClassB>().Property<int>("AnotherClassId");
            modelBuilder.Entity<ClassB>().HasOne(p => p.AnotherClass).WithMany().HasForeignKey("AnotherClassId");
        }
    }
    public class ClassA
    {
        public string PropertyA { get; set; }
    }
    public class ClassB
    {
        public string PropertyB { get; set; }
        public ClassA AnotherClass { get; set; }
    }
}

EF Core returns with the following error, which is very confused me:

System.InvalidOperationException: 'The relationship from 'ClassB.AnotherClass' to 'ClassA' with foreign key properties {'AnotherClassId' : int} cannot target the primary key {'ClassAId' : int} because it is not compatible. Configure a principal key or a set of compatible foreign key properties for this relationship.'

1
1
2/5/2019 7:42:42 PM

Popular Answer

It turns out that the automatic binding of properties to keys, implemented in EF Core through the naming of properties, does not work in this case!

They require you to force a key name before creating a connection!

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<ClassA>().Property<int>("ClassAId");
    modelBuilder.Entity<ClassA>().HasKey("ClassAId"); // <=== This is a SOLUTION
    modelBuilder.Entity<ClassB>().Property<int>("ClassBId");
    modelBuilder.Entity<ClassB>().Property<int>("AnotherClassId");
    modelBuilder.Entity<ClassB>().HasOne(p => p.AnotherClass).WithMany().HasForeignKey("AnotherClassId");
}
1
2/5/2019 2:04:02 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow