1

外部ソースからのエンティティのリストがあります。私はそれを私がすでに持っているものと比較し、存在しないものだけを追加する必要があります。以下の擬似コード。

 var newVersions = item.Versions
      .Where(s => db.ExistingVersions
           .Select(t=>t.versionID)
           .DoesNotContains(s.versionID));

それは明らかに機能しません、そして私はそれを修正する方法がわかりません。forループは使用したくありません。これは、各アイテムのバージョンを確認するためだけに、何百ものデータベースヒットが発生することを意味すると考えているためです。複数のアイテムを読み込んでいます。各アイテムには100ものバージョンがあります。

4

2 に答える 2

7

質問に私が思う以上のものがなければ、それは複雑であってはなりません。

それが一意の識別子であると仮定するとVersionID、次のことができます。

var existingVersions = db.ExistingVersions.Select(x => x.VersionID).ToList();

気に留めておいてくださいContains

var existingVersions = new HashSet(db.ExistingVersions.Select(x => x.VersionID).ToList());

[編集]: Magnusのコメントによると、ToList上記のコードスニペットからドロップできます。

その後:

var newVersions = items.Versions.Where(x => !existingVersions.Contains(x.VersionID));

これはおそらく最もパフォーマンスが高いです。データベースを呼び出すときに、を選択するだけだからVersionIDです。他のオプションには、カスタムの作成IEqualityComparer<T>と使用Exceptが含まれますが、DBからすべてをプルする必要があり、コストがかかる可能性があります。

于 2013-03-11T20:17:04.903 に答える
3

あなたはこのようなことを試すことができます:

// in memory: get list of potential version ids
var potentialIds = item.Versions.Select( o => o.versionID ).ToList();

// hit database ( once ) : get existing version ids
var existingIds = db.ExistingVersions
  .Where( o => potentialIds.Contains( o.versionID ) )
  .Select( o => o.versionID )
  .ToList();

// in memory: filter potential objects
var newVersions = item.Versions
  .Where( o => !existingIds.Contains( o.versionID ) )
  .ToList();

// database inserts:
foreach( var newVersion in newVersions )
{
  ...

覚えておくべきことの1つは、これはスレッドセーフではないということです。他の何かがExistingVersion同時に行を追加している場合、データベースをチェックした後に追加されたレコードを挿入しようとする可能性があります。

于 2013-03-11T20:18:56.947 に答える