Entity framework 实体框架核心所有者可以创建单独的表,而不是像预期的那样向同一个表添加属性
我认为EntityFramework核心拥有的类型默认情况下会添加到与其所有者相同的表中。但我没有在迁移中看到这一点 有人能告诉我这里的情况吗 有没有一种方法可以通过直接将Name属性添加到Person表中来获得所需的迁移Entity framework 实体框架核心所有者可以创建单独的表,而不是像预期的那样向同一个表添加属性,entity-framework,core,entity-framework-migrations,ef-core-2.1,owned-types,Entity Framework,Core,Entity Framework Migrations,Ef Core 2.1,Owned Types,我认为EntityFramework核心拥有的类型默认情况下会添加到与其所有者相同的表中。但我没有在迁移中看到这一点 有人能告诉我这里的情况吗 有没有一种方法可以通过直接将Name属性添加到Person表中来获得所需的迁移 public class Person { public Name Name { get; set; } } public class Name { public string FirstName { get; set; } public strin
public class Person
{
public Name Name { get; set; }
}
public class Name
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class PersonConfiguration : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> person)
{
person.OwnsOne(p => p.Name);
}
}
公共类人物
{
公共名称名称{get;set;}
}
公共类名
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
公共类人员配置:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder人员)
{
person.OwnsOne(p=>p.Name);
}
}
dotnet ef迁移添加没有预见到这一点
导致
public partial class DidNotSeeThatComing : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Name",
columns: table => new
{
FirstName = table.Column<string>(type: "varchar", nullable: true),
LastName = table.Column<string>(type: "varchar", nullable: true),
PersonId = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Name", x => x.PersonId);
table.ForeignKey(
name: "FK_Name_Person_PersonId",
column: x => x.PersonId,
principalTable: "Person",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
);
}
}
public分部类没有看到即将到来的消息:迁移
{
受保护的覆盖作废(MigrationBuilder MigrationBuilder)
{
migrationBuilder.CreateTable(
姓名:“姓名”,
列:表=>new
{
FirstName=table.Column(类型:“varchar”,可为空:true),
LastName=table.Column(类型:“varchar”,可为空:true),
PersonId=table.Column(可空:false)
},
约束:表=>
{
表.PrimaryKey(“PK_Name”,x=>x.PersonId);
表1.外键(
姓名:“FK\u姓名\u人名\u人名”,
列:x=>x.PersonId,
原则性:“人”,
主栏:“Id”,
onDelete:引用。级联);
});
);
}
}
我自己用这个配置代码无意中创建了这个
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
entity.Relational().TableName = entity.Name;
}
}
这是我正在使用的解决方法
[Owned] // Microsoft.EntityFrameworkCore
public class Name { ... }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
if(!entity.ClrType.GetCustomAttributes().OfType<OwnedAttribute>().Any())
{
entity.Relational().TableName = entity.Name;
}
}
}
[Owned]//Microsoft.EntityFrameworkCore
公共类名{…}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
基于模型创建(modelBuilder);
foreach(modelBuilder.Model.GetEntityTypes()中的var实体)
{
如果(!entity.ClrType.GetCustomAttributes().OfType().Any())
{
entity.Relational().TableName=entity.Name;
}
}
}
尝试以下方法:
public class Person
{
public Guid Id { get; set; }
public Name Name { get; set; }
}
public class Name
{
public Guid Id { get; set; }
public Guid PersonId {get;set;}
public Person Person { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class PersonConfiguration : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> person)
{
person.OwnsOne(p => p.Name,
nCls =>
{
nCls.HasOne(n => n.Person);
nCls.HasKey(n => new {n.Id, n.PersonId});
nCls.HasForeignKey(m => m.PersonId);
nCls.ToTable(nCls.OwnedEntityType.ClrType.Name);
}
);
}
}
公共类人物
{
公共Guid Id{get;set;}
公共名称名称{get;set;}
}
公共类名
{
公共Guid Id{get;set;}
公共Guid PersonId{get;set;}
公众人物{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
公共类人员配置:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder人员)
{
person.OwnsOne(p=>p.Name,
nCls=>
{
nCls.HasOne(n=>n人);
nCls.HasKey(n=>new{n.Id,n.PersonId});
nCls.HasForeignKey(m=>m.PersonId);
ntable(nCls.OwnedEntityType.ClrType.Name);
}
);
}
}
这应该会让您得到如下结果:
protected override void Up(MigrationBuilder migrationBuilder)
{
// the table names are lower case because my convention is to generate all names in snake_case
migrationBuilder.CreateTable(
name: "persons",
columns: table => new
{
id = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_persons", x => x.id);
});
migrationBuilder.CreateTable(
name: "name",
columns: table => new
{
id = table.Column<Guid>(nullable: false),
person_id = table.Column<Guid>(nullable: false),
first_name = table.Column<string>(maxLength: 256, nullable: true),
last_name = table.Column<string>(maxLength: 256, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_name", x => new { x.id, x.person_id });
table.ForeignKey(
name: "fk_name_persons_person_id",
column: x => x.person_id,
principalTable: "persons",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
}
protected override void Up(MigrationBuilder MigrationBuilder)
{
//表名是小写的,因为我的约定是生成所有大小写的名称
migrationBuilder.CreateTable(
姓名:“人”,
列:表=>new
{
id=table.Column(可空:false)
},
约束:表=>
{
表.PrimaryKey(“pk_persons”,x=>x.id);
});
migrationBuilder.CreateTable(
姓名:“姓名”,
列:表=>new
{
id=table.Column(可空:false),
person_id=table.Column(可空:false),
first_name=table.Column(maxLength:256,nullable:true),
last_name=table.Column(maxLength:256,null:true)
},
约束:表=>
{
表.PrimaryKey(“pk_name”,x=>new{x.id,x.person_id});
表1.外键(
姓名:“fk\U姓名\U人员\U人员id”,
列:x=>x.person\u id,
原则性:“人”,
主栏:“id”,
onDelete:引用。级联);
});
}
@Davious我今天遇到了完全相同的问题,感谢您分享您的解决方案。这里是我的解决方案,您不需要OwnedAttribute
,因为您还可以使用entity.isoowned()
。我总是尝试通过DbContext进行所有验证
///[Owned] // Not needed anymore
public class Name { ... }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelbuilder.Entity<Person>().OwnsOne(p => p.Name)
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
if(!entity.IsOwned())
{
entity.Relational().TableName = entity.Name;
}
}
}
//[Owned]//不再需要了
公共类名{…}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
基于模型创建(modelBuilder);
modelbuilder.Entity().OwnsOne(p=>p.Name)
foreach(modelBuilder.Model.GetEntityTypes()中的var实体)
{
如果(!entity.IsOwned())
{
entity.Relational().TableName=entity.Name;
}
}
}
您的想法是正确的-默认情况下,它与所有者放在同一张表中,我无法重现该问题。你有干净的回购项目吗?@IvanStoev验证了一个干净的回购项目的预期效果,在发生这种情况的项目中有任何不寻常的代码吗?像模型实体/反射上的循环和调用ToTable
?Ugg我用foreach(modelBuilder.model.GetEntityTypes()中的var实体){entity.Relational(),所以在最后,它是不寻常的模型实体循环:)很高兴你已经解决了这个问题。