0

私はEF(4.4)を使用しており、...Nという名前の列を持つフラットテーブルを持っています。Value1ValueN

別の列 ( ) に基づいて、 、、およびの値をValueIndex持つ 3 つの列を取得する必要があります。NValueN-1ValueNValueN+1

たとえば、 、、およびを取得する必要があるValueIndex場合。3Value2Value3Value4

ValueIndex簡単にするために、境界の問題がないと仮定します。つまり、 1or Nand ではなく、7 つValueの列があるとします。

これがメモリ内にある場合、私は次のようなことをします (おそらくそうするでしょう):

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

Entity Framework (および多くの 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 に答える