C# 使用fluentapi的一对多实体框架

C# 使用fluentapi的一对多实体框架,c#,entity-framework,ef-code-first,one-to-many,ef-fluent-api,C#,Entity Framework,Ef Code First,One To Many,Ef Fluent Api,一个父母可以有很多孩子。一个孩子可以有一个父母。(是的,我知道,没有比这更好的例子了。) 如何使用fluentapi编写此代码 请注意,父项没有列出子项。这是故意的,也是问题的一部分。这里: 公共部分类父类{ 公共虚拟int-ParentId 公共虚拟字符串名 } 公营儿童{ 公共虚拟int-ChildId 公共虚拟字符串名 公共虚拟父级 } 在映射上,执行以下操作: public部分类ChildMap:ClassMap{ 公共儿童地图(){ 表(“[子]”); 懒散的负荷(); Id(x=>

一个父母可以有很多孩子。一个孩子可以有一个父母。(是的,我知道,没有比这更好的例子了。)

如何使用fluentapi编写此代码

请注意,
父项
没有列出子项。这是故意的,也是问题的一部分。

这里:

公共部分类父类{
公共虚拟int-ParentId
公共虚拟字符串名
}
公营儿童{
公共虚拟int-ChildId
公共虚拟字符串名
公共虚拟父级
}
在映射上,执行以下操作:

public部分类ChildMap:ClassMap{
公共儿童地图(){
表(“[子]”);
懒散的负荷();
Id(x=>x.ChildId).GeneratedBy.Identity()列(“ChildId”);
Map(x=>x.Name).Column(“Name”);
引用(x=>x.Parent).Column(“ParentId”).Not.Nullable();
}
}
公共部分类父映射:类映射{
公共ParentMap(){
表(“[母公司]”);
懒散的负荷();
Id(x=>x.ParentId).GeneratedBy.Identity()列(“ParentId”);
Map(x=>x.Name).Column(“Name”);
}
}
这种映射是在nhibernate中完成的,但它映射的内容与实体相同


编辑:此外,如果要访问一个父级的所有子级,应将列表添加到父级实体,并将其映射到父级映射上的HasMany

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; }
}

  • 带导航属性,不带EntityTypeConfiguration
只需运行代码:

<connectionStrings>
  <add name="Teste_123" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Teste_123;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
</connectionStrings>
如果添加迁移,请执行以下操作:

addmigration FirstMigration

您将获得以下代码:

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();
    }
}
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());
    }
}
只需在up方法上手动添加:

AddForeignKey(“dbo.Children”、“ParentId”、“dbo.Parents”、“ParentId”,删除:false)

您将得到:

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");
    }
}
现在,当您运行
updatedatabase
时,您将得到您想要的:

模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasRequired(c=>c.Parent)
.有许多();
}

这是一个非常简单的案例,你尝试过什么?我在2秒钟前发现了这个,似乎我一定错过了一个过载。哇。没想到会有一个NHibernate的例子作为答案。有趣的API看起来很灵活,但与EF相比,有点太多的代码不合我的口味。你用一个NHibernate示例回答了一个EF问题,EF的代码非常不同只是sintax不同,但逻辑是完全相同的。我的一个项目上有一个NHibernate示例,似乎需要做很多工作才能将其转换为EF。声明两者关系的逻辑非常相似,只是sintax不同。完整示例只需要.WithMany()部分,但需要+1。将来可能会帮助别人。我将创建一个新的答案tho,因为我想保持它简短和简单。EntityTypeConfiguration很好,保持了东西的整洁,但我现在不需要它在我的应用程序中,也许在未来的版本中。另外,应该谨慎使用延迟加载(虚拟)。据我所知,如果没有至少一个导航属性,就无法映射对象之间的关系。您可以尝试手动执行迁移…我更改了答案,添加了一个迁移示例。希望能有所帮助;)这些是不需要的:modelBuilder.Entity().HasKey(x=>x.ParentId);modelBuilder.Entity().HasKey(x=>x.ChildId);EF将按约定自动处理主键。也不需要此主键:。HasForeignKey(x=>x.ParentId)EF按约定知道这一点。
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");
    }
}
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");
    }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Child>()
            .HasRequired(c => c.Parent)
            .WithMany();
}