c# – 如何在实体框架的FluentAPI /数据注释中定义外键可选关系?

我有一个(示例)应用程序与以下代码:

public class Posts
{

    [Key]
    [Required]
    public int ID { get; set; }

    [Required]
    public string TypeOfPost { get; set; }

    public int PollID { get; set; }
    public virtual Poll Poll { get; set; }

    public int PostID { get; set; }
    public virtual Post Post { get; set; }

}

基本上,我不知道是否有更好的方法,但是我有一个职位列表,人们可以选择是否是一个投票或邮件,因为实体框架不适用于枚举,我只是将它作为一个字符串存储在TypeOfPost,然后在应用程序中,我以编程方式查询Poll或Post,基于TypeOfPost的值.

我不认为有没有设置“只需要一个”或类似的,所以我处理所有的检查和应用程序的东西. (如果有人知道更好的方法,请说!).

无论如何,问题是,我可以通过进入SQL Management Studio并手动编辑模式来允许null来使这个工作正常 – 但是,我无法解决如何在FluentAPI中执行此操作,并且需要一些帮助.

我已经尝试了以下两个:

modelBuilder.Entity<Post>()
    .HasOptional(x => x.Poll).WithOptionalDependent();

modelBuilder.Entity<Post>()
    .HasOptional(x => x.Poll).WithOptionalPrincipal();

第一个似乎在数据库中创建一个允许空值的附加列,第二个列似乎没有做任何事情.

我相信第一个是我需要的,但是我需要在Post Class中与[ForeignKey]结合使用它.如果我在这里是正确的,[ForeignKey]应该去虚拟财产还是财产的ID?

另外,WithOptionalDependent和WithOptionalPrincipal之间的实际区别是什么? – 我已经在MSDN上阅读过,但是我真的不明白这个区别.

我可能会尝试创建两个一对一的关系作为可选的:必需的,因为一个民意调查必须有一个引用的帖子和一个帖子也必须引用的帖子:

modelBuilder.Entity<Posts>()
    .HasOptional(x => x.Post)
    .WithRequired();

modelBuilder.Entity<Posts>()
    .HasOptional(x => x.Poll)
    .WithRequired();

这使得帖子自动地成为关系中的主体,并且Post或Poll是依赖关系.主体具有关系中的主键,依赖外键也是Post / Poll表中的主键,因为它是一对一的关系.只有在一对多关系中,您将有一个单独的外键列.对于一对一的关系,您还必须删除外键列PostId和PollId,因为帖子通过其主键到Post和Poll.

在您的模型中似乎适合的替代方法是继承映射.那么模型将如下所示:

public abstract class BasePost  // your former Posts class
{
    public int ID { get; set; }
    public string UserName { get; set; }
}

public class Post : BasePost
{
    public string Text { get; set; }
    // other properties of the Post class
}

public class Poll : BasePost
{
    // properties of the Poll class
}

您不再需要TypeOfPost,因为您可以使用OfType LINQ运算符过滤两个具体类型,例如:

var x = context.BasePosts.OfType<Post>()
    .Where(p => p.UserName == "Jim")
    .ToList();

这将选择特定用户的所有帖子,而不是投票.

您必须决定要使用哪种继承映射 – TPH, TPT or TPC.

编辑

要获得一对多的关系,您可以在Fluent API中指定以下映射:

modelBuilder.Entity<Posts>()
    .HasOptional(x => x.Post)
    .WithMany()
    .HasForeignKey(x => x.PostID);

modelBuilder.Entity<Posts>()
    .HasOptional(x => x.Poll)
    .WithMany()
    .HasForeignKey(x => x.PollID);

外键属性必须为null(int?),如您已经找到的那样.因为您的外键属性的命名遵循命名约定EF用于映射,您可以完全省略Fluent映射.只有您有非常规的名称(如PostFK或某些东西)才需要.然后,您也可以使用数据注释([ForeignKey(…)]属性)而不是Fluent API.

相关文章
相关标签/搜索