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,但您必须从数据库中提取所有内容,这可能会更昂贵。

于 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 )
{
  ...

要记住的一件事是,这不是线程安全的:如果其他东西同时添加ExistingVersion行,您可能会尝试插入在检查数据库后添加的记录。

于 2013-03-11T20:18:56.947 回答