img*_*gen 9 c# entity-framework-core
当我尝试向视图中添加对象时,它抛出异常unable to track an instance of type because it is a query type。有办法解决这个问题吗?
根据定义,查询类型是只读的(对于所有数据库提供程序,不仅限于内存中的查询类型):
- 永远不会跟踪DbContext上的更改,因此永远不会在数据库上插入,更新或删除。
但是,除了它们通常的使用场景之外,
- 映射到数据库视图。
- 映射到未定义主键的表。
他们允许
- 映射到模型中定义的查询。
或者换句话说
- 可以映射到定义查询 -定义查询是模型中声明的辅助查询,该查询充当查询类型的数据源。
这是通过ToQuery fluent API 实现的:
配置用于提供查询类型数据的查询。
因此,对于在内存数据库中测试查询类型,您应该利用定义的查询映射功能。
例如,在OnModelCreating覆盖中,您可以添加以下内容:
if (Database.IsInMemory())
{
// In memory test query type mappings
modelBuilder.Query<MyQueryType>().ToQuery(() => LINQ_query);
// ... similar for other query types
}
else
{
// Database query type mappings
modelBuilder.Query<MyQueryType>().ToView("MyQueryTypeView");
// ...
}
Run Code Online (Sandbox Code Playgroud)
其中LINQ_query在正常LINQ查询访问上下文DbSetS和DbQueryS和伸出MyQueryType。
然后,测试将为涉及的实体提供数据,并且使用DbQuerys进行的查询将从定义的查询中检索数据。
上面的方法应该是在内存数据库中测试视图的推荐方法。
仅出于完整性考虑,可以DbQuery通过创建某种查询存储库直接向s提供数据(基本上是模拟它们),但是有以下限制-必须共享(static),因为当前EF Core无法正确处理db上下文成员。 (就像全局查询过滤器一样)不是DbSet<T>和DbQuery<T>。
像这样:
public static class FakeQueryProvider
{
static Dictionary<Type, IQueryable> queries = new Dictionary<Type, IQueryable>();
public static void SetQuery<T>(IQueryable<T> query)
{
lock (queries)
queries[typeof(T)] = query;
}
public static IQueryable<T> GetQuery<T>()
{
lock (queries)
return queries.TryGetValue(typeof(T), out var query) ? (IQueryable<T>)query : Enumerable.Empty<T>().AsQueryable();
}
public static QueryTypeBuilder<T> ToFakeQuery<T>(this QueryTypeBuilder<T> builder)
where T : class
{
return builder.ToQuery(() => GetQuery<T>());
}
}
Run Code Online (Sandbox Code Playgroud)
然后代替
.ToQuery(() => LINQ_query);
Run Code Online (Sandbox Code Playgroud)
你会用
.ToFakeQuery();
Run Code Online (Sandbox Code Playgroud)
并像这样将其喂入测试
List<MyQueryType> data = ...;
FakeQueryProvider.SetQuery(data.AsQueryable());
Run Code Online (Sandbox Code Playgroud)
由于共享存储限制了MyQueryType并行运行相关测试的能力,因此我仍然建议第一种方法。
| 归档时间: |
|
| 查看次数: |
879 次 |
| 最近记录: |