4

私はEntity Framework(それが重要な場合は4.2)を使用しており、複合主キー(2つのint列)を持つモデルを持っています。データベースから取り出したいオブジェクトのリストを表す int のペアのリストがあります。単一のクエリを使用してこれらすべてのオブジェクトを取得する簡単な方法はありますか?

次のように、クエリをリストに結合しようとしました。

List<Tuple<int, int>> ids = GetIds();

var data =
    from e in ctx.CompositeEntities
    join i in ids on new {e.KeyA, e.KeyB} equals new {KeyA = i.Item1, KeyB = i.Item2}
    select e;

ただし、これにより常に例外が発生します。

4

4 に答える 4

6

これを行うためのよりクリーンな方法を見たいのですが...少なくともうまくいくはずです。

ソリューション1

必要なもの:タプルリストを連結してから、SqlFunctions.StringConvertを使用してエンティティから「intキー」を連結します。パラメータとして double または decimal のみを取るため、最初に int を double にキャストする必要があります。

List<Tuple<int, int>> ids = GetIds();

var concatenatedIds = ids.Select(m => m.Item1 + "," + m.Item2).ToList();

var result = ctx.CompositeEntities
                .Where(conatenatedIds.Contains(
                       SqlFunctions.StringConvert((double)m.KeyA) + 
                       "," + 
                       SqlFunctions.StringConvert((double)m.KeyB)));

ソリューション2

PredicateBuilderを使用する

List<Tuple<int, int>> ids = GetIds();

var predicate = Predicate.False<CompositeEntity>();
foreach (var tuple in ids) 
   predicate = predicate.Or(m => m.KeyA == tuple.Item1 && m.KeyB == tuple.Item2);

var result = ctx.CompositeEntities.Where(predicate);

ソリューション3

最初に列挙してから比較します。もちろん、これはデータベースからすべての CompositeEntities を取得します。

于 2013-01-30T16:03:26.597 に答える
0

私はこれを試すことができませんが、このwhere句のようなものを使ってみてください。

from e in ctx.CompositeEntities
where ids.Where(i => e.KeyA == i.Item1  && e.KeyB == i.Item2).Count() > 0
select e;

=====編集=====

よく同じ例外で失敗します、励ましに感謝します。

キーがintであり、bigintではないと仮定すると、次はどうでしょうか。

public class e1 {
    public int KeyA { get; set; }
    public int KeyB { get; set; }
}

public class e1Configuration : EntityTypeConfiguration<e1> {
    public e1Configuration()
        : base() {
            HasKey(x => new { x.KeyA, x.KeyB });
    }
}

public class TestEFContext : DbContext {
    public IDbSet<e1> es { get; set; }

    public TestEFContext(String cs)
        : base(cs) {
        Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new e1Configuration());            
    }
}

class Program {
    static void Main(String[] args) {


        using (TestEFContext c = new TestEFContext(@"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True")) {
            c.es.Add(new e1 { KeyA = 1, KeyB = 1 });
            c.es.Add(new e1 { KeyA = 1, KeyB = 2 });
            c.es.Add(new e1 { KeyA = Int32.MaxValue, KeyB = 2 });
            c.SaveChanges();
        }

        List<Tuple<int, int>> ids = new List<Tuple<int, int>> { 
            new Tuple<int, int>(1, 1), 
            new Tuple<int, int>(Int32.MaxValue, 2),};

        List<Int64> lis = (from t in ids select (Int64)t.Item1 * 2^ 32 + t.Item2).ToList();

        using (TestEFContext c0 = new TestEFContext(@"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True")) {
            var v = from e in c0.es
                    where lis.Contains((Int64)e.KeyA * 2 ^ 32 + e.KeyB)
            select e;

            Console.WriteLine(v.Count());
        }

    }
}
于 2013-01-30T15:42:46.720 に答える
0

私はほぼ同じシナリオで作業していますが、上記のシナリオにマップしてみます。コンパイルできない場合はお知らせください。

これは、Raphaël の例 2 と同じ基本的なアイデアですが、実行できませんでした。各タプルに 1 つずつ、個々のエンティティのクエリの結合として Predicate を構築しています。

  List<Tuple<int, int>> ids = GetIds();

  ids.Aggregate<Tuple<int,int>,IQueryable<CompositeEntity>>(
      null,
      (current, id) => 
        current == null ? SingleCompositeEntity(ctx.CompositeEntities, id)
        : current.Union(SingleCompositeEntity(ctx.CompositeEntities, id)));
}


private static IQueryable<CompositeEntity> 
        SingleCompositeEntity(IQueryable source, Tuple<int,int> tuple)
{
   return source.Where(m => m.KeyA == tuple.Item1 && m.KeyB == tuple.Item2)

}
于 2014-04-15T15:14:19.923 に答える
-1

テストされていませんが、うまくいくと思います。

エンティティオブジェクトにプロパティを追加して、キーをタプルとして公開します。

public Tuple<int, int> TupleKey
{
    get { return new Tuple<int, int>(_keyA, _keyB);}
}

次に、この新しいプロパティを使用するようにクエリを変更します。

List<Tuple<int, int>> ids = GetIds();

var data = from e in ctx.CompositeEntities
            where ids.Contains(e.TupleKey)
            select e;
于 2013-01-30T16:14:27.843 に答える