简体   繁体   中英

Entity Framework one to many using fluent API

public class Parent
{
    public int ParentId { get; set; }
    public string Name { get; set; }
}

public class Child
{
    public int ChildId { get; set; }
    public string Name { get; set; }
    public Parent Parent { get; set; }
    public int ParentId { get; set; }
}

One parent can have many children. One child can have one parent. (Yeah, I know, couldn't come up with a better example.)

How do you write this using the fluent API?

Note that the Parent does not have a List<Child> Children . That is intentional and part of the problem.

Here is a complete console application with the configuration you need:

class Program
{
    static void Main(string[] args)
    {
        var ctx = new TesteContext();
        ctx.Database.CreateIfNotExists();

        Console.ReadKey();
    }
}

public class Parent
{
    public int ParentId { get; set; }
    public string Name { get; set; }
}

public class Child
{
    public int ChildId { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
    public virtual Parent Parent { get; set; }
}

public class ParentConfiguration : EntityTypeConfiguration<Parent>
{
    public ParentConfiguration()
    {
        HasKey(x => x.ParentId);
    }
}

public class ChildConfiguration : EntityTypeConfiguration<Child>
{
    public ChildConfiguration()
    {
        HasKey(x => x.ChildId);

        HasRequired(x => x.Parent)
            .WithMany()
            .HasForeignKey(x => x.ParentId)
            .WillCascadeOnDelete(false);
    }
}

public class TesteContext : DbContext
{
    public DbSet<Parent> Parents { get; set; }
    public DbSet<Child> Childs { get; set; }

    public TesteContext() : base("Teste_123")
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ParentConfiguration());
        modelBuilder.Configurations.Add(new ChildConfiguration());
    }
}

And add the connection string to you app.config : (Replacing the database, etc)

<connectionStrings>
  <add name="Teste_123" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Teste_123;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
</connectionStrings>

  • With navigation property and without EntityTypeConfiguration

Just run the code:

class Program
{
    static void Main(string[] args)
    {
        var ctx = new TesteContext();
        ctx.Database.CreateIfNotExists();

        Console.ReadKey();
    }
}

public class Parent
{
    public int ParentId { get; set; }
    public string Name { get; set; }
}

public class Child
{
    public int ChildId { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
    public Parent Parent { get; set; }
}

public class TesteContext : DbContext
{
    public DbSet<Parent> Parents { get; set; }
    public DbSet<Child> Childs { get; set; }

    public TesteContext() : base("Teste_123")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Child>()
            .HasRequired(x => x.Parent)
            .WithMany();
    }
}

  • Without navigation property

You can add a migration:

enable-migrations

With the code below:

public class Parent
{
    public int ParentId { get; set; }
    public string Name { get; set; }
}

public class Child
{
    public int ChildId { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
}

public class ParentConfiguration : EntityTypeConfiguration<Parent>
{
    public ParentConfiguration()
    {
        HasKey(x => x.ParentId);
    }
}

public class ChildConfiguration : EntityTypeConfiguration<Child>
{
    public ChildConfiguration()
    {
        HasKey(x => x.ChildId);
    }
}

public class TesteContext : DbContext
{
    public DbSet<Parent> Parents { get; set; }
    public DbSet<Child> Childs { get; set; }

    public TesteContext() : base("Teste_123")
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ParentConfiguration());
        modelBuilder.Configurations.Add(new ChildConfiguration());
    }
}

If you add a migration:

Add-Migration FirstMigration

You will get the code below:

public partial class FirstMigration : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Children",
            c => new
                {
                    ChildId = c.Int(nullable: false, identity: true),
                    Name = c.String(),
                    ParentId = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ChildId);

        CreateTable(
            "dbo.Parents",
            c => new
                {
                    ParentId = c.Int(nullable: false, identity: true),
                    Name = c.String(),
                })
            .PrimaryKey(t => t.ParentId);
    }

    public override void Down()
    {
        DropTable("dbo.Parents");
        DropTable("dbo.Children");
    }
}

Just add manually on the up method:

AddForeignKey("dbo.Children", "ParentId", "dbo.Parents", "ParentId", cascadeDelete: false);

And you'll get:

public partial class FirstMigration : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Children",
            c => new
                {
                    ChildId = c.Int(nullable: false, identity: true),
                    Name = c.String(),
                    ParentId = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ChildId);

        CreateTable(
            "dbo.Parents",
            c => new
                {
                    ParentId = c.Int(nullable: false, identity: true),
                    Name = c.String(),
                })
            .PrimaryKey(t => t.ParentId);

        AddForeignKey("dbo.Children", "ParentId", "dbo.Parents", "ParentId", cascadeDelete: false);
    }

    public override void Down()
    {
        DropTable("dbo.Parents");
        DropTable("dbo.Children");
    }
}

Now, when you run update-database , you'll get what you want:

在此处输入图片说明

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Child>()
            .HasRequired(c => c.Parent)
            .WithMany();
}

Here:

public partial class Parent {
    public virtual int ParentId 
    public virtual string Name
}

public class Child {
    public virtual int ChildId 
    public virtual string Name
    public virtual Parent Parent
}

and on your mappings, do:

public partial class ChildMap : ClassMap<Child> {
        public ChildMap(){
            Table("[child]");
            LazyLoad();
            Id(x => x.ChildId ).GeneratedBy.Identity().Column("ChildId ");
            Map(x => x.Name).Column("Name");
            References(x => x.Parent).Column("ParentId").Not.Nullable();
        }
    }

public partial class ParentMap : ClassMap<Parent> {
        public ParentMap(){
            Table("[parent]");
            LazyLoad();
            Id(x => x.ParentId).GeneratedBy.Identity().Column("ParentId");
            Map(x => x.Name).Column("Name");
        }
    }

This mapping is done in nhibernate, but it maps just the same as entity.

Edit: Also, if you want to access all childs of one parent, you should add the List to parent entity, and map it with HasMany on the parent mapping

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