0

我正在使用 EF (4.4) 并且有一个包含N名为Value1...的列的平面表ValueN

基于另一列 ( ValueIndex) 我需要获取N值为ValueN-1ValueN和的三列ValueN+1

例如,如果ValueIndex3需要获取Value2,Value3Value4.

为简单起见,假设ValueIndex没有边界问题,即不是1N我有 7Value列。

如果这是在内存中,我会做(并且可能会做)这样的事情:

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]
  }
);

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

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

.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(),
  }
);

但不幸的是,这也不支持(LINQ to Entities 无法识别变量Where上的方法)。t.Values

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

tables.Select(t => 
  new[] {
    t.ValueIndex == 2 ?
      new[] {
        t.Value1,
        t.Value2,
        t.Value3,
      }
    : t.ValueIndex == 3 ?
      new[] {
        t.Value2,
        t.Value3,
        t.Value4,
      }
    : // Etc..
  }
);

那么有什么方法可以实现我在使用 EF(即可转换为 SQL)之后的查询,而不是大量的开关/案例?

4

1 回答 1

1

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

也就是说,如果您的 Entity Framework 仍然是这里的正确工具,请考虑如何在 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);
    }
于 2012-12-06T06:11:15.607 回答