Linq关联更新报错:Only primitive types or enumeration types are supported in this context
问题分析:EF关联查询报错“Only primitive types or enumeration types are supported in this context.”
你遇到的这个错误,核心问题出在内存集合和数据库IQueryable的混合操作上,咱们一步步拆解:
先看你写的代码:
var entityCodesRepo = _context.EntityCodes.ToList(); var qualifiedRecs = await (from px in searchQuery join ecx in entityCodesRepo on px.EntityCodeID equals ecx.EntityCodeID select new IDMS_Partner() { EntityType = ecx.DisplayLabel } ).ToListAsync();
错误原因
你先调用ToList()把EntityCodes整个加载到了内存里,而searchQuery应该是EF生成的数据库层面的IQueryable查询。EF的LINQ查询需要转换成SQL在数据库执行,它没办法把「内存集合和数据库查询做join」这个操作翻译成SQL——因为SQL只能操作数据库内的表,没法直接关联内存中的数据,所以就抛出了这个不支持的错误。
解决方法
给你两种可行的方案,根据实际场景选择:
方案一:让整个join在数据库执行(推荐)
不要提前把EntityCodes加载到内存,直接用_context.EntityCodes作为join的数据源,这样EF会把整个关联查询转换成SQL,在数据库端完成操作,性能更优:
var qualifiedRecs = await (from px in searchQuery join ecx in _context.EntityCodes on px.EntityCodeID equals ecx.EntityCodeID select new IDMS_Partner() { // 记得把IDMS_Partner的必要字段都赋值,否则会是默认值 PID = px.PID, EntityCodeID = px.EntityCodeID, EntityType = ecx.DisplayLabel } ).ToListAsync();
方案二:把两边数据都加载到内存再关联(仅适用于数据量小的场景)
如果因为特殊需求(比如要对EntityCodes做内存里的复杂过滤)必须先加载到内存,那也要把searchQuery先加载到内存,再做内存中的join——但这样会把searchQuery的所有结果拉到本地,数据量大时性能会很差:
var entityCodesRepo = _context.EntityCodes.ToList(); // 先把searchQuery的结果加载到内存 var searchResults = await searchQuery.ToListAsync(); var qualifiedRecs = from px in searchResults join ecx in entityCodesRepo on px.EntityCodeID equals ecx.EntityCodeID select new IDMS_Partner() { PID = px.PID, EntityCodeID = px.EntityCodeID, EntityType = ecx.DisplayLabel };
额外提醒
你创建的新IDMS_Partner对象,如果后续要用来更新数据库,一定要把主键PID和关联字段EntityCodeID也赋值,不然EF找不到要更新的目标记录,只会当成新数据插入哦。
内容的提问来源于stack exchange,提问作者Karan
相关产品推荐
相关产品推荐

