EFCore 模型无效。以多种方式引用另一个 class 似乎是问题所在?

EFCore Model is invalid. Reference another class from it multiple ways seems to be the problem?

我有一个工作流数据库,其中一部分是 WORKFLOW_INSTANCE,其中有很多 WORKFLOW_STEP_INSTANCE。它工作正常,直到我添加下面的行。

我想说的是一对多但是对于单个WORKFLOW_INSTANCE我也想知道具体的开始工作流程步骤和结束工作流程步骤。为什么会出错?我想我可以只使用 int 并跳过 class 引用吗?

无法确定类型 'WfStepInstance' 的导航 属性 'WfInstance.WfInitialStepInstance' 表示的关系。手动配置关系,或使用“[NotMapped]”属性或使用 'OnModelCreating'.

中的 'EntityTypeBuilder.Ignore' 忽略此 属性
    public class WfInstance : Entity
{
    public string CreateBy { get; set; }
    public DateTime CreatedOn { get; set; }


    // n-1 relationship
    public int WfStatusTypeId { get; set; }
    public WfStatusType WfStatusType { get; set; }

    public int WfDefinitionId { get; set; }
    public WfDefinition WfDefinition { get; set; }

    public int WfActionTypeId { get; set; }
    public WfActionType WfActionType { get; set; }

    //doesnt work!!!!
    public int WfInitialStepInstanceId { get; set; }
    public WfStepInstance WfInitialStepInstance { get; set; }

    //doesnt work!!!!
    //public int WfCurrentStepInstanceId { get; set; }
    //public WfStepInstance WfCurrentStepInstance { get; set; }

    // 1-n relationship 
    public List<WfStepInstance> WfStepInstances { get; set; } = new List<WfStepInstance>();
}

public class WfStepInstance : Entity
{
    public string Inputs { get; set; }
    public string Outputs { get; set; }
    public string WaitData { get; set; }
    public string CreateBy { get; set; }
    public DateTime CreatedOn { get; set; }

    // 1-1 relationship
    public int? NextStepId { get; set; }
    public virtual WfStepInstance NextStep { get; set; }

    // n-1 relationship
    public int WfInstanceId { get; set; }
    public WfInstance WfInstance { get; set; }

    public int WfStepStatusTypeId { get; set; }
    public WfStepStatusType WfStepStatusType { get; set; }

    public int WfStepTypeId { get; set; }
    public WfStepType WfStepType { get; set; }
}

我认为问题在于您需要告诉 EF 使用什么 FK。在多对一 (WfInitialStepInstance / WfCurrentStepInstance) 的情况下,EF 使用 Type 来推断键名。

这是可行的,因为类型是 WfActionType,所以约定指向一个名为 WfActionTypeId 的键。

public int WfActionTypeId { get; set; }
public WfActionType WfActionType { get; set; }

这些不起作用,因为约定无法推断 FK 名称,并且您有两个 WfStepInstance 类型的属性。

//doesnt work!!!!
public int WfInitialStepInstanceId { get; set; }
public WfStepInstance WfInitialStepInstance { get; set; }

//doesnt work!!!!
public int WfCurrentStepInstanceId { get; set; }
public WfStepInstance WfCurrentStepInstance { get; set; }

这应该有效..

[ForeignKey("WfInitialStepInstance")]
public int WfInitialStepInstanceId { get; set; }
public WfStepInstance WfInitialStepInstance { get; set; }

[ForeignKey("WfCurrentStepInstance")]
public int WfCurrentStepInstanceId { get; set; }
public WfStepInstance WfCurrentStepInstance { get; set; }

我不太喜欢约定优于配置,因为它在某种程度上滋生了自满情绪,人们可以欣赏它 "just works" 直到它 "just doesn't" 然后被留在没有桨的小溪上,如果他们没有跟上配置的速度。 :)

我建议通过 EntityTypeConfiguration<T> (EF6)/IEntityTypeConfiguration<T> (EFCore) 和 DbContext.OnModelCreating 阅读 EF 配置。这将极大地帮助理解 EF 关系是如何映射的,以及当约定不完全适用时您可以做什么。我还建议使用 Shadow Properties (EFCore) 或 Map+MapKey (EF6) 而不是在实体中声明 FK 属性。映射的 FK 为实体中的关系提供两个真实来源,并可能导致错误。使用阴影属性,您的实体仅声明导航属性。 FK 是隐藏的。