【问题标题】:Navigation property with additional constraint具有附加约束的导航属性
【发布时间】:2012-01-04 02:18:05
【问题描述】:

我是 EF 和 CodeFirst 的新手,我有以下(简化的)模型:

public class Comment
{
    public int ID {get; set;}
    public int SourceType {get; set;}
    public int SourceID {get; set;}
    public string Name {get; set;}
    public string Text {get; set;}
}

public class Photo
{
    public int ID {get; set;}
    public virtual ICollection<Comment> Comments {get; set;}
}

public class BlogPost
{
    public int ID {get; set;}
    public virtual ICollection<Comment> Comments {get; set;}
}

在我的实际数据库中,我只有这三个表。 我的目标是有一个表“cmets”,它存储 cmets 用户发布的照片​​和博客帖子。 Comment.SourceType 字段应该区分发布到照片的评论 (SourceType==1) 或博客文章 (SourceType==2),而 Comment.SourceID 字段告诉我来源的 ID。

Photo photo = DbContext.Photos.Find(15); //some photo with ID 15
BlogPost blog = DbContext.BlogPost.Find(15); //some blog post, also with ID 15

Comment photoComment = new Comment();
photoComment.SourceType = 1; //photo
photoComment.SourceID = photo.ID;
photoComment.Name = "John";
photoComment.Text = "This is a very nice picture!";

Comment blogComment = new Comment();
blogComment.SourceType = 2; //blog post
blogComment.SourceID = blog.ID;
blogComment.Name = "Peter";
blogComment.Text = "An interesting blog post!";

DbContext.Comments.Add(photoComment);
DbContext.Comments.Add(blogComment);
DbContext.SaveChanges();

//...

Photo photoFromBefore = DbContext.Photos.Find(15);
foreach(Comment comment in photoFromBefore.Comments)
    Console.Write(comment.Name+"("+comment.SourceType+", "+comment.SourceID+"); ");
//Output will be: "John(1, 15); Peter(2, 15);"
//Desired output should be instead just "John(1, 15);"
//because Peter's comment actually belongs to blog post with
//the same ID but different "SourceType"-identifier in my database table.

我希望以某种方式清楚我想要实现的目标。基本上,我不希望有多个表 photo_commentsblogpost_comments 等用于我网站上可以评论的所有内容。

我能否以某种方式告诉 EF 仅加载带有 SourceType==1 的 cmets(用于照片)?我可以使用某种“约束”或“限制”来实现这一目标吗?

【问题讨论】:

    标签: c# asp.net-mvc entity-framework ef-code-first


    【解决方案1】:

    您应该能够在 foreach 语句中使用 LINQ where 子句。

    foreach(Comment comment in photoFromBefore.Comments.Where(x=>x.SourceType == 2))
    

    另外,看代码,foreach 上面的那行应该是

    IEnumerable<Photo> photoFromBefore = DbContext.Photos.First(15);
    

    【讨论】:

    • 这就是我试图避免的 :) EF 的全部目的是减少工作量。我知道我可以手动加载 cmets,但 Photo.Comments 是一个导航属性,当我调用它时它会自动加载所有照片的 cmets。另外,您对不正确的代码是正确的。我现在纠正了一个错字(“First”而不是“Find”)。谢谢。
    • 您的问题将是照片和博客是两个不同的表(对吗?)。由于它们是两个不同的表,因此它们将具有两组主键。所以 - 你可以拥有一个 ID 为 1 的博客和一张 ID 为 1 的照片。如果不在 Find 语句中指定 where 子句(sourcetype == x),EF 就无法知道根据该 ID 加载哪个评论。导航属性是等效于 FK 的代码 - 您将值从表 a col x 映射到表 b col y。如果您试图避免 where 子句,您可以将源类型存储在您的照片和博客表中...
    • 是的,我知道这个问题 :) 我试图弄清楚是否有办法让 EF 知道 加载哪个评论。例如使用流体 API。用modelBuilder.Entity&lt;Photo&gt;().Property(p =&gt; p.Comments).HasCondition(c =&gt; c.SourceType == 1);modelBuilder.Entity&lt;BlogPost&gt;().Property(b =&gt; b.Comments).HasCondition(c =&gt; c.SourceType == 2); 之类的东西覆盖OnModelCreating(DbModelBuilder modelBuilder)。我只是在这里吐口水,但我想知道这样的事情是否可能?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多