我正在使用 Entity Framework 6.x,一个实体看起来像这样(有些简化):
public partial class Record
{
public int Id { get; set; }
public string Name { get; set; }
public Nullable<int> XmlFormatID { get; set; }
public virtual XmlFormat XmlFormat { get; set; }
}
我是这样使用它的,但在实际代码中它使用不同的方法:
Record record = null;
using(var context = new DbContext())
{
record = context.Records.FirstOrDefault(x => x.Id == id);
}
// Now the context is (correctly) disposed.
if (record.XmlFormatID.HasValue && record.XmlFormat != null)
{
// It crashes before in this if.
}
上面的代码产生了这个异常:
record.XmlFormat = 'record.XmlFormat' threw an exception of type 'System.ObjectDisposedException'
我知道这个错误是因为我在处理上下文时尝试延迟加载实体。我也知道我可以简单地将代码更改为 context.Records.Include(x => x.XmlFormat)
,或者在上下文打开时执行 if-case。
问题是这条线在应用程序的不同地方被重复使用。
if (record.XmlFormatID.HasValue && record.XmlFormat != null)
{
// It crashes in this if.
}
有时在上下文中,有时当我使用包含时,有时当它不包含时。所以我的问题是:
我如何进行 null 检查并考虑到它应该在处理上下文时起作用?我没有访问 DbContext
当我进行 null 检查时。
我有 3 种情况:
record.XmlFormat
是预先加载的。然后我想使用预先加载的XmlFormat
。record.XmlFormat
不是预先加载的,但上下文是开放的。然后我想延迟加载它。record.XmlFormat
未预先加载,上下文已释放。然后我根本不想输入if
并将XmlFormat
视为null
。
最佳答案
据我所知,你做不到。但您可以尝试以下三个选项:
第一个选项。
作为一种解决方法,我建议您关闭LazyLoading
并在需要时使用EagerLoading
获取数据(如您所知) .您可以在上下文的构造函数中全局执行此操作:
public MyContext : base("Name=MyContext")
{
// Turn off lazy loading and proxy creation
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
或者,如果您想在应用程序的其他部分使用延迟加载,您可以在加载时执行 Record
:
Record record = null;
using(var context = new DbContext())
{
// Turn of lazy loading and proxy creation.
// Disabling one of these also should be enough.
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
// Load record
record = context.Records.FirstOrDefault(x => x.Id == id);
}
// Check for null
if (record.XmlFormatID.HasValue && record.XmlFormat != null)
{
}
如果你不想重复编写延迟加载禁用代码,你可以添加处理它的构造函数:
public MyContext(bool enableLazyLoading)
: this()
{
this.Configuration.LazyLoadingEnabled = enableLazyLoading;
this.Configuration.ProxyCreationEnabled = enableLazyLoading;
}
然后将其用作:
using(var context = new DbContext(false))
{
record = context.Records.FirstOrDefault(x => x.Id == id);
}
第二个选项。
如果您可以访问上下文,则可以通过检查 Database.Connection
来检查它是否已被释放。将此方法添加到您的上下文中:
public bool IsDisposed()
{
bool isDisposed = false;
try
{
isDisposed = Database.Connection != null;
}
catch (InvalidOperationException ex)
{
isDisposed = true;
}
return isDisposed;
}
然后将检查添加到您的 if
条件:
Record record = null;
Context context = null;
using(context = new DbContext())
{
record = context.Records.FirstOrDefault(x => x.Id == id);
}
// Check
if (context != null
&& !context.IsDisposed()
&& record.XmlFormatID.HasValue
&& record.XmlFormat != null)
{
}
第三个选项
最后但同样重要的是,您始终可以处理 ObjectDisposedException
。将此方法添加到您的 Record
模型中:
class Record
{
...
public bool IsXmlRootLoaded
{
bool isLoaded = false;
try
{
isLoaded = XmlFormatID.HasValue && XmlFormat != null;
}
catch(ObjectDisposedException ex)
{
isLoaded = false;
}
return isLoaded;
}
}
然后检查是否加载了XmlFormat
:
if(record.IsXmlRootLoaded())
{
// Do what you want.
}
关于c# - 在空检查中获取 ObjectDisposedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39159077/