我正在尝试使用 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
吗?
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注入并适当地清理你的字符串。
您可以将
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();