题 没有声明外键的导航属性


我的所有模型都包含至少两个关联。在ef4中对此进行建模时,我只能通过使用流畅的界面在没有第二个外键属性的情况下执行此操作。 ForeignKey似乎是正确使用的属性,除了它需要一个字符串参数。

所以我的问题是,你能拥有一个导航属性并使用属性声明它吗?

public class User : IAuditable
{
    // other code

    public virtual User Creator { get; set; }

    public virtual User Modifier { get; set; }
}

28
2018-04-17 05:52


起源




答案:


我相信,不可能只与数据属性定义关系。问题是EF的映射约定假设了这一点 Creator 和 Modifier 是同一个关系的两端,但无法确定该关联的主体和依赖是什么。据我所知,在支持的属性列表中,没有选项可以使用数据注释定义主体和从属端。

除此之外,我想你真的想要 两个关系,两者都有一个没有在模型中暴露的结束。这意味着您的模型在映射约定方面是“非常规的”。 (我认为之间的关系 Creator 和 Modifier 实际上是无意义的 - 从语义的角度来看。)

因此,在Fluent API中,您需要这样:

modelBuilder.Entity<User>()
            .HasRequired(u => u.Creator)
            .WithMany();

modelBuilder.Entity<User>()
            .HasRequired(u => u.Modifier)
            .WithMany();

因为一个 User 可以是许多其他用户记录的创建者或修饰符。对?

如果你想在没有Fluent API且只有DataAnnotations的情况下创建这两个关系,我认为你必须在你的模型中引入关联的Many-Ends,如下所示:

public class User
{
    public int UserId { get; set; }

    [InverseProperty("Creator")]
    public virtual ICollection<User> CreatedUsers { get; set; }
    [InverseProperty("Modifier")]
    public virtual ICollection<User> ModifiedUsers { get; set; }

    [Required]
    public virtual User Creator { get; set; }
    [Required]
    public virtual User Modifier { get; set; }
}

我在这里假设 Creator 和 Modifier 是必需的,否则我们可以省略 [Required] 属性。

我认为这是一个明显的例子,使用Fluent API很有意义,并且比修改模型更好,只是为了避免Fluent配置。


32
2018-04-17 12:11



+1真的很好的答案。我不知道 InverseProperty 属性 - Ladislav Mrnka
很好的答案,我想知道逆属性,这是一个耻辱,它是不可能的。您认为可以根据自定义属性生成映射吗? - Daniel Little
@Lavinski:如果您定义自己的自定义属性,我认为您需要使用Reflection进行评估,然后根据此评估使用Fluent API创建映射。如果你真的有很多需要这个自定义属性的类,那么这可能是值得的。否则我会使用Fluent API而不关心属性。有许多映射配置是属性不可能的,只有Fluent代码。因此,无论如何,使用Fluent API通常是不可避免的。 - Slauma
@Lavinski:属性由约定处理,并且在此版本中无法添加自定义约定。 - Ladislav Mrnka