如何将 Linq 中的列表中的值与实体(任意 / 包含)进行比较



有一个列表,policiesToDelete实体类,MonitoringRelations 。从这个列表中,我选择了两个元素并解释了一个新的列表:

var policyKeysToDelete = policiesToDelete
    .Select(r => new {r.PolicyId, r.GroupId})
    .ToList();

现在,我有一个查询,我想在其中比较列表中的元素policyKeysToDelete

var objectsToDelete = (from p in storageContext.MonitoringRelations
                       where policyKeysToDelete
                            .Any(x => x == new {p.PolicyId, p.GroupId})
                       select p)
                       .ToList();

问题:上面的查询抛出此异常:

NotSupportedException: Unable to create a constant value of type 'Anonymous type'. Only primitive types or enumeration types are supported in this context.

我尝试将匿名列表更改为list<tuple<PolicyId, GroupId>>,但这也没有帮助,抛出了几乎相同的异常。我尝试使用Contains代替Any但这也没有帮助。

知道我该如何解决这个问题吗?

EF

无法将复杂对象的列表转换为 SQL 查询。EF 可以执行的操作是在将简单值列表与 .Contains 方法一起使用时将其转换为 SQL。

因此,如果从policyKeysToDelete中提取 PolicyId 列表和组 ID 列表,并使用它来使用 EF 尽可能多地进行选择,则可以使用 Linq-to-对象在结果集中执行完整检查,然后在内存中

警告:您从数据库中提取了太多内容,因此根据数据量,不同的解决方案可能会更好。

var policyKeysToDelete = policiesToDelete
    .Select(r => new {r.PolicyId, r.GroupId})
    .ToList();
// List of values types, which can be translated to SQL
var policyIds = policyKeysToDelete.Select(x => x.PolicyId).ToList();
var groupIds = policyKeysToDelete.Select(x => x.GroupId).ToList();
var objectsToDelete = storageContext.MonitoringRelations
    // Do the part that we can do in the database, which is select the records
    // which have an corresponding PolicyId or GroupId
    .Where(x => policyIds.Contains(x.PolicyId) || groupIds.Contains(x.GroupId))
    // Use this method to indicate that whatever follows after should not be
    // translated to SQL
    .AsEnumerable()
    // Do the full check in-memory
    .Where(x => policyKeysToDelete
        .Any(y => x.PolicyId == y.PolicyId && x.GroupId == y.GroupId)
    )
    .ToList();

最新更新