我有一个实体,帖子:
public class Post
{
[Key]
[Required]
public int PostId { get; set; }
}
我有另一个实体,Response
:
public class Response
{
[Key]
[Required]
public int ResponseId{ get; set; }
public int PostId {get; set;}
public int ParentResponseId {get; set;}
}
这个想法是,Response
要么定义了ParentResponseId
,要么PostId
- 但不是两者都有。 Post
可以有很多回复,Response
可以有很多回复。
我永远不需要通过virtual
属性从一个导航到另一个,也不需要延迟加载 - 我只需要在数据库中设置约束。
我是modelBuilder的新手,但这似乎是必须使用它的情况。我有一个起点:
modelBuilder.Entity<Response>()
.HasOptional(c => c.Post)
.HasForeignKey(u => u.PostId);
modelBuilder.Entity<Response>()
.HasOptional(c => c.Response)
.HasForeignKey(u => u.ParentResponseId);
这是处理可选的一对多的正确方法吗?有没有办法添加一个约束,说“需要定义一个或另一个FK”?这里的任何指导都将非常感激。
答案 0 :(得分:1)
您现在需要有4个班级
public class Post
{
[Key]
[Required]
public int PostId { get; set; }
public virtual ICollection<PostResponse> Responses { get; set; }
}
public abstract class Response //abstract to never get just a simple response
{
[Key]
[Required]
public int ResponseId{ get; set; }
public string Message { get; set; }
}
public class PostResponse : Response
{
[Required]
public int PostId { get; set; }
public Post Post { get; set; }
}
public class ResponseReply : Response
{
[Required]
public int ParentResponseId { get; set; }
public virtual Response ParentResponse { get; set; }
}
在您的ModelBuilder块中:
modelBuilder.Entity<PostResponse>()
.ToTable("PostResponse")
.HasRequired(c => c.Post)
.WithMany(c => c.Responses)
.HasForeignKey(u => u.PostId);
modelBuilder.Entity<ResponseReply>()
.ToTable("ResponseReply")
.HasRequired(c => c.ParentResponse)
.WithMany()
.HasForeignKey(u => u.ParentResponseId);
这将为您创建3个表,以便处理模型中的响应想法。
这有助于您强制实际需要PostId和ParentResponseId,并在单独的表中创建 "NOT NULL"
列。
如果您不想要单独的表并将外键保留为数据库中的可选项,只需从模型构建器块中删除 ToTable()
调用。
希望这会有所帮助
答案 1 :(得分:0)
您可以从Reponse
继承Post
并且只有一个外键,因此您永远不必担心应该设置哪个FK:
public class Post
{
public int PostId { get; set; }
public Post ParentPost { get; set; }
public int? ParentPostId { get; set; }
}
public class Response : Post
{
}
使用映射:
modelBuilder.Entity<Post>()
.HasOptional(p => p.ParentPost)
.WithMany()
.HasForeignKey(p => p.ParentPostId);
现在,如果你这样做
var a = new Post();
var b = new Response { ParentPost = a };
var c = new Response { ParentPost = b };
db.Posts.Add(c);
db.SaveChanges();
你会得到
PostId ParentPostId Discriminator
----------- ------------ -------------
1 NULL Post
2 1 Response
3 2 Response
如果帖子和回复本质上是不同的东西,也许这不起作用,但我很难想象是这样的。