5 回答

TA貢獻1775條經驗 獲得超11個贊
您可以使用DbDataReader:
using (var command = context.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "SELECT * From Make";
context.Database.OpenConnection();
using (var reader = command.ExecuteReader())
{
// Do something with result
reader.Read(); // Read first row
var firstColumnObject = reader.GetValue(0);
var secondColumnObject = reader.GetValue(1);
reader.Read(); // Read second row
firstColumnObject = reader.GetValue(0);
secondColumnObject = reader.GetValue(1);
}
}
在這里您可以了解更多如何從DbDataReader
.
或者,您可以使用FromSql()
方法,但這僅適用于DbSet
某些實體的預定義,這不是您想要的解決方案。

TA貢獻1865條經驗 獲得超7個贊
您仍然可以使用 EF Core 實現外部數據庫的用例,無需求助于 ADO.Net,此解決方案基于@ErikEj 的 EF Core 通用解決方案。(請注意,EF Core 3 的一些函數和命名空間發生了變化,因此保留在 .Net 5+ 中,但仍然可以應用相同的通用概念)
public static IList<T> Query<T>(string connectionString, string query, params object[] parameters) where T : class
{
try
{
using (var contextGeneric = new ContextForQuery<T>(connectionString))
{
return contextGeneric.Query<T>().FromSql(query, parameters).ToList();
}
}
catch (System.Data.SqlClient.SqlException ex)
{
throw new SQLIncorrectException(ex);
}
catch (System.InvalidOperationException ex)
{
throw new NotImplementedException();
}
}
private class ContextForQuery<T> : DbContext where T : class
{
private readonly string connectionString;
public ContextForQuery(string connectionString)
{
this.connectionString = connectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString, options => options.EnableRetryOnFailure());
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<T>().HasNoKey();
base.OnModelCreating(modelBuilder);
}
}
那么 this 的使用需要一個具體的類型定義,添加對匿名類型的支持需要付出更多的努力,但是為此創建一個具體的類型并不是一件壞事,這里的重點是讓你嘗試更多的聲明式代碼風格因為它們增強了代碼的可讀性和檢查性,并提供文檔和其他擴展配置,如相關實體。
public class NamedObject
{
public int Id { get; set; }
public string Name { get; set; }
}
...
var connectionString = "Insert your connection string here...";
var data = Query<NamedObject>(connectionString, "SELECT TOP 10 Id, FullName as Name FROM Employee");
foreach (var emp in data)
{
Console.WriteLine(emp.Name);
}
背景
在 EF 6(.Net Framework)中,我們可以DbContext.Database.FromSQL<T>()
用來執行將自動映射到指定類型的T
. 此功能未在 EF Core 中復制,因為結果FromSQL
與 EF 的其余部分不一致,結果是一次使用IEnumerable<T>
。您無法進一步將此查詢組合到Include()
相關實體,也無法向基礎查詢添加過濾器。
在 EF Core to Execute Raw SQL中,您想要返回的類型T
需要在 DbContext 中定義為DbSet<T>
. 這個集合根本不需要映射到數據庫中的表,事實上,自從 EF Core 2.1 我們不需要為此類型指定鍵,它只是一種預定義預期結構而不是執行的機制按需臨時請求,它為您提供與舊版相同的功能,FromSQL
但還允許您定義一組豐富的導航屬性,以便在使用 LINQ to SQL 管道插入RawSQL后進一步組合查詢。
一旦在上下文中定義了類型,您只需調用DbSet<T>.FromSqlRaw()
. 不同之處在于,現在我們有一個IQueryable<T>
可以用來進一步組合以包含相關實體或應用將在數據庫中評估的過濾器。
此響應中發布的解決方案不允許組合,但按預期順序使用 EF 運行時來提供與原始 EF 6 實現相同的行為。
在最新版本的 EF Core 中,以及現在在 .Net 5+ 中,需要應用以下細微變化:
核心2.1:
return contextGeneric.Query<T>().FromSql(query, parameters).ToList();
核心 3+:
return contextGeneric.Set<T>().FromSqlRaw(query, parameters).ToList();

TA貢獻1851條經驗 獲得超5個贊
您可以使用context.Database.ExecuteSqlRaw("select 1")
不要忘記導入正確的命名空間:using Microsoft.EntityFrameworkCore;

TA貢獻1784條經驗 獲得超7個贊
它是這樣工作的:
private void SqlCommand (string connectionString, string query)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
var a = reader[0];
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
要么
using (var connection = ContextFactory.GetNewContextGeneric(connectionString).Database.GetDbConnection())
{
connection.Open();
DbCommand command = connection.CreateCommand();
command.CommandText = query;
using (var reader = command.ExecuteReader())
{
// Do something with result
reader.Read(); // Read first row
var firstColumnObject = reader.GetValue(0);
/*var secondColumnObject = reader.GetValue(1);
reader.Read(); // Read second row
firstColumnObject = reader.GetValue(0);
secondColumnObject = reader.GetValue(1);*/
connection.Close();
return firstColumnObject.ToString();
}
}
- 5 回答
- 0 關注
- 246 瀏覽
添加回答
舉報