当我尝试向 View 中添加对象时,它抛出异常unable to track an instance of type because it is a query type。有办法解决这个问题吗?

最佳答案

Query Types根据定义是只读的(对于所有数据库提供程序,不仅限于内存中的):



但是,除了它们通常的使用场景之外,



他们允许



或者换句话说



这是通过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");
    // ...
}

其中LINQ_query是访问上下文DbSetDbQuery并投影到MyQueryType的普通LINQ查询。

然后,测试将为涉及的实体提供数据,并且使用DbQuery的查询将从定义的查询中检索数据。

上面的方法应该是在内存数据库中测试 View 的推荐方法。

仅出于完整性考虑,可以通过创建某种查询存储库直接向DbQuery提供数据(基本上是模拟它们),但是有以下限制-必须共享(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>());
    }
}

然后代替
.ToQuery(() => LINQ_query);

你会用
.ToFakeQuery();

并像这样将其喂入测试
 List<MyQueryType> data = ...;
 FakeQueryProvider.SetQuery(data.AsQueryable());

我仍然推荐第一种方法,因为共享存储限制了并行运行MyQueryType相关测试的能力。

关于c# - 如何使用内存数据库提供程序中的Entity Framework Core测试数据库 View ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55373825/

10-08 23:42
查看更多