我一直在将使用 EF6 的 VB.net 应用程序迁移到使用 EF-Core 3.0 的 C# .Net Core 应用程序。我一直使用 EF 作为 DB-First。使用 EF-Core,我需要指定我想要加载我的值的方式。因为我经常需要访问许多导航属性(通过 FK 链接到其他表),所以我宁愿使用 Lazy Load 而不是管理 Eager Loads。但是每当我想这样做时,我都会在导航属性上收到此错误:
((CaSTLe.Proxies.WillyDemandesProxy)willyDemandes).IdPartNavigation
引发了“System.InvalidOperationException”类型的异常:
因警告“Microsoft.EntityFrameworkCore.Infrastructure.LazyLoadOnDisposedContextWarning:在处理关联的 DbContext 后尝试在实体类型“WillyDemandesProxy”上延迟加载导航属性“IdPartNavigation”而生成错误。”。通过将事件 ID“CoreEventId.LazyLoadOnDisposedContextWarning”传递给“DbContext.OnConfiguring”或“AddDbContext”中的“ConfigureWarnings”方法,可以抑制或记录此异常。
表 WillyDemandes 使用 WillyDemande.Id_Part 和 Parts.ID 通过外键链接到表 Parts。
当您使用 EF-Core DB-First 构建您的 DbContext 时,它会创建名为“导航属性”的虚拟属性,以便您轻松访问其他表中的链接信息。
每当您尝试访问 IDPartNavigation 时都会抛出异常。这是一个例子:
它也不是 100% 的时间发生。
有什么想法吗?
上下文
/// <summary>
/// https://learn.microsoft.com/en-us/ef/core/querying/related-data
/// </summary>
/// <param name="optionsBuilder"></param>
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseLazyLoadingProxies();
//optionsBuilder.ConfigureWarnings(warnings => warnings.Default(WarningBehavior.Ignore));
optionsBuilder.UseSqlServer("Server=TRBSQL02;Database=Info_Indus;Trusted_Connection=True;");
}
}
函数
static public WillyDemandes GetFirst()
{
using (Info_IndusContext conn = new Info_IndusContext())
{
WillyDemandes willyDemandes;
willyDemandes = conn.WillyDemandes
.Where(x => x.Statut == Statuts.EnTest.ToString() && x.Username == Environment.UserName)
//.Include(x=>x.IdPartNavigation)
.OrderBy(x => x.Priority)
.ThenBy(x => x.Id)
.FirstOrDefault();
if (willyDemandes != null)
{
willyDemandes.Statut = Statuts.EnTraitement.ToString();
willyDemandes.ServerName = Environment.MachineName;
willyDemandes.DateDebut = DateTime.Now;
conn.SaveChanges();
conn.Entry(willyDemandes).GetDatabaseValues();
conn.Entry(willyDemandes).Reload();
}
return willyDemandes;
}
}
以前在 Vb.Net 中
Public Function Demande_GetFirst() As WillyDemandes
Dim conn As New Info_IndusEntities(False)
Dim DemandeWilly As WillyDemandes = conn.WillyDemandes.Where(Function(x) x.Statut = Statuts.EnTest.ToString AndAlso x.Username = Environment.UserName).OrderBy(Function(x) x.Priority).ThenBy(Function(x) x.ID).FirstOrDefault
If Not IsNothing(DemandeWilly) Then
DemandeWilly.Statut = Statuts.EnTraitement.ToString
DemandeWilly.ServerName = Environment.MachineName
DemandeWilly.DateDebut = DateTime.Now
conn.SaveChanges()
End If
Return DemandeWilly
End Function
2019/05/21
错误似乎与DbContext的范围有关。当您结合使用 USING 和 PROXIES 时,就会发生这种情况。
我已经为我的函数编写了另一个定义,但这次通过参数传递连接,而不是使用 USING 在函数内部创建它。然后,只要 DbContext 处于事件状态,代理就可用。
static public WillyDemandes GetFirst(Info_IndusContext conn)
{
WillyDemandes willyDemandes;
willyDemandes = conn.WillyDemandes
.Where(x => x.Statut == Statuts.EnTest.ToString() && x.Username == Environment.UserName)
//.Include(x=>x.IdPartNavigation)
.OrderBy(x => x.Priority)
.ThenBy(x => x.Id)
.FirstOrDefault();
if (willyDemandes != null)
{
willyDemandes.Statut = Statuts.EnTraitement.ToString();
willyDemandes.ServerName = Environment.MachineName;
willyDemandes.DateDebut = DateTime.Now;
conn.SaveChanges();
conn.Entry(willyDemandes).GetDatabaseValues();
conn.Entry(willyDemandes).Reload();
}
return willyDemandes;
}
最佳答案
所以我找到了解决这个问题的方法,但我怀疑这是最好的解决方案。
基本上,我所做的是创建了一个 ContextProvider 类,它允许我创建 1 个每个人都可以访问的 Info_IndusContext。我还删除了 Controller 的所有USING 语句。
我也放弃了使用 LazyLoading 并开始使用 EagerLoading,您可能会在下面的 GetFirst 函数中注意到这一点。
想法?
上下文提供者
using WillyServer.Models;
namespace WillyServer.Controllers
{
public static class ContextProvider
{
public static Info_IndusContext db = new Info_IndusContext();
}
}
WillyDemandesController.GetFirst
static public WillyDemandes GetFirst()
{
WillyDemandes willyDemandes = ContextProvider.db.WillyDemandes
.Include(x => x.IdPartNavigation)
.Include(x => x.WillyMachines)
.Where(x => x.Statut == Statuts.EnTest.ToString() && x.Username == Environment.UserName)
.OrderBy(x => x.Priority)
.ThenBy(x => x.Id)
.FirstOrDefault();
if (willyDemandes != null)
{
willyDemandes.Statut = Statuts.EnTraitement.ToString();
willyDemandes.ServerName = Environment.MachineName;
willyDemandes.DateDebut = DateTime.Now;
ContextProvider.db.SaveChanges();
}
return willyDemandes;
}
关于c# - 延迟加载导航属性返回 'System.InvalidOperationException',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56190607/