实体框架6.1 - SaveChanges因可选主体关系而失败

时间:2014-04-19 23:46:58

标签: c# entity-framework entity-framework-6

我有一个名为Employee的实体。它有一个名为CreatedById的可空属性,可用作自身的引用。它必须为空,因为第一个记录,可能是管理员,不会有创建者。当初始化数据库时,我插入第一个Employee对象时出现错误,我认为是因为我更新了与Fluent API的关系。代码如下:

Employee类:

public class Employee : NullableInt32Entity, IUser<int> {
    /// Omitted code that doesn't matter
}

NullableInt32Entity继承自的Employee类:

public class NullableInt32Entity :
    Entity,
    ICreatableEntity<int?>,
    IIndexableEntity<int> {
    #region ICreatableEntity Members
    public int? CreatedById { get; set; }
    #endregion

    #region IIndexableEntity Members
    public int Id { get; set; }
    #endregion
}

我认为导致问题的EmployeeConfiguration类中的配置:

this.HasOptional(
    t =>
        t.CreatedBy).WithOptionalPrincipal();

DatabaseInitializer类:

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

最后,但并非最不重要的是我得到的例外:实体在&#39; DatabaseContext.Employees&#39;参加&#39; Equipment_CreatedBy&#39;关系。 0相关&#39; Equipment_CreatedBy_Source&#39;被找到。 1&#39; Equipment_CreatedBy_Source&#39;预计。

所以,我的问题是,我该如何解决这个问题?我今天第一次开始使用WithOptionalPrincipal()WithRequiredPrincipal(),因为我意识到我并不关心从Employee到任何其他对象的导航属性。我曾经在XCreated中为每个其他对象都有一个Employee集合导航属性,我意识到它们没有被暴露,因为我永远不会使用它们。因此我把它们剥离了,不得不使用上面的方法。

我感谢任何建议,并提前致谢!

1 个答案:

答案 0 :(得分:0)

好的,事实证明我是这里的白痴。 @KirillBestemyanov在他的一篇评论中说,导致这个问题的是Equipment实体。那是因为我正在阅读,而不是理解错误信息,所有这一切都在我的脑海中点击。我脑子里有一个Employee实体是它的原因。当我使用WithOptionalPrincipal()WithRequiredPrincipal()方法时,我也使用了错误的配置。我不明白他们是如何运作的。

上面第二条评论中的代码实际上是正确的,但同样,我将它应用于错误的实体,这是没有错误的,这就是为什么错误没有得到解决。了解我出错的地方,我为我的整个DbContext实施进行了重写。我现在有一个更强大的实现,其可维护性指数从60变为76,我很高兴。

我实现了两个帮助我解决问题的基类,这是代码,以防有人对未来感兴趣:

Configuration_TEntity

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
}

Configuration_TEntity_TCreatedByKey

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() {
    }
}