我正在使用Microsoft docs来模仿DbContext
。我在查询IOrderedQueryable
时遇到问题。
var report = new Report();
report.DataSource = null;
var q = context.Reports.Select(x => x.DataSource).OrderBy(x => x.Name);
var results = q.ToList();
当我致电ToList
时,它会在此行的TestDbAsyncEnumerator.MoveNextAsync
中引发错误
return Task.FromResult(_inner.MoveNext())
错误:
System.AggregateException:发生了一个或多个错误 System.NullReferenceException:未将对象引用设置为对象的实例。
在lambda_method(关闭,经验)
在System.Linq.EnumerableSorter2.ComputeKeys(TElement[] elements, Int32 count)
1.Sort(TElement []元素,Int32计数)
at System.Linq.EnumerableSorter
在System.Linq.OrderedEnumerable1.<GetEnumerator>d__1.MoveNext()
1.MoveNextAsync(CancellationToken cancellationToken)
at S360.Tests.TestDbAsyncEnumerator
如果我删除OrderBy
或OrderBy x => 0
,一切正常。我可以如何模拟DbContext
以便我的查询不会抛出任何异常的任何解决方案?
答案 0 :(得分:0)
请参阅Microsoft文档中的Limitations of EF in-memory test doubles
。
当您在.DataSource
中投射到Select()
时,很可能是null,当您尝试访问.Name
中的OrderBy()
时,会导致NullReferenceException。
当您对数据库执行此可查询时,EF将看到DataSource
导航属性的访问权限,并包含JOIN
以便获取它。
在内存中执行时,不会发生此连接。
您可以将预期的DataSource
实体添加到测试设置中的Reports
实体,或者更好地使用Effort in-memory provider,这将填充导航属性,就像真正的数据库一样会。
答案 1 :(得分:0)
就我而言,我还收到了与lambda_method相关的异常:
System.NullReferenceException occurred
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at lambda_method(Closure , InspectionAsset )
at System.Linq.Enumerable.<>c__DisplayClass6_0`1.<CombinePredicates>b__0(TSource x)
at System.Linq.Enumerable.WhereListIterator`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at AssetManagement.Model.Repositories.AssetDataService.<LoadOtherAssetsFromTrackAsset>d__18.MoveNext() in C:\src\AssetManagement\AssetManagement.Model\Repositories\AssetDataService.cs:line 135
InnerException:
对我来说,我最初是在像query = query.Where(filter);
那样构建数据,
using Nito.AsyncEx;
// ...
private static readonly AsyncLock _assetsMutext = new AsyncLock();
public List<Expression<Func<sset, bool>>> Filters { get; } = new List<Expression<Func<Asset, bool>>>();
// ...
public async Task<IQueryable<Asset>> LoadAssetsOnTrack(IList<Asset> trackAssets, List<Asset> assets)
{
IQueryable<IAsset> query = null;
await Task.Run(async () =>
{
using (await _assetsMutext.LockAsync())
{
var equipmentList = this.GetEquipment();
Parallel.ForEach(trackAssets, (asset, state) =>
{
if (!AssetRepository.GetIsAssetTrackType(asset.TypeCode))
{
var equipment = equipmentList.Where(x => x.AssetID == asset.AssetID).FirstOrDefault();
var inspectionAsset = new Asset()
{
AssetID = equipment?.AssetID,
Description = equipment?.Description,
// ...
};
// ...
assets.Add(inspectionAsset);
}
});
query = assets.AsQueryable();
foreach (var filter in Filters)
{
query = query.Where(filter);
}
}
});
return query;
}
为消除异常,我将功能更改为:
public async Task<IQueryable<Asset>> LoadAssetsOnTrack(IList<Asset> trackAssets, List<Asset> assets)
{
IQueryable<IAsset> query = assets.AsQueryable();
foreach (var filter in Filters)
{
query = query.Where(filter);
}
await Task.Run(async () =>
{
using (await _assetsMutext.LockAsync())
{
var equipmentList = this.GetEquipment();
foreach (var asset in trackAssets)
{
if (!AssetRepository.GetIsAssetTrackType(asset.TypeCode))
{
var equipment = equipmentList.Where(x => x.AssetID== asset.AssetID).FirstOrDefault();
var inspectionAsset = new Asset()
{
AssetID = equipment?.AssetID,
Description = equipment?.Description,
// ...
};
// ...
assets.Add(inspectionAsset);
}
}
}
});
return query;
}
也就是说,我仍然不完全清楚为什么我会偶尔在函数的最高版本中获取异常而不在底层版本中获取该异常。如果有人有进一步的见解,请告诉我。