asp.net - 我可以使用 EF Core 5 InMemory 数据库进行集成测试吗
问题描述
我正在从 net core 3.1 迁移到 net 5(EF Core 3 也迁移到 EF Core 5)。我们正在使用 EF Core 3 InMemory 数据库进行集成测试。迁移测试不再通过并且查询抛出错误后:
System.InvalidOperationException:LINQ 表达式 'ShapedQueryExpression:QueryExpression:InMemoryQueryExpression:ServerQueryExpression:InMemoryTableExpression:实体:RatingExclusionProduct .Where(valueBuffer => IsFalse(ValueBufferTryReadValue(valueBuffer,0,属性:RatingExclusion.Id(UUId)必需 PK AfterSave:Throw)。 Equals(null)) && object.Equals( objA: ExpressionExtensions.ValueBufferTryReadValue( valueBuffer: valueBuffer, index: 0, property: Property: RatingExclusion.Id (UUId) 必需 PK AfterSave:Throw), objB: ExpressionExtensions.ValueBufferTryReadValue( valueBuffer: valueBuffer ,索引:0,属性:属性:RatingExclusionProduct.ExclusionId (UUId) 必需 PK FK AfterSave:Throw)) ProjectionMapping:成员:EmptyProjectionMember 投影:EntityProjectionExpression:属性:RatingExclusionProduct。ExclusionId (UUId) 必需 PK FK AfterSave:Throw -> ExpressionExtensions.ValueBufferTryReadValue( valueBuffer: valueBuffer, index: 0, property: Property: RatingExclusionProduct.ExclusionId (UUId) 必需 PK FK AfterSave:Throw) 属性: RatingExclusionProduct.ProductId (UUId) 必需PK FK 索引 AfterSave:Throw -> ExpressionExtensions.ValueBufferTryReadValue( valueBuffer: valueBuffer, index: 1, property: Property: RatingExclusionProduct.ProductId (UUId) 必需的 PK FK 索引 AfterSave:Throw) ,ValueBufferTryReadValue(valueBuffer: valueBuffer, index: 1, property: Property: RatingExclusionProduct.ProductId (UUId) Required PK FK Index AfterSave:Throw) ,ValueBufferTryReadValue(valueBuffer: valueBuffer, index: 1, property: Property: RatingExclusionProduct.ProductId (UUId) Required PK FK Index AfterSave:Throw) ,
ShaperExpression: EntityShaperExpression: EntityType: RatingExclusionProduct ValueBufferExpression: ProjectionBindingExpression: EmptyProjectionMember IsNullable: False .AsQueryable() .LeftJoin( inner: DbSet<ControlProduct>(), outerKeySelector: o0 => EF.Property<UUId>(o0, "ProductId"), innerKeySelector: c => EF.Property<UUId>(c, "Id"), resultSelector: (o, i) => new TransparentIdentifier<RatingExclusionProduct, ControlProduct>( Outer = o, Inner = i ))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly
通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用
我们能否以某种方式解决这个问题,或者我们需要切换到另一种模拟数据库的方法?据我所知,发生了重大变化:
https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-5.0/break-changes#no-client-methods
我的问题与它有关吗?我在网上搜索过,有些人建议使用真实数据库进行测试,但我担心这会是一个非常慢的解决方案,而且我们有多个使用单个数据库的上下文,因此很难在测试开始时创建数据库。有些人建议创建上下文聚合(包含所有实体的单个上下文仅用于创建数据库),但我不知道如何实现它。我认为我的问题看起来更像是后续问题的组合,但我对这个话题有点迷茫。非常感谢您的关注。
更新: UUId 是自定义类型,用作我们所有表的 PK。为了解决它,我们使用:
services
.AddDbContext<RatingsContext>(opt =>
opt.AddRelationalTypeMappingSourcePlugin<UUIdTypeMapperPlugin>()
.UseMySql(connectionString, mso => mso
.ServerVersion(new Version(5, 7, 29), ServerType.MySql)
.EnableRetryOnFailure()
)
);
其中 UUIdTypeMapperPlugin:
public class UUIdTypeMapperPlugin : ITypeMappingSourcePlugin, IRelationalTypeMappingSourcePlugin
{
public CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
{
return mappingInfo.ClrType == typeof(UUId) ? new UUIdTypeMapper() : null;
}
public RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
return mappingInfo.ClrType == typeof(UUId) ? new UUIdTypeMapper() : null;
}
}
和 UUIdTypeMapper:
public class UUIdTypeMapper : RelationalTypeMapping
{
private static readonly ValueConverter<UUId, byte[]> _converter
= new ValueConverter<UUId, byte[]>(uuid => uuid.ToByteArray(),
byteArray => new UUId(byteArray));
protected UUIdTypeMapper(RelationalTypeMappingParameters parameters) : base(parameters)
{
}
public UUIdTypeMapper() : base(new RelationalTypeMappingParameters(
new CoreTypeMappingParameters(typeof(UUId), _converter), "binary(16)")
)
{
}
protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
{
return new UUIdTypeMapper(parameters);
}
public override string GenerateSqlLiteral(object value)
{
return $"0x{value}";
}
}
解决方案
经过广泛的研究,我发现 EF Core GitHub 上有一个与我的问题相关的未决问题,这是一个错误。
https://github.com/dotnet/efcore/issues/24318
我认为我们的团队应该转向在真实数据库上进行集成测试。有一个有用的链接: https ://medium.com/nerd-for-tech/run-ef-core-integration-tests-in-a-repeatable-and-isolated-way-using-a-public- docker-image-with-a-e912a89c7bf4
推荐阅读
- mysql - 从 MySQL 表中检索属于一组用户的最新模型
- json - RAD Server Delphi - 由于 Json 转换后元音突变,使用 savetostream 和 loadfromstream 不起作用
- flutter - 如何在 DropdownBelow 中显示不应在其列表中的提示文本
- python - 如何比较 Google 或工具中的 set() 和 list()?
- python - 如何根据Django中一个模型的计算重新计算另一个模型中的字段?
- c++ - 子构造函数使用祖父构造函数
- c++ - 为什么 C++ (cpp) 中的这个 sortArray 方法只对前两个数字进行排序?
- r - 如何在 r 中使用 NaN 对两个数据帧执行平均绝对误差(mae)
- javascript - 根据嵌套值将对象数组分组为二维数组
- utf-8 - 'utf-8' 编解码器无法解码位置 3057 中的字节 0x9c:导入某些 python 库时出现无效的起始字节错误