EF core 3.1:使用预先加载加载相关实体时,是否应该初始化列表导航属性?
EF core 3.1: should I initialize list navigation properties when using eager loading to load related entities?
考虑以下 EF 核心 3.1 数据模型:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Author { get; set; }
public DateTime Date { get; set; }
public Blog Blog { get; set; }
public int BlogId { get; set; }
}
public class BlogAppContext: DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=DB_BLOG_APP;Integrated Security=SSPI;MultipleActiveResultSets=True");
}
public DbSet<Post> Posts { get; set; }
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasMany(x => x.Posts)
.WithOne(x => x.Blog)
.HasForeignKey(x => x.BlogId)
.IsRequired();
}
}
考虑这样一个场景,我 运行 使用预先加载的以下查询:
static void Main(string[] args)
{
using var context = new BlogAppContext();
var blogs = context.Blogs.Include(x => x.Posts).ToList();
foreach (var blog in blogs)
{
Console.WriteLine($"There are {blog.Posts.Count} posts");
}
}
通过查看一些示例,我注意到初始化列表导航属性是一种常见的做法。在我的例子中,这会导致这样的结果:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public List<Post> Posts { get; set; } = new List<Post<();
}
我在问这在通过预加载查询时是否真的有用。
我做了一些测试,我已经验证了上面显示的查询自动为没有帖子的博客创建了一个空列表。
换句话说,似乎即使 Posts
导航 属性 也没有 初始化为 Blog
中的空列表实体定义,使用预加载的查询不关心 not return Posts
导航的 null
值 属性.
我的理解正确吗?
如果是这样,在使用预先加载加载相关实体查询数据库时,将Posts
导航属性初始化为空列表有什么用处(如果有的话)?
这没有用,您不必这样做,因为您正在使用预先加载(如果您加载大量不必要的数据,效率不是很高,但这是另一个话题)。
但是,这在两种情况下很有用:
- 如果你不使用预加载,因为
Posts
属性 可能是 null
- 您正在创建一个新的
Blog
对象,该对象尚未保存在数据库中,您想要向其中添加一个新的 Post
。在这种情况下 Posts
属性 必须在调用 Posts.Add(post)
之前初始化,因为将抛出 null ref 单元化异常。
考虑以下 EF 核心 3.1 数据模型:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Author { get; set; }
public DateTime Date { get; set; }
public Blog Blog { get; set; }
public int BlogId { get; set; }
}
public class BlogAppContext: DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=DB_BLOG_APP;Integrated Security=SSPI;MultipleActiveResultSets=True");
}
public DbSet<Post> Posts { get; set; }
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasMany(x => x.Posts)
.WithOne(x => x.Blog)
.HasForeignKey(x => x.BlogId)
.IsRequired();
}
}
考虑这样一个场景,我 运行 使用预先加载的以下查询:
static void Main(string[] args)
{
using var context = new BlogAppContext();
var blogs = context.Blogs.Include(x => x.Posts).ToList();
foreach (var blog in blogs)
{
Console.WriteLine($"There are {blog.Posts.Count} posts");
}
}
通过查看一些示例,我注意到初始化列表导航属性是一种常见的做法。在我的例子中,这会导致这样的结果:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public List<Post> Posts { get; set; } = new List<Post<();
}
我在问这在通过预加载查询时是否真的有用。
我做了一些测试,我已经验证了上面显示的查询自动为没有帖子的博客创建了一个空列表。
换句话说,似乎即使 Posts
导航 属性 也没有 初始化为 Blog
中的空列表实体定义,使用预加载的查询不关心 not return Posts
导航的 null
值 属性.
我的理解正确吗?
如果是这样,在使用预先加载加载相关实体查询数据库时,将Posts
导航属性初始化为空列表有什么用处(如果有的话)?
这没有用,您不必这样做,因为您正在使用预先加载(如果您加载大量不必要的数据,效率不是很高,但这是另一个话题)。
但是,这在两种情况下很有用:
- 如果你不使用预加载,因为
Posts
属性 可能是null
- 您正在创建一个新的
Blog
对象,该对象尚未保存在数据库中,您想要向其中添加一个新的Post
。在这种情况下Posts
属性 必须在调用Posts.Add(post)
之前初始化,因为将抛出 null ref 单元化异常。