在我的一個項目中,我使用實體框架和實體上的虛擬導航屬性。這意味着實體從數據庫加載或使用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; }
}
我希望有人能解釋這裏發生了什麼。
你WURE這些集合的導航屬性初始化時您使所有屬性都變爲虛擬,從而允許創建更改跟蹤代理?我認爲你錯了。這些集合屬性僅在您使用延遲加載並自動訪問它們時纔會自動實例化。如果不是,他們仍然是空的。 – JotaBe
@JotaBe:好點,但是在更改跟蹤代理的情況下,'Posts'屬性在被訪問之前被初始化。 –
這就是我的意思:始終初始化集合屬性,除非通過延遲加載來加載它,否則會得到「空引用異常」。 AFAIK集合屬性從不初始化,除非它們是懶惰,急切或顯式加載的。把它放在你的類構造函數中不會產生任何干擾。 – JotaBe