C# 返回任务<;IReadOnlyCollection<;T>&燃气轮机;从EF核心查询不等待?
我喜欢对我的类型尽可能具体。当提供封装查询的方法时,通常会看到返回的C# 返回任务<;IReadOnlyCollection<;T>&燃气轮机;从EF核心查询不等待?,c#,entity-framework-core,ef-core-2.1,C#,Entity Framework Core,Ef Core 2.1,我喜欢对我的类型尽可能具体。当提供封装查询的方法时,通常会看到返回的List(或者更具体地说是Task),这也难怪EF Core的.toListSync()方法。但这不是很准确,是吗列表是SQL Server(或您正在使用的任何持久性)中更大集合的投影。它是不可修改的 我想从我的方法返回IReadOnlyCollection。这似乎更准确。我正在从源数据返回投影,您不能通过修改投影来修改源数据。我的结果也不能被错误地修改,除非返回到列表,在这一点上,您已经走得够远了,我假设您知道自己在做什么 因
List
(或者更具体地说是Task
),这也难怪EF Core的.toListSync()
方法。但这不是很准确,是吗<代码>列表是SQL Server(或您正在使用的任何持久性)中更大集合的投影。它是不可修改的
我想从我的方法返回IReadOnlyCollection
。这似乎更准确。我正在从源数据返回投影,您不能通过修改投影来修改源数据。我的结果也不能被错误地修改,除非返回到列表
,在这一点上,您已经走得够远了,我假设您知道自己在做什么
因此,我尝试像同步返回一样返回接口
public Task<IReadOnlyCollection<TResult>> GetResultAsync() =>
_dbContext.Where(x => x.Property == true).ToListAsync();
为了避免添加代码,我考虑了一种扩展方法
public static async Task<IReadOnlyCollection<T>> ToReadOnlyCollectionAsync<T>(this IQueryable<T> query) =>
await query.ToListAsync();
publicstaticasync任务ToReadOnlyCollectionAsync(此IQueryable查询)=>
等待query.ToListAsync();
这从我的方法中获得了
await
,但当然仍然添加了另一个await。有没有一种方法可以从EF Core 2.1返回Task
“免费”的任务?不知道ToListSync()
做什么,只知道名称,如果我猜对了,它会迭代结果并将其转换为后台线程上的列表,并返回在生成列表之前必须等待的任务
如果是这样的话,你的问题是
如何将任务
转换为任务
如果是这样,理论上你可以这样做:
public Task<IReadOnlyCollection<string>> ToReadOnlyCollection()
{
return ToListAsync().ContinueWith(x => new ReadOnlyCollection<string>(x.Result) as IReadOnlyCollection<string>);
}
public Task<IReadOnlyList<string>> ToReadOnlyList()
{
// if you don't mind an IReadOnlyList, you can use this
// one which doesn't involve creating a new collection
return ToListAsync().ContinueWith(x => x.Result as IReadOnlyList<string>);
}
private Task<List<string>> ToListAsync()
{
return Task.Run(() =>
{
Task.Delay(1000);
return new List<string>
{
"1",
"2",
"3"
};
});
}
public任务ToReadOnlyCollection()
{
返回toListSync().ContinueWith(x=>newreadonlyCollection(x.Result)作为IReadOnlyCollection);
}
公共任务ToReadOnlyList()
{
//如果您不介意使用IReadOnlyList,可以使用
//不涉及创建新集合的集合
返回toListSync().ContinueWith(x=>x.Result作为IReadOnlyList);
}
私有任务ToListSync()
{
返回任务。运行(()=>
{
任务延迟(1000);
返回新列表
{
"1",
"2",
"3"
};
});
}
我不相信
任务
允许反向变化,因此任务
(其中子项:父项)无法自动转换为任务
,因此您需要自己完成 我将此标记为答案,但想快速回答您的问题.ToListSync()
来自实体框架:查询SQL数据库,反序列化结果,并将投影作为包含所有反序列化对象的列表返回。此外,我想指出,因为这里的可能是错误的运算符正如
所示,结果可能不是IReadOnlyCollection
类型,如果不是,则返回null即可。这是不正确的。如果ToListAsync
的结果不是IReadOnlyCollection
,那么我们应该抛出
,因为出现了一些非常错误的情况,或者我们的底层框架已经更改,我们的代码需要更新。这里应该使用一个常规的旧类型转换来获得这种效果。@Licht感谢您纠正我关于ToListAsync()
的错误。我已经很长时间没有使用EF
了,我不记得曾经见过这种方法。关于as
,我认为返回类型是List
类型List
实现IReadOnlyList
,因此案例始终有效。IReadOnlyCollection
也始终有效,因为我们首先创建一个ReadOnlyCollection
(新的ReadOnlyCollection(originalList
)然后“casting”它是一个IReadOnlyCollection
。虽然打字速度很快,但这里或那里可能会有错误。这比实际(和完美)的实现更…意味着传达想法。我会忽略它,因为你提供的确切原因(想法比确切的实现更重要)然而,人们有从堆栈溢出复制粘贴的倾向。因此我认为实现尽可能正确是很重要的,因为我们在这里编写的代码可能会滑入我们甚至不知道的代码库。甚至可能是我们某天使用的代码库。
public Task<IReadOnlyCollection<string>> ToReadOnlyCollection()
{
return ToListAsync().ContinueWith(x => new ReadOnlyCollection<string>(x.Result) as IReadOnlyCollection<string>);
}
public Task<IReadOnlyList<string>> ToReadOnlyList()
{
// if you don't mind an IReadOnlyList, you can use this
// one which doesn't involve creating a new collection
return ToListAsync().ContinueWith(x => x.Result as IReadOnlyList<string>);
}
private Task<List<string>> ToListAsync()
{
return Task.Run(() =>
{
Task.Delay(1000);
return new List<string>
{
"1",
"2",
"3"
};
});
}