在我的一个项目中,我使用Entity Framework和实体上的虚拟导航属性。这意味着实体从数据库加载或使用IDbSet<T>.Create()
创建,返回DynamicProxy。因为我只将导航属性设置为虚拟,所以此代理会进行延迟加载而不进行更改跟踪(所有属性都需要virtual
才能获得更改跟踪代理)。
我的假设是DynamicProxy负责初始化虚拟ICollection<T>
属性,就像从数据库加载实体时一样。但是当我使用IDbSet<T>.Create()
创建新实体时,这些导航属性仍为null
。
然后我尝试制作所有属性virtual
,因此我获得了一个带有更改跟踪的DynamicProxy,令我惊讶的是这些导航属性已初始化。
请参阅以下示例:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
static class Program
{
static void Main()
{
using (var db = new BloggingContext())
{
var changeTrackingBlog = db.ChangeTrackingBlogs
.Create(); // returns a DynamicProxy
var changeTrackingBlogPostCount = changeTrackingBlog
.Posts
.Count; // Posts has type EntityCollection<Post>
var lazyLoadingBlog = db.LazyLoadingBlogs
.Create(); // returns a DynamicProxy
var lazyLoadingBlogPostCount = lazyLoadingBlog.Posts
.Count; // Posts == null
}
}
}
public class BloggingContext : DbContext
{
public IDbSet<Post> Posts { get; set; }
public IDbSet<ChangeTrackingBlog> ChangeTrackingBlogs { get; set; }
public IDbSet<LazyLoadingBlog> LazyLoadingBlogs { get; set; }
}
public class Post
{
[Key]
public int PostId { get; set; }
public virtual ChangeTrackingBlog ChangeTrackingBlog { get; set; }
public virtual LazyLoadingBlog LazyLoadingBlog { get; set; }
}
public class ChangeTrackingBlog
{
[Key]
public virtual int BlogId { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class LazyLoadingBlog
{
// Not all properties are virtual, so no Change tracking, just lazy loading
[Key]
public int BlogId { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
我希望有人能解释这里发生的事情。
答案 0 :(得分:2)
避免空引用的常用方法是在构造函数中初始化集合:
public LazyLoading()
{
Posts = new List();
}
我认为使用支持字段可能是更好的做法 - 与在某些情况下不被调用的匿名构造函数(序列化或某些东西 - 模糊的道歉)有关。所以我这样做:
public class LazyLoadingBlog
{
private ICollection<Post> _Posts = new List<Post>();
public virtual ICollection<Post> Posts
{
get { return _Posts ; }
//protected set lets EF override for lazy loading
protected set { _Posts = value;
}
}
不幸的是,当你将所有属性标记为虚拟时,我无法解释为什么你没有收到错误...