当我的实体的IValidatableObject.Validate
方法被DbContext的SaveChangesAsync
方法调用时,EF6代理的引用有时为null。
多次运行相同的确切代码会导致不同的行为。如果我在Sku
方法之外检查我的股票的stock.Sku == null
属性(即Validate
),它将始终返回实体化实体。如果我不这样做并且仅在this.Sku
方法中检查Validate
,那么this.Sku
有时对于完全相同的实体而言为空。并且通过“完全相同的实体”,我的意思是我在所有测试运行中多次测试具有相同Id
和SkuId
的一个库存。我不是在这里创建新股票或更改其SkuId
属性的值。我正在做的一件事是调用股票的ChangeQuantity
方法,然后保存更改。
我最好的猜测是,一旦保存更改被调用,所有实体和参考实现都将被冻结。如果Sku
属性至少没有被访问过一次,那么当数据库上下文的保存更改代码调用我的对象的Validate
方法时,它将为null并保持为空。
我的问题是:为什么会发生这种情况?为什么我不能依赖于可以随时延迟加载的属性?
public abstract class StockBase : RecordBase
{
// Snipped //
[Required, Display(Name = "SKU")]
public Guid SkuId { get; set; }
[Display(Name = "SKU")]
public virtual Sku Sku { get; protected set; }
[Required]
public int Quantity { get; private set; }
[DataType("StockActions")]
public virtual ICollection<StockAction> Actions { get; private set; }
public void ChangeQuantity(DateTime logged, Guid loggedById, int changeInQuantity, string notes = null)
{
TrackChange(logged, loggedById);
Quantity += changeInQuantity;
Actions.Add(new StockAction(logged, loggedById, changeInQuantity));
}
}
public class StandardStock : StockBase, IValidatableObject
{
// Snipped //
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// Right here is where `this.Sku` is sometimes null!
if (Sku.IsExpiringStock)
{
throw new InvalidOperationException("Standard stock must have a non-expiring SKU.");
}
yield break;
}
}
答案 0 :(得分:1)
不幸的是,在通过Entity Framework执行验证期间,延迟加载被禁用。
https://msdn.microsoft.com/en-us/data/gg193959#Considerations
答案 1 :(得分:0)
看起来您正在使用延迟加载来填充Sku对象。手动测试Sku属性时,您正在强制运行延迟加载,并且值已实现。如果您在期望加载上下文时已经对上下文执行了某些操作,或者已经处理了上下文,那么它将保持为空。
如果您始终需要填充此属性,请考虑在加载实体时显式加载它。这将停止您的延迟加载问题,并且还可以消除数据库之旅。