C# 实体框架6.1-保存更改失败,主体关系可选
我有一个名为C# 实体框架6.1-保存更改失败,主体关系可选,c#,entity-framework,entity-framework-6,C#,Entity Framework,Entity Framework 6,我有一个名为Employee的实体。它有一个名为CreatedById的可空属性,用作对自身的引用。它必须为空,因为第一条记录(可能是管理员)没有创建者。当by数据库被初始化时,当插入第一个Employee对象时,我不断得到一个错误,我认为这是因为我更新了与Fluent API的关系。代码如下: 员工类别: public class Employee : NullableInt32Entity, IUser<int> { /// Omitted code that doesn
Employee
的实体。它有一个名为CreatedById
的可空属性,用作对自身的引用。它必须为空,因为第一条记录(可能是管理员)没有创建者。当by数据库被初始化时,当插入第一个Employee
对象时,我不断得到一个错误,我认为这是因为我更新了与Fluent API的关系。代码如下:
员工
类别:
public class Employee : NullableInt32Entity, IUser<int> {
/// Omitted code that doesn't matter
}
internal sealed class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext> {
protected override void Seed(
DatabaseContext context) {
Employee creator = new Employee {
FirstName = "System",
IsActive = true,
LastName = "Administrator",
PasswordHash = "AIw9zIWiDnIesTaYhSjJhHJo5VYWCUV1rH0Oa0TaTriQXiDmXDBSq5y8Q0Zv3KUw/Q=="
};
context.Employees.Add(creator);
context.SaveChanges();
/// Additional seeds that depend on the one above as their creator.
}
}
我认为是EmployeeConfiguration
类中的配置导致了问题:
this.HasOptional(
t =>
t.CreatedBy).WithOptionalPrincipal();
数据库初始值设定项
类:
public class Employee : NullableInt32Entity, IUser<int> {
/// Omitted code that doesn't matter
}
internal sealed class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext> {
protected override void Seed(
DatabaseContext context) {
Employee creator = new Employee {
FirstName = "System",
IsActive = true,
LastName = "Administrator",
PasswordHash = "AIw9zIWiDnIesTaYhSjJhHJo5VYWCUV1rH0Oa0TaTriQXiDmXDBSq5y8Q0Zv3KUw/Q=="
};
context.Employees.Add(creator);
context.SaveChanges();
/// Additional seeds that depend on the one above as their creator.
}
}
内部密封类数据库初始值设定项:DropCreateDatabaseIfModelChanges{
受保护覆盖无效种子(
数据库(上下文){
员工创建者=新员工{
FirstName=“系统”,
IsActive=true,
LastName=“管理员”,
PasswordHash=“aiw9ziwidniestayhsjhjo5vywcuv1rh0oa0atriqxidmxdbsq5y8q0zv3kuw/Q=”
};
context.Employees.Add(创建者);
SaveChanges();
///额外的种子依赖于上面的一个作为他们的创造者。
}
}
最后,但并非最不重要的例外是:“DatabaseContext.Employees”中的实体参与“Equipment_CreatedBy”关系。找到0个相关的“设备\u由\u源创建”。应为1“由源创建的设备”
所以,我的问题是,我如何解决这个问题?今天我第一次开始使用带OptionalPrincipal()的和带RequiredPrincipal()的了,因为我意识到我不关心从Employee
到任何其他对象的导航属性。我以前在Employee
中为每个其他对象都有一个XCreated
集合导航属性,我意识到它们是没有意义的,因为我永远不会使用它们。因此,我将它们剥离出来,并不得不使用上述方法
我感谢您的建议,并提前表示感谢 好吧,原来我是这里的白痴@KirillBestemyanov在他的一篇评论中说,是设备
实体造成了问题。那是因为我正在阅读,但不理解错误信息,所以它在我的脑海中发出咔哒声。我脑子里想的是,员工
实体是原因,而事实并非如此。当我使用带OptionalPrincipal()的和带RequiredPrincipal()的方法时,我也使用了错误的配置。我不明白它们是如何运作的
上面第二条注释中的代码实际上是正确的,但我再次将其应用于错误的实体,而该实体没有出现错误,这就是错误没有得到解决的原因。理解了哪里出了错,我开始了整个DbContext
实现的重写狂潮。我现在有了一个更加健壮的实现,它的可维护性指数从60提高到了76,这让我很高兴
我实现了两个基类,它们帮助我解决了我的问题,下面是代码,以防有人对未来感兴趣:
配置强度等级
internal abstract class Configuration<TEntity> :
EntityTypeConfiguration<TEntity>
where TEntity : class, ICreatableEntity, IRemovableEntity, new() {
protected virtual void Configure() {
this.ConfigureCreatableProperties();
this.ConfigureRemovableProperties();
this.ConfigureProperties();
this.ConfigureCreatableRelationships();
this.ConfigureRemovableRelationships();
this.ConfigureRelationships();
}
#region Property Configurations
protected virtual void ConfigureCreatableProperties() {
this.Property(
p =>
p.CreatedDateTime).HasColumnType("datetime2");
}
protected virtual void ConfigureRemovableProperties() {
this.Property(
p =>
p.RemovedDateTime).HasColumnType("datetime2");
}
protected abstract void ConfigureProperties();
#endregion
#region Relationship Configurations
protected abstract void ConfigureCreatableRelationships();
protected virtual void ConfigureRemovableRelationships() {
this.HasOptional(
t =>
t.RemovedBy).WithMany().HasForeignKey(
k =>
k.RemovedById);
}
protected abstract void ConfigureRelationships();
#endregion
}
internal class Configuration<TEntity, TCreatedByKey> :
Configuration<TEntity>
where TEntity : class, ICreatableEntity, ICreatableEntity<TCreatedByKey>, IRemovableEntity, new()
where TCreatedByKey : struct {
protected override void ConfigureCreatableRelationships() {
this.HasRequired(
t =>
t.CreatedBy).WithMany().HasForeignKey(
k =>
k.CreatedById);
}
protected override void ConfigureProperties() {
}
protected override void ConfigureRelationships() {
}
}
内部抽象类配置:
EntityTypeConfiguration
其中tenty:class、ICreatableEntity、IRemovableEntity、new(){
受保护的虚拟void Configure(){
这是.ConfigureCreatableProperties();
此.ConfigureRemovableProperties();
此参数为.ConfigureProperties();
这是.ConfigureCreatableRelationships();
此.ConfigureRemovableRelationships();
这是.ConfigureRelationships();
}
#区域属性配置
受保护的虚拟void ConfigureCreatableProperties(){
这是我的财产(
p=>
p、 HasColumnType(“datetime2”);
}
受保护的虚拟void ConfigureRemovableProperties(){
这是我的财产(
p=>
p、 RemovedDateTime)。HasColumnType(“datetime2”);
}
受保护的抽象无效配置属性();
#端区
#区域关系配置
受保护的抽象void ConfigureCreatableRelationships();
受保护的虚拟void ConfigureRemovableRelationships(){
这个是可选的(
t=>
t、 RemovedBy)。WithMany().HasForeignKey(
k=>
k、 去除BYID);
}
受保护的抽象无效配置关系();
#端区
}
配置\u tenty\u TCreatedByKey类
internal abstract class Configuration<TEntity> :
EntityTypeConfiguration<TEntity>
where TEntity : class, ICreatableEntity, IRemovableEntity, new() {
protected virtual void Configure() {
this.ConfigureCreatableProperties();
this.ConfigureRemovableProperties();
this.ConfigureProperties();
this.ConfigureCreatableRelationships();
this.ConfigureRemovableRelationships();
this.ConfigureRelationships();
}
#region Property Configurations
protected virtual void ConfigureCreatableProperties() {
this.Property(
p =>
p.CreatedDateTime).HasColumnType("datetime2");
}
protected virtual void ConfigureRemovableProperties() {
this.Property(
p =>
p.RemovedDateTime).HasColumnType("datetime2");
}
protected abstract void ConfigureProperties();
#endregion
#region Relationship Configurations
protected abstract void ConfigureCreatableRelationships();
protected virtual void ConfigureRemovableRelationships() {
this.HasOptional(
t =>
t.RemovedBy).WithMany().HasForeignKey(
k =>
k.RemovedById);
}
protected abstract void ConfigureRelationships();
#endregion
}
internal class Configuration<TEntity, TCreatedByKey> :
Configuration<TEntity>
where TEntity : class, ICreatableEntity, ICreatableEntity<TCreatedByKey>, IRemovableEntity, new()
where TCreatedByKey : struct {
protected override void ConfigureCreatableRelationships() {
this.HasRequired(
t =>
t.CreatedBy).WithMany().HasForeignKey(
k =>
k.CreatedById);
}
protected override void ConfigureProperties() {
}
protected override void ConfigureRelationships() {
}
}
内部类配置:
配置
其中tenty:class、ICreatableEntity、ICreatableEntity、IRemovableEntity、new()
其中TCreatedByKey:struct{
受保护的覆盖无效ConfigureCreatableRelationships(){
这是必需的(
t=>
t、 CreatedBy).WithMany().HasForeignKey(
k=>
k、 CreatedById);
}
受保护的覆盖无效配置属性(){
}
受保护的覆盖无效配置关系(){
}
}
您确定每个创建者实体(您在CreatedBy属性中使用的)只能在一个员工实体中使用吗?看来你应该用一对多的关系来代替。@KirillBestemyanov,是的,你是对的,这就是我想要的。我想我对xprincipal()的理解得不太好。我试着用this.HasOptional(t=>t.CreatedBy).WithMany().HasForeignKey(k=>k.CreatedById)
替换它,但仍然得到了相同的异常。建议?您的异常消息中有设备实体。你能展示它的代码(类和配置)吗?你能展示更多的Seed
方法吗?特别是在哪里设置CreatedBy
属性?