Giter VIP home page Giter VIP logo

ef-relationship's Introduction

EF Core Principal<->Dependant IDs

This repository explores how EF Core handles principal-dependent relationships and the navigation properties related to those by convention.

We're going to demonstrate a 1:1 association between two entities and observe EF Core manage the IDs of both ends for us. Then we are going to change them and watch the IDs stay in sync. Next we are going to try to forcefully set incorrect IDs and will observe EF Core push back on that idea.

  • Do the above

Let's create a new .NET Core application and install the EF Core package to it, including the SQL Server provider support, because we are going to be using LocalDB.

Note that I am installing the NuGet packages from the official NuGet source and in order to obtain consistent results, you should disable other package sources in your Visual Studio > Tools > Options > NuGet Package Manager > Package Sources option. It is enough to uncheck them while installing the packages below.

dotnet new console
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

Now that we have the application set up, we also need to set up the LocalDB database. We're going to call it by the name of the application namespace, which works out to be ef_core_principal_dependent_ids since the repository directory name where we've run dotnet new is called ef-core-principal-dependent-ids. By doing this we can use nameof in the source code in the connection string.

sqllocaldb create ef_core_principal_dependent_ids -s

Note that the -s switch automatically starts the instance after creation.

We are not going to be adding a dependency on Microsoft.EntityFrameworkCore.Design as we do not need the dotnet ef tool, we are not going to use EF Core Migrations.

Let's check everything compiles: dotnet run.

Now that we have the application up and running, we can move on to the entity classes and the application database context setup.

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int CarId { get; set; }
    public Car Car { get; set; }
}

public class Car
{
    public int Id { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public int UserId { get; set; }
    public User User { get; set; }
}

The model looks good, now for the application database context class and the database connection:

public class AppDbContext: DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Car> Cars { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer($@"Server=(localdb)\{nameof(ef_core_principal_dependent_ids)};Database={nameof(ef_core_principal_dependent_ids)};");
    }
}

To test this out, we will connect to the database and reset it by dropping it and recreating it. This will help with repeatability of this demo.

static void Main(string[] args)
{
    using (var appDbContext = new AppDbContext())
    {
        appDbContext.Database.EnsureDeleted();
        appDbContext.Database.EnsureCreated();
        Console.WriteLine("The database has been reset.");
    }
}

Running this (after adding Microsoft.EntityFrameworkCore namespace import), we encounter this issue:

The child/dependent side could not be determined for the one-to-one relationship between 'Car.User' and 'User.Car'.

This makes sense, EF Core has no way of knowing which side of the 1:1 relationship is the principal and which one is the dependant.

Let's help it understand using the fluent API.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<User>()
        .HasOne(principal => principal.Car)
        .WithOne(dependant => dependant.User)
        .HasForeignKey<Car>(car => car.UserId);
}

Now for the first scenarion - us adding a user and a car, and EF assigning the correct IDs:

Whoops! It doesn't. I asked dotnet/efcore#14704.

I seem to have been mistaken remembering this working.

To-Do

Fix the misspelling of "dependant" in the repo name and the source code

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.