C# 使用fluentapi的一对多实体框架
一个父母可以有很多孩子。一个孩子可以有一个父母。(是的,我知道,没有比这更好的例子了。) 如何使用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=>
父项
没有列出子项。这是故意的,也是问题的一部分。这里:
公共部分类父类{
公共虚拟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();
}