1

TL;DR我正在使用EntityFramework 5.0withOracle并且需要仅使用两列的索引来查询两列NVL的表。

经过数小时的尝试后的细节......我会尽量组织它。

所需的SQL 查询应该是:

SELECT t.Code, NVL(t.Local, t.Global) Description
FROM   Shows t
Where  t.Code = 123

那么问题是什么?如果我想使用,Context.Shows.Parts.SqlQuery(query)我必须返回整行(*),然后我得到Table Access Full,所以我必须只返回所需的列。

我尝试过的下一件事(实际上在以下之前有很多尝试......)给出了非常接近的结果是使用空合并运算符??):

Context.Shows.Where(x => x.Code == 123)
             .Select(x => new { x.Code, Description = x.Local ?? x.Global);

但是它使用的 SQL 使用起来很复杂case & when,而不是使用我 Code, Nvl(Local, Global)的关键索引!

我的下一步是使用Database.SqlQuery

context.Database.SqlQuery<Tuple<int, string>>("the Raw-SQLQuery above");

Tuple但是我得到一个不能是抽象的错误,并且必须有默认的ctor(它没有)。

我不喜欢的最后一步是创建一个只有这两个属性(Code, Description)的类,现在......它工作得很好,但我不想为这样的每个查询编写一个类。

想法?

4

1 回答 1

2

这是一个无解的答案。

我认为无论你尝试什么,你都做不到。即使您定义了自己的可变泛型元组,它也会失败,因为属性的名称必须与列的名称匹配

SqlQuery(String, Object[]):创建一个原始 SQL 查询,该查询将返回给定泛型类型的元素。该类型可以是任何具有与查询返回的列的名称相匹配的属性的类型,也可以是简单的原始类型。

我认为您能做的最好的事情就是创建自己的通用方法来通过经典CommandExecuteReader模式查询数据库。未经测试,但你明白了:

public static IEnumerable<Tuple<T>> SqlQuery<T>(this DbContext context, string sql)
{
    using(var connection = new SqlConnection(context.Database.Connection.ConnectionString))
    using (var command = new SqlCommand(sql, connection))
    {
        var reader = command.ExecuteReader();
        while (reader.NextResult())
        {
            yield return new Tuple<T>((T)reader[0]);
        }
    }
}
public static IEnumerable<Tuple<T1, T2>> SqlQuery<T1, T2>(this DbContext context, string sql)
{
    using (var connection = new SqlConnection(context.Database.Connection.ConnectionString))
    using (var command = new SqlCommand(sql, connection))
    {
        var reader = command.ExecuteReader();
        while (reader.NextResult())
        {
            yield return new Tuple<T1, T2>((T1)reader[0], (T2)reader[1]);
        }
    }
}
于 2013-04-25T10:06:21.867 回答