实体框架/ Linq:有效地检测数据库中是否存在所有元素

时间:2017-06-27 09:41:16

标签: c# entity-framework linq

评论后添加,我的问题不够明确

某些软件访问了数据库并检索了一组项目。他选择了他们的一部分并叫我要求处理该集合。 在其他软件对数据库的访问及其对我的调用之间可能会被其他人删除。

其他流程:

IEnumerable<MyType> itemsToProcess = FetchItemsToProcess();
Process(itemsToProcess);

我的程序:

void Process(IEnumerable<MyType> items)
{
   ...
}

items的集合相当小,通常所有项目都应该出现在数据库中,主键和外键没有变化,但是我无法确定所有项目是否仍然存在。

继续原始问题

如果在处理期间我再次检测到数据库中不存在某个项目,那么这只是浪费时间。因此,在处理之前,我想检查数据库中是否存在所有项目。

我已检查过序列中的所有项目都是非零ID。现在我需要检查所有ID是否是数据库中现有项的ID:

效率不高的解决方案:将所有现有项目的ID放入本地内存并使用Except

IEnumerable<MyType> itemsToProcess = ...
IEnumerable<int> idsToProcess = itemsToProcess.Select(item => item.Id);
IEnumerable<int> existingIds = myDbContext.MyItems.Select(item => item.Id);

bool nonExistingItemsDetected = idsToProcess.Except(existingIds).Any();

以下方法需要对每个项目进行一次数据库访问以进行检查:

IEnumerable<MyType> itemsToProcess = ...
IEnumerable<int> idsToProcess = itemsToProcess.Select(item => item.Id);
bool nonExistingItemsDetected = idsToProcess
    .Where(idToProcess => !myDbContext.MyItems.Any(item => item.Id == idToProcess);

因为要处理的项目序列相当小,所以我想使用数据库来检测是否存在任何ID。我想我需要使用IQueryable

制作Contains
bool nonExistinItemsDetected = myDbContext.MyItems
  .Any( ?? )

我可以使用什么谓词来检测idsToProcess是否包含不存在的项目的ID。

1 个答案:

答案 0 :(得分:0)

如果您还需要处理这些项目,则需要从数据库中获取它们。在这种情况下,您可以使用以下内容来获取匹配项:

var existingDbItems = dbContext.MyItems.Where(i => localIdCollection.Contains(i.Id));

然后你可以简单地检查不同id的计数是否与继续之前返回的记录数相匹配。

确保您使用.Contains()的id的集合是内存中的集合(而不是商店表达式),否则您可能会看到异常。

修改

根据您的评论,您可以将上面的查询更改为:

var existingDbItemsCount = dbContext.MyItems
     .Where(i => localIdCollection.Contains(i.Id)).Distinct().Count();

这样你才能获得计数,而不是所有的记录。

如果项目非常不稳定,此时您必须检查它们是否存在,除非您在事务中工作,否则在您的代码修改数据库时仍可能存在问题。