C# Oracle ManagedDataAccess.EntityFramework Database.SqlQuery按位置列出的绑定参数?
我有以下代码:C# Oracle ManagedDataAccess.EntityFramework Database.SqlQuery按位置列出的绑定参数?,c#,oracle,entity-framework,C#,Oracle,Entity Framework,我有以下代码: var query = Database.SqlQuery<int>(@" SELECT CASE WHEN EXISTS ( SELECT 1 FROM v$session v, UsersXxxx u WHERE v.Client_Info LIKE u.UserName || ';%' AN
var query = Database.SqlQuery<int>(@"
SELECT CASE WHEN EXISTS (
SELECT 1
FROM v$session v, UsersXxxx u
WHERE v.Client_Info LIKE u.UserName || ';%'
AND v.UserName = :schemaName
AND u.SchemaName = :schemaName
AND v.module = 'XXXX.exe'
AND u.UserKey = :userKey)
THEN 1 ELSE 0 END AS LoggedIn FROM DUAL",
new OracleParameter("schemaName", schemaName),
new OracleParameter("userKey", userKey));
return query.First() != 0;
这将生成一个ORA-01008:并非所有变量都绑定。我怀疑变量绑定的方式出了问题,最后尝试了以下方法:
var query = Database.SqlQuery<int>(@"
SELECT CASE WHEN EXISTS (
SELECT 1
FROM v$session v, UsersXxxx u
WHERE v.Client_Info LIKE u.UserName || ';%'
AND v.UserName = :schemaName
AND u.SchemaName = :schemaName
AND v.module = 'XXXX.exe'
AND u.UserKey = :userKey)
THEN 1 ELSE 0 END AS LoggedIn FROM DUAL",
new OracleParameter("asdf", schemaName),
new OracleParameter("fdsa", schemaName),
new OracleParameter("userKey", userKey));
return query.First() != 0;
这就像一个符咒!我翻了翻文档,发现了一个广告,上面写着:
ODP.NET和实体框架支持绑定标量参数。在实体框架中,支持按名称绑定参数。不支持按位置绑定
不知何故,我认为医生们在骗我,他们试图通过立场来约束我。我记得很久以前在EF支持之前修复过一次,但我不记得修复是什么,更不用说如何在EF中应用相同的技术了
我的解决方法虽然很难实现,但是否有一个选项可以让它通过名称而不是位置绑定?如果是,那是什么?问题是Database.SqlQuery方法使用底层DbConnection的CreateCommand方法。在ODP.NET中,这将导致一个OracleCommand,默认情况下,该命令通过位置BindByName=false绑定参数
这种行为是不可配置的,也没有改变它的好地方。作为一种解决方法,我可以建议使用自定义SqlQuery方法替换,该方法将创建BindByName=true的OracleCommand,执行ExecuteReader并使用ObjectContext.Translate方法进行映射:
public static class EFExtensions
{
public static IEnumerable<T> DbQuery<T>(this DbContext db, string sql, params object[] parameters)
{
if (parameters != null && parameters.Length > 0 && parameters.All(p => p is OracleParameter))
return OracleDbQuery<T>(db, sql, parameters);
return db.Database.SqlQuery<T>(sql, parameters);
}
private static IEnumerable<T> OracleDbQuery<T>(DbContext db, string sql, params object[] parameters)
{
var connection = db.Database.Connection;
var command = connection.CreateCommand();
((OracleCommand)command).BindByName = true;
command.CommandText = sql;
command.Parameters.AddRange(parameters);
connection.Open();
try
{
using (var reader = command.ExecuteReader())
using (var result = ((IObjectContextAdapter)db).ObjectContext.Translate<T>(reader))
{
foreach (var item in result)
yield return item;
}
}
finally
{
connection.Close();
command.Parameters.Clear();
}
}
}
要使用它,只需更换
context.Database.SqlQuery<..>(...)
打电话给
context.DbQuery<..>(...)
在托管驱动程序的最新版本中,您可以添加默认情况下将BindByName设置为true的web.config条目
<oracle.manageddataaccess.client>
<version number="*">
<settings>
<setting name="BindByName" value="true" />
</settings>
</version>
</oracle.manageddataaccess.client>
我会尽我所能去发现:/@Halter,不,我还没有找到如何让这项工作按我想要的方式进行。解决方法仍然存在,老实说,我几乎放弃了。知道这一点当然还是很好的。谢谢没问题,这种解决方法对我来说根本不起作用:詹姆斯,你知道你使用的是什么版本的EF吗?@Halter最终的另一个选择是使用你自己的SqlQuery方法替换,它创建一个正确的命令,然后使用旧的good ObjectContext。翻译以获得结果。非常感谢兄弟!!!在配置中,默认情况下将bindbyname设置为true真是太神奇了。你太棒了