c# - 延迟加载导航属性返回 'System.InvalidOperationException'

标签 c# entity-framework-core visual-studio-2019 .net-core-3.0

我一直在将使用 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_PartParts.ID 通过外键链接到表 Parts

当您使用 EF-Core DB-First 构建您的 DbContext 时,它会创建名为“导航属性”的虚拟属性,以便您轻松访问其他表中的链接信息。

每当您尝试访问 IDPartNavigation 时都会抛出异常。这是一个例子:

Navigation Property Error

它也不是 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的范围有关。当您结合使用 USINGPROXIES 时,就会发生这种情况。

我已经为我的函数编写了另一个定义,但这次通过参数传递连接,而不是使用 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/

相关文章:

c# - Null-Coalescing 运算符 - 为什么要转换?

c# - Dictionary ContainsKey 似乎不适用于 string[] 键

c# - 如何在 winRT xaml 应用程序中启动 native map 应用程序?

git - 为什么 Visual Studio 中的 git Pull 按钮被禁用了?

c# - 这个 C# 功能有名称吗?它有什么作用?

entity-framework-core - 'Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal.SqlServerOptionsExtension 类型中的方法 'get_Info'

c# - LINQ - EF Core - 返回嵌套列表中包含两个对象(由属性引用)的对象

c# - 如何查看传递给 EF Core 查询的参数?

c++ - 使用 Visual Studio 2019 显示 CMake 的编译器命令行

c# - 如何在 Visual Studio 2019 中向我的 C# 程序添加 list 文件?