【问题标题】:Entity Framework Core raw SQL issue实体框架核心原始 SQL 问题
【发布时间】:2019-08-30 23:27:35
【问题描述】:

我有一个History 表,其中包含C0, C1, C2, C3, TimeStamp 列。

我想根据输入选择一个特定的列以及对应的TimeStamp

channelId 为'C2'

var context = new DalModels.DbContext();
string command = "SELECT TimeStamp, @channelId FROM dbo.History";
var user = new SqlParameter("@channelId", channelId);
var result = context.History.FromSql(command, user).ToList();

但是我得到一个异常而不是结果:

没有为“h”的第 2 列指定列名。

列名“C0”无效。

列名“C1”无效。

列名“C2”无效。

列名“C3”无效。

列名“时间戳”无效。

【问题讨论】:

  • 什么是channelId?
  • 你需要:string channelId = "C2";
  • @SpiritBob channelID 是一个可以变化的列名

标签: c# entity-framework-core


【解决方案1】:

参数化查询不能用于动态列名。参数只能用在表达式的右侧,例如在= 之后。

要解决您的问题,请将查询转换为使用变量。

var context = new DalModels.DbContext();
string command = $"SELECT TimeStamp, {channelId} FROM dbo.History";
var result = context.History.FromSql(command, user).ToList();

注意$ 用于string interpolation

然后,您必须将用户可以传递给该字段的值列入白名单,以防止 SQL 注入攻击。

【讨论】:

  • 没错,但这只是(SQL)故事的一半。 FromSql 需要选择所有实体列,所以无论如何不能在这种情况下使用。
  • @IvanStoev 是正确的,FromSql 中有一个limitation。在这种情况下,方法是使用context.History.ToList(); 获取所有列,然后在代码中进行一些操作。