我有背包和书籍实体。书籍参考背包(一对多)。 我正在创建一个背包和一堆书籍的实例。所以在这种情况下,背包有很多书。我将这些实体保存到数据库中。我正在验证那些已保存到数据库中。当我尝试加载背包时,它加载正常,除导航属性外,所有属性都已设置。我也在检查是否禁用了LazyLoading。我的导航属性具有virtual关键字。 我不确定我做错了什么。如果我尝试使用Include()加载背包,则会加载书籍:
dbContext.Backpacks.Where(b=>b.Name!="").Include("Books").FirstOrDefault()
我想弄清楚为什么懒得加书?加载这本书时遇到同样的问题。当我装书时,它没有附加背包。我看到BackpackId就在那里。
在我的属性getter / setter中,我有一些会被解雇的逻辑,但我不确定这可能是一个什么问题。
答案 0 :(得分:3)
由于手头的信息有限,我可以看到您的问题的以下解释。
确保启用延迟加载和代理创建,第一个没有后者不起作用。
dbContext.Configuration.ProxyCreationEnabled = true;
dbContext.Configuration.LazyLoadingEnabled = true;
(详见Locale
)
Simplified,Lazy Loading的工作原理如下:
virtual
导航属性,即代理。 当然,最后一步只有在实体/代理仍然附加到上下文时才有可能,因此可以查询数据库以检索所述对象。
using( var dbContext = new MyContext() )
{
dbContext.Configuration.ProxyCreationEnabled = true;
dbContext.Configuration.LazyLoadingEnabled = true;
// Note: You can modify or derive from `MyContext` so that this is
// done automatically whenever a new `MyContext` is instantiated
var backpack = dbContext.Backpacks.Where(b=>b.Name!="").FirstOrDefault();
// This should work
var firstBook = backpack.Books.FirstOrDefault();
}
// This will probably not, because the context was already disposed
var firstDrink = backpack.Drinks.FirstOrDefault();
我希望这会有所帮助,但如果不是
,请随时提供更多信息答案 1 :(得分:3)
经过几天的调试,终于找到了问题所在。正如上面提到的那样,您必须启用LazyLoading和ProxyCreating。即使启用了LazyLoading和ProxyCreating,我也遇到了问题。另外,请确保将导航属性声明为virtual
,否则EF将无法懒惰地加载实体。
所以我遇到的问题是,由于我的实体没有带有NO参数的公共或受保护的构造函数,因此EF没有创建代理。在创建没有参数的public(在我的情况下受保护)构造函数之后,它工作了。
注意:没有参数的公共/受保护构造函数不会影响预先加载。
Here is a link that explains the requirements for the LazyLoading
答案 2 :(得分:1)
使用Include()
方法实现了预先加载,因此您使用Include("Books")
强制进行预先加载。
改变这个:
dbContext.Backpacks.Where(b=>b.Name!="").Include("Books").FirstOrDefault()
到此:
dbContext.Backpacks.Where(b=>b.Name!="").FirstOrDefault()
您现在应该看到Books
不再被急切加载。
<强>参考:强>
答案 3 :(得分:0)
我必须使用.NET Core 3.1和Microsoft.EntityFrameworkCore 3.1.5 ...
1)添加Microsoft.EntityFrameworkCore.Proxies
NuGet程序包
2)将DbContext
配置为UseLazyLoadingProxies
(在Startup.cs
中)
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDbContext<DataContext>(optionsBuilder =>
{
optionsBuilder
.UseLazyLoadingProxies() // <--- You need this bit
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
});
...
}
3)将所有适当的属性(您要延迟加载的属性)标记为virtual
public class MyEntity
{
public virtual OtherEntity? { get; set; } // Lazy loaded coz `virtual`
public ICollection<OtherEntity> { get; set; } // NOT lazy loaded coz not `virtual`
}