实体框架“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 是仅存储我的IDUUID 的类。

这是我的 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 调用的,并且在它上面有一个查询。”返回对象的错误的主要内容,如果未能解决你的问题,请参考以下文章

实体框架分离实体和相关实体消失

为啥实体框架要复数和大写实体类名?

实体框架/LINQ/SQL 与实体框架/LINQ/MYSQL

使用实体框架的报告服务

使用 automapper 更新实体框架实体

无法查看实体 - 实体框架的数据模型