Entity Framework Core:按 3 个字段过滤

问题描述 投票:0回答:2

我正在尝试使用 Entity Framework Core 从数据库查询一些订阅。如果

userId
NotificationType
Channel
匹配,则订阅等于另一个订阅。

我正在尝试这样:

// Create a list of anonymous objects that combine the three fields for comparison
var subscriptionKeys = subscriptions
    .Select(s => new { s.UserId, s.NotificationType, s.Channel })
    .ToList();
       
// Fetch all existing subscriptions where the combination of UserId,  NotificationType, and Channel match
var existingSubscriptions = await this.context.Subscriptions
    .Where(s => subscriptionKeys.Contains(new { s.UserId, s.NotificationType, s.Channel })).ToListAsync();

但是我遇到了这个异常:

System.InvalidOperationException HResult=0x80131509 Message=LINQ 表达式 '__subscriptionKeys_0
.包含(新{
用户 ID = StructuralTypeShaperExpression:
Micro.NotificationService.Models.Subscription
值缓冲区表达式:
ProjectionBindingExpression:EmptyProjectionMember
是否可为空:False
.用户ID,
通知类型 = StructuralTypeShaperExpression:
Micro.NotificationService.Models.Subscription
值缓冲区表达式:
ProjectionBindingExpression:EmptyProjectionMember
是否可为空:False
.通知类型,
通道 = StructuralTypeShaperExpression:
Micro.NotificationService.Models.Subscription
值缓冲区表达式:
ProjectionBindingExpression:EmptyProjectionMember
是否可为空:False
.频道
})' 无法翻译。以可翻译的形式重写查询,或者通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用来显式切换到客户端计算。请参阅 https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。

来源=Microsoft.EntityFrameworkCore

堆栈跟踪:
在 Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatedExpressionVisitor.Translate(表达式表达式)

如何进行此类查询?顺便说一句,订阅可枚举和

DbSet
Subscriptions
不是同一类型的实体。一个是消息,另一个是数据库中保存的实际实体。

我可以做一些事情,例如将一个映射到另一个并仅使用

Contains
吗?

c# entity-framework-core
2个回答
1
投票

根据我的测试,你只剩下

FromSqlRaw

var whereClause = string.Join(
    " OR ",
    subscriptions.Select(x => $"(UserId={s.UserId} AND NotificationType='{s.NotificationType}' AND Channel='{s.Channel}')"));
   
// Fetch all existing subscriptions where the combination of UserId, 
NotificationType, and Channel match
var existingSubscriptions = await this.context.Subscriptions
    .FromSqlRaw(SELECT * FROM Subscriptions WHERE " + whereClause)
    .ToListAsync();

当然,请注意SQL注入并适当地清理你的字符串。


0
投票

您可以将

Contains
更改为
Any
即可解决您的问题

var existingSubscriptions = await this.dbContext.Subscriptions
    .Where(s => subscriptionKeys.Any(k =>
                k.UserId == s.UserId &&
                k.NotificationType == s.NotificationType &&
                k.Channel == s.Channel
    )).ToListAsync();
© www.soinside.com 2019 - 2024. All rights reserved.