【问题标题】:WCF OData Service stored procedure call generates "Operation could destabilize the runtime" error with $select optionWCF OData 服务存储过程调用使用 $select 选项生成“操作可能破坏运行时”错误
【发布时间】:2015-02-07 02:37:18
【问题描述】:

我一直在尝试通过实体框架和 WCF 数据服务 (OData) 调用存储过程。它返回一个实体而不是复杂类型。按照在网上找到的演练(比如one),我在我的服务中想出了这段代码:

[WebGet]
public IQueryable<Entity> GetEntitiesByParameterId(int parameterId)
{
     return CurrentDataSource.GetEntitiesByParameterId(parameterId).AsQueryable();
}

以这种方式调用 proc:~WcfService.svc/GetEntitiesByParameterId?parameterId=1 执行存储过程并返回应返回的实体。没问题。

在我尝试使用 $select OData 选项之前,一切正常。 ~WcfService.svc/GetEntitiesByParameterId?parameterId=1&amp;$select=name。调试时,上面的方法运行时没有任何错误,但它在到达客户端时返回 Operation could destabilize runtime 错误。经过这么多研究,显然这是一个非常普遍的错误,指向很多不同的原因。我还没有找到一个真正符合我的特定问题的。最接近的是 thisthis,但没有一个解决方案对我有用。

另外,来自上面的第二篇文章:

这是 WCF DS 的一个已知限制。 ...

其次是一些查询不能正常工作,因为 LINQ to EF 与 LINQ to Objects 的 LINQ 表达式几乎没有什么不同 一些案例。你看到的是哪个问题。

2012 年发布。如果是真的,现在还没有更新吗?还有其他解决方法可以让 $select 在存储的 proc 调用上工作吗?

TL;DR:

作品:

~WcfService.svc/GetEntitiesByParameterId?parameterId=1
~WcfService.svc/GetEntitiesByParameterId?parameterId=1&$top=1
~WcfService.svc/GetEntitiesByParameterId?parameterId=1&$skip-5
~WcfService.svc/GetEntitiesByParameterId?parameterId=1&$filter={filter query}
~WcfService.svc/GetEntitiesByParameterId?parameterId=1&$expand=SomeNavigationProperty

不起作用:

~WcfService.svc/GetEntitiesByParameterId?parameterId=1&$select=name

技术细节:

EntityFramework 5、WCF 数据服务 5.0、OData V3

*我也尝试升级到 EF6 和 WCF 5.6.2,但还是不行。

任何帮助将不胜感激。谢谢!


更新: 经过一番摸索之后,我尝试不通过存储过程,只返回一个手动构造的List&lt;Entity&gt;,然后将其作为可查询返回。惊讶地发现使用 $select 时它仍然有相同的错误。这可能是 WCF 服务操作限制,而不仅仅是存储过程调用。我回到documentation,它确实显示了其他 OData 查询(顶部、展开和排序)的使用情况,但没有关于 $select。

这只是通过我的测试观察到的,因为我找不到这个特定问题的太多来源。欢迎任何澄清和其他文件。

【问题讨论】:

  • 恐怕还不支持$select。但是要解决此问题,您可以实现另一个操作,例如 GetEntitiesNameByParameterId 来包装 GetEntitiesByParameterId 并在此操作中选择名称。此操作返回名称的集合。
  • @LaylaLiuMSFT 嗨!谢谢你。我想澄清一下你所说的:“$select 仍然不受支持。”这仅适用于存储过程调用还是一般用于 WCF 服务操作?既然已经讨论过放弃对 WCF 的进一步更新,您知道什么时候会支持它吗?
  • @LaylaLiuMSFT 更新了我的帖子以获得进一步的观察。另外,感谢您的解决方法,但我希望 $select 更加动态和灵活,即。根据需要添加/删除尽可能多的列,例如 OData 的操作方式。再次感谢您抽出宝贵时间。

标签: select entity-framework-5 odata entity-framework-6 wcf-data-services


【解决方案1】:

根据 Layla Liu MSFT 的评论,尽管我找不到任何关于它的权威文档,但仍然不支持 $select。

根据我的收集和观察,$select 会中断存储过程调用,因为它会尝试更改已从数据库中获取的数据形状并尝试返回动态实体。关于返回 ObjectResult 的存储过程的某些东西可能会搞砸。至于为什么硬编码的List&lt;Entity&gt; 不起作用,我不知道。但是,不要引用我的话。正如我所说,这些只是我的观察。

解决方法:我找到了一个简单而优雅的解决方法。由于我的存储过程仅从数据库中获取数据并且不会以任何方式更改数据(INSERT、UPDATE、DELETE),因此我尝试使用返回与我的 EF 上的实体等效的表的表值函数。我发现在服务操作方法上调用这个函数会返回一个IQueryable&lt;Entity&gt;,这基本上是需要的。 $select 现在也可以使用,其他 OData 查询选项也可以使用。

步骤:

  1. 在数据库上创建函数
  2. 更新 EDMX -> 添加功能
  3. 添加具有实体返回类型的新函数导入
  4. 在 WCF 数据服务中创建调用CurrentDataSource.&lt;FunctionName&gt;() 的服务操作
  5. 在提琴手中测试。

代码

数据库功能:

CREATE FUNCTION GetEntities(@parameter)
RETURN @entites TABLE(
    [Id] [int], 
    [Name] [nvarchar](100),
    ...
)
AS
BEGIN      
    INSERT INTO @entities
       SELECT [Id], [Name], ... FROM [EntityTable]

    RETURN      
END

WCF:

[WebGet]
public IQueryable<Entity> GetEntity(int parameter)
{
     return CurrentDataSource.GetEntity(parameter);
}

它并没有真正解决存储过程问题,但我将其标记为答案,直到有人可以提供更好的答案,因为它确实解决了我正在尝试做的事情。

希望这对其他人也有帮助。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 2012-11-05
    相关资源
    最近更新 更多