我正在使用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,它提供了 AmbientTransactionWarning
当 UseMySql
被调用。另外,当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的各个部分,但一直没能在这个方向上得到任何效果。
这可能是解决依赖性程序集的问题。
你可能想要调试你的 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;
}