【问题标题】:Entity Framework with Oracle using odp.net not taking parameters in linq query使用 odp.net 的 Oracle 实体框架在 linq 查询中不采用参数
【发布时间】:2018-02-12 18:40:27
【问题描述】:

我使用 odp.net 将 EntityFramework 与 Oracle 一起使用。参数化的sql查询不起作用。

var orderCode = "XYZ";
var set = ctx.Database.SqlQuery<Order>(
    "Select * from dwh.Orders where OrderCode = '{0}'"
    , orderCode
);

(或)

var set1 = ctx.Database.SqlQuery<Order>(
    "Select * from dwh.Orders where OrderCode = ':param'", 
    new OracleParameter("param", orderCode)
);

Console.WriteLine(set.Count() + ", " + set1.Count()); //Gives 0, 0

但是,如果我对值进行硬编码,它就可以工作。

var set = ctx.Database.SqlQuery<Order>(
    "Select * from dwh.Orders where OrderCode = 'XYZ'",
    orderCode
);

有人知道为什么吗?我在那个视图中有 150 列。有问题吗?

更新: 使用 Oracle 参数的查询有效。问题是我在 :param 变量周围有单引号。

话虽如此,带有“{0}”的顶级查询不起作用。此外,以下 linq 查询不起作用。

var set = ctx.Orders.Where(a => a.OrderCode == orderCode); // Gets zero results.

当我对值进行硬编码时,它可以正常工作并正确获取结果。

var set = ctx.Orders.Where(a => a.OrderCode == "XYZ"); // Gets the results correctly.

更新 2: 这些查询与 Devart 的 dotconnect 驱动程序一起使用。看起来这是 odp.net 的问题。

有人有类似的问题吗?

【问题讨论】:

  • 你能更好地解释“不起作用”吗?您是否收到异常、空结果或错误结果?
  • 使用a.OrderCode.Equals(orderCode)是否有效
  • .Equals 也不起作用。
  • 我遇到了类似的问题。我不想在我的应用程序中引用 ODP 驱动程序(这就是我有 EF 的原因),所以这很烦人。现在,我可能会做连接 SQL 的反模式。该参数完全在应用程序内部,因此 SQL 注入不会成为问题。尽管如此,它在我的嘴里留下了不好的味道。
  • 任何带有完整源代码示例的最终解决方案?

标签: linq entity-framework odp.net


【解决方案1】:

不确定您是否截断了示例,但如果您使用多个参数,这可能是问题所在:

Parameterized query in Oracle trouble

虽然我看不出您的示例有什么问题,但我想知道您是否遇到了旧的 BindByName 问题。默认情况下,ODP.NET 按照将参数添加到集合中的顺序将参数绑定到查询,而不是根据您的需要基于它们的名称。尝试在 OracleCommand 对象上将 BindByName 设置为 true,看看是否能解决问题。

【讨论】:

    【解决方案2】:

    在使用与 Oracle 相关的字符串时要小心,因为它具有填充定义为 CHAR 的字符串的怪癖(有关详细信息,请阅读 CHAR versus VARCHAR2 Semantics)。

    假设您已将 OrderCode 定义为 CHAR(4),其值为 XYZ,然后 PL/SQL 将值填充为声明的长度,从而导致 XYZ_(而 _ 是填充字符在这里)。

    还假设 非常量 字符串 orderCode 由于 docs 中的此语句而被视为 VARCHAR2

    如果比较中的任一值具有数据类型 VARCHAR2, 使用非空白填充语义。也就是说,当比较 长度不等的字符值,PL/SQL 不做任何调整和 使用确切的长度。

    现在,如果您尝试执行a.OrderCode == orderCode,则左侧为CHAR,右侧为VARCHAR2,因此使用non-blank-padding,导致XYZ_ = XYZ 返回false .

    因此解决方案是使用a.OrderCode.TrimEnd() == orderCode 之类的东西来进行比较,因为.TrimEnd() 被转换为返回VARCHAR2 的PL/SQL RTRIM() 函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 2013-03-08
      • 2015-04-30
      • 1970-01-01
      • 2015-11-11
      • 2020-07-19
      相关资源
      最近更新 更多