添加ICollection和简单地添加一个字段来存储另一个表的密钥有什么区别?

时间:2014-07-28 18:35:05

标签: c# asp.net-mvc entity-framework asp.net-mvc-4

以下代码中的两组Code First模型之间有什么区别。我相信第一种方式是普遍实践的。但我也发现第二种方法更容易,因为我们只需要将一个键存储到与另一个表相关的项目中。与第二种方式相比,使用它有什么好处吗?我很乐意清除这个问题中的任何混淆。感谢。

方法1:

public class Blog{
public int BlogId {get;set;}
public string Name {get;set;}
public int Category {get;set;}
public ICollection<Post> Posts{get;set;}
}


public class Post{
public int PostId{get;set;}
public string Contents {get;set;}
public DateTime Date{get;set;}
public string Author {get;set;}
public Blog Blog {get;set;}
}

方法2:

public class Blog{
public int BlogId {get;set;}
public string Name {get;set;}
public int Category {get;set;}
}


public class Post{
public int PostId{get;set;}
public string Contents {get;set;}
public DateTime Date{get;set;}
public string Author {get;set;}
public int BlogId {get;set;}
}

3 个答案:

答案 0 :(得分:2)

嗯,主要的区别当然是没有办法用第二种方法从Blog实例直接访问博客的帖子。如果您想要获得该博客的帖子,您必须发出单独的查询,例如:

db.Posts.Where(m => m.BlogId == blog.BlogId)

这样做的另一件事是禁止实体框架能够懒惰或急于加载博客的帖子。例如,使用第一种方法,您可以执行以下操作:

var blog = db.Blogs.Include("Posts").SingleOrDefault(m => m.BlogId == blogId);

通过这样做,您就可以遍历博客的Posts集合,而无需向数据库发出另一个查询;实体框架将进行联接以在一个查询中包含所有帖子。

此外,如果您将virtual添加到该集合属性:

public virtual ICollection<Post> Posts { get; set; }

您可以延迟加载结果集,以便给出:

var blog = db.Blogs.Find(blogId);

您可以立即执行以下操作:

foreach (var post in blog.Posts)
{
    // whatever
}

它会向数据库发出另一个查询以在那时检索Posts集合,但您不必担心明确查询属于该博客的帖子作为第一个代码示例上面显示。

答案 1 :(得分:0)

坦率地说,我更喜欢你的第二种方法。我并不关心第一个例子说明的Blog和Post之间的循环引用。这不是一个真正的答案,而是一个观点。您的第二种方法更清晰地映射到RDMBS。

第一个看起来像是Entity Framework的自动生成产品,其中Blog知道其子帖子,但孩子本身完全了解其关联的Blog。在ADO.NET中使用具有子行的DataTable找到这种父/子到父动态的父类,然后可以将行本身追溯到完全加载的父表。我认为它适用于较重的对象和堆上的更多引用。

我坚持第二种方法,然后有一些聚合对象,包括博客和一组帖子。

public class BlogWithPosts
{
    public Blog @Blog { get; set; }
    public IEnumerable<Post> Posts { get; set; }
}

答案 2 :(得分:0)

您的第二种方法无效。

使用第二种方法,您如何在BlogPost之间建立关系? 您需要在Post上提供Blog个集合,或在Blog上提供Post个参考。

我仍然不了解OP第二种方法。

public class AppContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Compile error, the type int must be a reference type...
        //modelBuilder.Entity<Post>().HasRequired(p => p.BlogId).WithMany();
    }
}
public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public class Post
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int BlogId { get; set; }
}