如何在LINQ中填充单个属性?VB.NET查询填充未映射属性遇阻
解决LINQ Join后未映射属性赋值不生效的问题
嗨,这问题我之前处理过,大概率是EF的延迟加载和查询执行时机在搞鬼,咱们一步步来搞定它!
问题根源
你用AsEnumerable()的时候,其实并没有真正触发数据库查询——EF的IQueryable是延迟执行机制,只有当你真正开始枚举(比如foreach循环)的时候才会去数据库拉取数据。这时候可能出现的情况是:循环里的t1还是EF生成的动态代理对象,或者因为延迟加载的特性,赋值操作没有被正确应用到内存中的实体上。
解决方案1:强制立即执行查询
把AsEnumerable()换成ToList(),这样EF会立刻把查询结果完整加载到内存里,循环时操作的就是实实在在的内存对象,赋值自然就生效了:
' 先把查询结果加载到内存 Dim query = (From t1 In context.table1 Join t2 In context.table2 On t1.ID Equals t2.ID Select t1, t2).ToList() ' 再循环赋值 For Each val In query val.t1.t2property = val.t2 Next
解决方案2:关闭跟踪避免代理干扰
如果上面的方法还是不行,可能是EF的动态代理在捣乱——代理对象会拦截属性访问,未映射的属性可能会被忽略。这时候可以给查询加上AsNoTracking(),让EF不生成代理对象:
Dim query = (From t1 In context.table1.AsNoTracking() Join t2 In context.table2.AsNoTracking() On t1.ID Equals t2.ID Select t1, t2).ToList() For Each val In query val.t1.t2property = val.t2 Next
额外小技巧:投影到匿名类型再处理
也可以在查询时明确投影出需要的对象,这样逻辑更清晰,也能避免EF跟踪机制的影响:
Dim query = (From t1 In context.table1 Join t2 In context.table2 On t1.ID Equals t2.ID Select New With { .TargetT1 = t1, .SourceT2 = t2 }).ToList() For Each item In query item.TargetT1.t2property = item.SourceT2 Next
总结
核心就是确保查询结果被完全加载到内存中,避免延迟执行带来的对象状态问题。用ToList()是最直接的方式,遇到代理干扰就加AsNoTracking(),一般就能解决你的问题啦!
内容的提问来源于stack exchange,提问作者Rolan
相关产品推荐
相关产品推荐

