用EF查询平台结构

时间:2012-12-06 05:55:42

标签: .net entity-framework entity-framework-4

我正在使用EF(4.4),并且有一个名为N的{​​{1}}列的平面表... Value1

根据另一列(ValueN),我需要抓取ValueIndex NValueN-1ValueN

例如,如果ValueN+1ValueIndex,我需要3Value2Value3

为简单起见,假设Value4没有边界问题,即不是ValueIndex1,而且我有7 N列。

如果这是在记忆中我会做(也可能会做)这样的事情:

Value

不幸的是,由于数组索引不受支持,这在EF中不起作用。

作为一种解决方法,我尝试用索引器选择替换数组索引:

table.Select(t =>
  new {
    ValueIndex = t.ValueIndex, 
    Values = new[] {
      Value1, Value2, Value3, Value4, Value5, Value6, Value7
    }
  })
.Select(t => 
  new[] {
    Values[ValueIndex-1], Values[ValueIndex], Values[ValueIndex+1]
  }
);

但遗憾的是,它也不受支持(LINQ to Entities无法识别.Select(t => new[] { t.Values.Where((v, i) => i == t.ValueIndex-1).First(), t.Values.Where((v, i) => i == t.ValueIndex).First(), t.Values.Where((v, i) => i == t.ValueIndex+1).First(), } ); 变量上的Where方法。

我并不特别想在我的代码中使用巨大的switch语句:

t.Values

那么有什么方法可以实现我在使用EF(即可转换为SQL)之后以非常大的交换机/案例的方式进行查询?

1 个答案:

答案 0 :(得分:1)

实体框架(和许多ORM)是为关系数据库设计的。在其他情况下(文档存储或键值存储),它们往往会崩溃......

也就是说,如果你的实体框架仍然是正确的工具,那么考虑一下如何在SQL中处理它...这听起来像是对我的支点。

SELECT CASE WHEN ValueIndex = 1 THEN Value0 WHEN ValueIndex = 2 THEN Value1...... END,
   CASE WHEN ValueIndex = 1 THEN Value1 WHEN ValueIndex = 2 THEN Value2.... END,
   CASE When ValueIndex = 1 THEN Value2 WHEN ValueIndex = 2 THEN Value3..... END
FROM ....

所以......你能在LINQ中构建它吗?当然...

from t in in table
select new 
{
     ValueIndex = t.ValueIndex,
     First = t.ValueIndex == 1 ? t.Value0 : (t.ValueIndex == 2 ? t.Value1 : ....),
     Second = t.ValueIndex == 1 ? t.Value1 : (t.ValueIndex == 2 ? t.Value2 : ....),
     Third = t.ValueIndex == 1 ? t.Value2 : (t.ValueIndex == 2 ? t.Value3 : ....)
}

虽然有点难看......

如果你想让它可持续发展,你可以很容易地动态地构建表达式树。

所以你可以拥有像

这样的东西
public class Triplet
{
    public string Item1 { get; set; }
    public string Item2 { get; set; }
    public string Item3 { get; set; }
}

public static IQueryable<Triplet> GetTriplets(IQueryable<TableRow> source)
    {
        var lambda =
            Expression
             .Lambda<Func<TableRow, Triplet>>(Expression.MemberInit(
                Expression.New(typeof (Triplet)),
                     CreateMemberBind(-1),
                     CreateMemberBind(0),
                     CreateMemberBind(1)));

        return source.Select(lambda);
    }