Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fluent Api Entity Framework core

A user can have 1 or 0 account

public class User
    {
        public int UserId { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public Account Account { get; set; }
    }

    public class Account
    {
        public int AccountId { get; set; }         
        public DateTime CreatedDateTime { get; set; }
        public User User { get; set; }

    }

This is the fluent api code using Entity Framework 6

public class ClassDbContext: DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<User>()
                  .HasOptional(s => s.Account) 
                  .WithRequired(ad => ad.User);
    }
    public DbSet<User> Users { get; set; }
    public DbSet<Account> Accounts { get; set; }
}

This is the result ResultImage

what is the equivalent fluent api code using Entity Framework Core?

like image 710
Moth Avatar asked Apr 21 '17 15:04

Moth


People also ask

What is Fluent API in Entity Framework Core?

Fluent API is another way to configure your domain classes. The Code First Fluent API is most commonly accessed by overriding the OnModelCreating method on your derived DbContext. Fluent API provides more functionality for configuration than DataAnnotations. Fluent API supports the following types of mappings.

Does EF core support Fluent API?

EF Fluent API is based on a Fluent API design pattern (a.k.a Fluent Interface) where the result is formulated by method chaining. In Entity Framework Core, the ModelBuilder class acts as a Fluent API.

Should I use EF6 or EF core?

Keep using EF6 if the data access code is stable and not likely to evolve or need new features. Port to EF Core if the data access code is evolving or if the app needs new features only available in EF Core. Porting to EF Core is also often done for performance.

Is EF core faster than EF6?

Entity Framework (EF) Core, Microsoft's object-to-database mapper library for . NET Framework, brings performance improvements for data updates in version 7, Microsoft claims. The performance of SaveChanges method in EF7 is up to 74% faster than in EF6, in some scenarios.


1 Answers

@Tseng is close, but not enough. With the proposed configuration you'll get exception with message:

The child/dependent side could not be determined for the one-to-one relationship that was detected between 'Account.User' and 'User.Account'. To identify the child/dependent side of the relationship, configure the foreign key property. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details.

It's basically explained in the documentation from the link.

First, you need to use HasOne and WithOne.

Second, you must use HasForeignKey to specify which one of the two entities is the dependent (it cannot be detected automatically when there is no separate FK property defined in one of the entities).

Third, there is no more required dependent. The IsRequired method can be used to specify if the FK is required or not when the dependent entity uses separate FK (rather than PK as in your case, i.e. with the so called Shared Primary Key Association because PK apparently cannot be null).

With that being said, the correct F Core fluent configuration of the posted model is as follows:

modelBuilder.Entity<User>()
    .HasOne(e => e.Account)
    .WithOne(e => e.User)
    .HasForeignKey<Account>(e => e.AccountId);

and the result is:

migrationBuilder.CreateTable(
    name: "User",
    columns: table => new
    {
        UserId = table.Column<int>(nullable: false)
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
        Email = table.Column<string>(nullable: true),
        Name = table.Column<string>(nullable: true)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_User", x => x.UserId);
    });

migrationBuilder.CreateTable(
    name: "Account",
    columns: table => new
    {
        AccountId = table.Column<int>(nullable: false),
        CreatedDateTime = table.Column<DateTime>(nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Account", x => x.AccountId);
        table.ForeignKey(
            name: "FK_Account_User_AccountId",
            column: x => x.AccountId,
            principalTable: "User",
            principalColumn: "UserId",
            onDelete: ReferentialAction.Cascade);
    });
like image 160
Ivan Stoev Avatar answered Sep 21 '22 11:09

Ivan Stoev