实体框架“FromSqlRaw 或 FromSqlInterpolated 是用不可组合的 SQL 调用的,并且在它上面有一个查询。”返回对象的错误
Posted
技术标签:
【中文标题】实体框架“FromSqlRaw 或 FromSqlInterpolated 是用不可组合的 SQL 调用的,并且在它上面有一个查询。”返回对象的错误【英文标题】:Entity Framework "FromSqlRaw or FromSqlInterpolated was called with non-composable SQL and with a query composing over it." error for a return object 【发布时间】:2021-11-28 10:35:16 【问题描述】:我有这个观点
[Table("vw_Entity", Schema = "c")]
public partial class vw_Entity : BaseEntity
public long? PredictedEntityTypeID get; set;
public bool IsManuallyChanged get; set;
其中BaseEntity
是仅存储我的ID
和UUID
的类。
这是我的 DTO 返回对象:
public class EntityDTO
public long ID get; set;
public LookupTableDetails PredictedEntityTypeId get; set;
public bool IsManuallyChanged get; set;
LookupTableDetails
的样子:
public class LookupTableDetails
public long Id get; set;
public string Name get; set;
现在我有了这个存储过程,它基本上是一个PATCH
。我使用以下 sn-p 调用它:
var data = await _context.vw_Entity.FromSqlRaw("EXECUTE core.Update_Entity @EntityID", parameters)
.Select(x => new EntityDTO()
ID = x.ID,
PredictedEntityTypeId = new LookupTableDetails() Id = x.PredictedEntityTypeId, Name = x.PredictedEntityTypeId == 1 ? "Entity1" : "Entity2" ,
IsManuallyChanged = x.IsManuallyChanged
).ToListAsync();
但是,这会因错误而崩溃
FromSqlRaw 或 FromSqlInterpolated 是使用不可组合的 SQL 调用的,并且在其上包含查询
我知道这个错误的作用,如果我的视图中有其他类的对象,则存储过程无法正确映射它并返回错误,但在这种情况下,我的视图很清楚这种类型,我需要做的就是在我的DTO
对象中返回LookupTableDetails
。错误在
PredictedEntityTypeId = new LookupTableDetails() Id = x.PredictedEntityTypeId, Name = x.PredictedEntityTypeId == 1 ? "Entity1" : "Entity2"
我尝试了互联网提供的大多数解决方案,例如用IgnoreFilters..
、AsEnumerable()
等包裹它。
任何想法是什么原因以及如何防止它在未来再次发生,即修复它? :D
【问题讨论】:
我知道这个错误是什么意思 你是吗? EF 尝试将整个查询转换为 SQL。这需要一个由存储过程结果组成的 SQL 语句,这是不可能的。AsEnumerable()
应该可以,但你没有展示你是如何尝试的。
AsEnumerable()
在 ToListAsync()
之前使用。代码看起来像.Select(x => ...) ... .AsEnumerable().ToList();
。但是AsEnumerable()
不是一个更糟糕的解决方案,因为我在某处读到AsEnumerable()
将返回所有记录,然后我需要在我的代码中进行额外的过滤,而此过程为不同的输入参数返回不同的记录.基本上,代码将包含许多 if..else
用于不同的输入参数,并且有许多过滤器,在我的情况下我想避免
好吧,别无选择。您必须按原样执行存储过程。 AsEnumerable()
应添加在 Select
之前。
好的,谢谢你的帮助:)
【参考方案1】:
由于您迭代了第一个查询的结果,请尝试更改为:
var data = _context.vw_Entity.FromSqlRaw("EXECUTE core.Update_Entity @EntityID", parameters)
.ToList() // force change from IQueryable to IEnumerable and resolve result
.Select(x => new EntityDTO() // You are anyway using all results, so this is ok
ID = x.ID,
PredictedEntityTypeId = new LookupTableDetails() Id = x.PredictedEntityTypeId, Name = x.PredictedEntityTypeId == 1 ? "Entity1" : "Entity2" ,
IsManuallyChanged = x.IsManuallyChanged
).ToList();
【讨论】:
我收到错误IEnumerable does not contain a definition for ToListAsync()
哦,是的,它不存在抱歉,正在从您的代码中重组,将更新
是的,不用担心,一切都好。谢谢你的帮助:)
@anthino12 所以它为你解决了问题,我很好奇你的问题是什么
不,它没有。问题是,我的程序返回了一个PredictedEntityTypeID
值。在这种情况下,我尝试直接在.Select()
中构造对象并弹出错误。如果我在这个.Select()
语句之后执行foreach(var d in data) PredictedEntityTypeID = new LookupTableDetails() Id = d.PredictedEntityTypeID..
,代码效果很好。以上是关于实体框架“FromSqlRaw 或 FromSqlInterpolated 是用不可组合的 SQL 调用的,并且在它上面有一个查询。”返回对象的错误的主要内容,如果未能解决你的问题,请参考以下文章