[英]How to convert from DbDataReader to Task<IEnumerable<TEntity>> in Entity Framework Core 2.0?
我通過以下方式在EF Core 2.0中調用存儲過程。
private async Task<IEnumerable<TEntity>> InvokeStoredProcedureAsync(string entityName)
{
var storedProcedureName = string.Format(CultureInfo.InvariantCulture, "sp_{0}BulkSelect", entityName);
dynamic temp;
using (MyDbContext MyDbContext = new MyDbContext(_options))
{
MyDbContext.Database.OpenConnection();
DbCommand cmd = MyDbContext.Database.GetDbConnection().CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = storedProcedureName;
using (var reader = cmd.ExecuteReader())
{
temp = reader.Cast<Task<IEnumerable<TEntity>>>();
}
}
return await temp;
}
我需要從DbDataReader
轉換為Task<IEnumerable<TEntity>>
。
但是在嘗試擴展temp變量以查看其值時,我收到此錯誤。
讀取器關閉時無效嘗試調用FieldCount。
請參閱隨附的屏幕截圖。
除了明顯的異步代碼問題之外,您無法通過簡單地調用Cast
來將DbDataReader
為類。 如果可能的話,就不需要像Dapper和類似的微型ORM。
EF Core目前沒有公開這樣做的公開方式。 但是如果TEntity
是一個模型實體類,你可以簡單地使用FromSql
方法:
private async Task<IEnumerable<TEntity>> InvokeStoredProcedureAsync(string entityName)
{
var storedProcedureName = string.Format(CultureInfo.InvariantCulture, "sp_{0}BulkSelect", entityName);
using (var db = new MyDbContext(_options))
{
var result = await db.Set<TEntity>().FromSql(storedProcedureName).ToListAsync();
return result;
}
}
確保SP通過TEntity
映射返回所有預期的列。
在您的閱讀器被調用時,它已經關閉,因為using
-block已經完成。 你還需要閱讀“逐行”。 嘗試下面的內容:
private async Task<IEnumerable<TEntity>> InvokeStoredProcedureAsync(string entityName)
{
var storedProcedureName = string.Format(CultureInfo.InvariantCulture, "sp_{0}BulkSelect", entityName);
List<TEntity> temp = new List<TEntity>();
using (MyDbContext MyDbContext = new MyDbContext(_options))
{
MyDbContext.Database.OpenConnection();
DbCommand cmd = MyDbContext.Database.GetDbConnection().CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = storedProcedureName;
using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
temp.Add(reader.Cast<TEntity>()); // ATTENTION: this does not work! (see below)
}
}
return temp;
}
但我認為上面使用的演員表並不符合您的想法。 有關如何從讀取器創建實體的示例,請參閱以下線程: 將數據讀取器中的行轉換為鍵入的結果
在異步方法中,無需強制轉換為任務。 這將自己發生。 reader對象有單行。 應該一次讀取每一行。
var temp = new List<TEntity>();
using (var reader = await cmd.ExecuteReaderAsync()) {
while(await reader.ReadAsync()) {
temp.add(CreateEntity(reader)) ;
}
}
return temp;
// this is tightly coupled to object. Generic methods can be made
// to convert reader to object
public TEntity CreateEntity(SqlDataReader reader) => new TEntity()
{
Id = reader.GetInt32("id"),
Col1 = reader.GetString("col1"),
Col2 = reader.GetString("col2"),
Col3 = reader.GetString("col3")
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.