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 关注
- 161 浏览
添加回答
举报