在Revit addin中使用EF Core的MissingFieldException (AmbientTransactionWarning)。

问题描述 投票:0回答:1

我正在使用Pomelo.EntityFrameworkCore.MySql(3.1.1)来保存一些数据到MySql。当第一次配置上下文时,我得到了这个异常。

在Pomelo.EntityFrameworkCore.MySql.dll中抛出异常:"System.MissingFieldException"。

未找到字段:"Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.AmbientTransactionWarning

这是我的 OnConfiguring:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        // This works just fine, even though that type is then not available in `UseMySql`.
        var test = Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.AmbientTransactionWarning; 

        // Exception thrown here.
        optionsBuilder.UseMySql("server=localhost;database=test;uid=user;pwd=<password>;TreatTinyAsBoolean=true;", x => x.ServerVersion(new Version(5, 7, 29), ServerType.MySql)); 
    }
}

可能的复杂因素。该应用程序是Autodesk Revit的插件。我有一些dll加载问题,我相信我已经解决了,但它是一个非标准环境,可能会导致问题。我已经验证了 Microsoft.EntityFrameworkCore.Relational的dll,它提供了 AmbientTransactionWarningUseMySql 被调用。另外,当VS在异常上暂停时,如果我输入了 Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.AmbientTransactionWarning 在立即窗口中,我没有得到一个错误。我还有另一个独立的WPF应用,使用同样的数据库模型和DbContext对象,它与数据库的通信也很好。

我不知道该如何继续调试这个问题。谢谢

编辑

addin和Revit(2020)都使用.NET框架4.7.2。

Stacktrace:

Field not found: 'Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.AmbientTransactionWarning'.

   at Microsoft.EntityFrameworkCore.MySqlDbContextOptionsExtensions.ConfigureWarnings(DbContextOptionsBuilder optionsBuilder)

   at Microsoft.EntityFrameworkCore.MySqlDbContextOptionsExtensions.UseMySql(DbContextOptionsBuilder optionsBuilder, String connectionString, Action`1 mySqlOptionsAction)

   at <MyAssembly>.DatabaseContext.OnConfiguring(DbContextOptionsBuilder optionsBuilder)

库加载

通常情况下,Revit插件会根据需要自动加载其依赖关系。但偶尔也会出现这种情况,所以我添加了下面的解析器,它可以手动加载在过去运行中无法自动加载的装配体,我越看越觉得这个问题在我的主装配体中可用,但在EntityFrameworkCore中却没有。

    // Executed on first run of addin.
    AppDomain.CurrentDomain.AssemblyResolve += ResolveMissingAssemblies;

...

private System.Reflection.Assembly ResolveMissingAssemblies(object sender, ResolveEventArgs args)
{
    string[] dlls = new[]
    {
        "System.Memory",
        "System.Buffers",
        "System.Threading.Tasks.Extensions",
        "System.Runtime.CompilerServices.Unsafe",
        "Microsoft.EntityFrameworkCore.Relational",
        "Microsoft.EntityFrameworkCore",
        "MySqlConnector",
    };

    string dll = dlls.FirstOrDefault(name => args.Name.Contains(name));

    if (!string.IsNullOrEmpty(dll))
    {
        string filename = Path.Combine(
            Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
            $"{dll}.dll");

        if (File.Exists(filename))
        {
            return System.Reflection.Assembly.LoadFrom(filename);
        }
    }

    return null;
}

我越看越觉得这个字段在我的主装配体中是可用的,但在EntityFrameworkCore中却没有。我不知道为什么会这样,也不知道为什么会这样。我也试过用IlMerge来组合addin的各个部分,但一直没能在这个方向上得到任何效果。

c# revit-api pomelo-entityframeworkcore-mysql
1个回答
1
投票

这可能是解决依赖性程序集的问题。

你可能想要调试你的 ResolveMissingAssemblies() 方法(或记录所有事件处理程序无法解析的程序集)。

同时输出看看 ResolveEventArgs.RequestingAssembly 属性,它告诉你当前程序集是哪个程序集的依赖关系(以了解依赖树)。

列表中的 Microsoft.EntityFrameworkCore.Relational 装配,如:取决于 Microsoft.EntityFrameworkCore,它依赖于10个其他库(其中一些库又依赖于其他库)。

一个简单的方法是让你的事件处理程序更通用,以确保它们都被加载。

private System.Reflection.Assembly ResolveMissingAssemblies(object sender, ResolveEventArgs args)
{
    string filename = Path.Combine(
        Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
        $"{args.Name}.dll");

    return File.Exists(filename))
        ? System.Reflection.Assembly.LoadFrom(filename)
        : null;
}
© www.soinside.com 2019 - 2024. All rights reserved.