SqlMetal 错误地生成我的存储过程的返回类型 (LINQ)

2024-01-28

您好,有一个存储过程,它总是根据参数返回一行:

IF @bleh = 1
  SELECT TOP 1 Xyz FROM Abc
ELSE
  SELECT TOP 1 Def FROM Abc

我必须使用 SqlMetal 生成 DataContext 但此存储过程返回一个IMultipleResults,这是一个错误。相反,它应该返回一个ISingleResult...

如果我删除 if (放一个SELECT调用),一个ISingleResult返回类型已生成。

有任何想法吗?


您所描述的场景是设计使然。我已经使用 .NET 3.5 和 .NET 4.0 Beta 2 进行了测试,并得到了相同的结果。给定一个像您一样使用 IF/ELSE 结构的 SPROC,生成的结果和使用的工具是:

  • SqlMetal: I多重结果
  • LINQ To SQL 设计器(在 VS IDE 中拖放):单一结果

This is 马特·沃伦支持 http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/ce90169d-70e7-41e7-9828-aca0eceab769/在微软:

设计者无法识别存储的 具有多个返回值的过程和 将把它们全部映射到返回 单个整数。

SQLMetal 命令行工具可以 识别多个结果并 将键入方法的返回值 正确地作为 IMultipleResults。你 可以使用 SQLMetal 或修改 手动 DBML 或添加方法 将此存储过程的签名发送给您 为你自己的部分课程 数据上下文。

In 这篇博文 http://blogs.msdn.com/dinesh.kulkarni/archive/2008/05/16/linq-to-sql-tips-7.aspxDinesh Kulkarni 评论了相反的情况,即设计者不添加 IMultipleResults 而是使用 ISingleResult。他指出(强调是后加的):

不,设计师不支持 此功能。所以你必须添加 部分类中的方法。 Sql金属 但是会提取存储过程。这 原因是一个实施 细节:两者使用相同的代码 生成器但数据库不同 模式提取器。

此外,标题为“处理存储过程中的多个结果形状”的部分斯科特·顾的帖子 http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx and 这篇 MSDN 文章 http://msdn.microsoft.com/en-us/library/bb399371.aspx两者都显示 IMultipleResults 与使用相同结构的 SPROC 一起使用。

太好了,现在怎么办?有一些解决方法,其中一些比其他更好。


重写存储过程

您可以重写 SPROC,以便 SqlMetal 使用 ISingleResult 生成函数。这可以通过以下方式实现

重写 #1 - 将结果存储在变量中:

DECLARE @Result INT
IF @Input = 1
    SET @Result = (SELECT TOP 1 OrderId FROM OrderDetails)
ELSE
    SET @Result = (SELECT TOP 1 ProductId FROM OrderDetails ORDER BY ProductId DESC)

SELECT @Result As Result

显然,这些类型需要相似或者可以转换为其他类型。例如,如果一个人是INT另一个是DECIMAL(8, 2)您可以使用小数来保持精度。

重写 #2 - 使用 case 语句:

这与马克的建议 https://stackoverflow.com/questions/2037280/sqlmetal-wrongly-generates-the-return-type-of-my-stored-proc-linq/2150955#2150955.

SELECT TOP 1 CASE WHEN @Input = 1 THEN OrderId ELSE ProductId END FROM OrderDetails

使用 UDF 代替 SPROC

你可以使用标量值 UDF http://msdn.microsoft.com/en-us/library/bb386973.aspx并调整您的查询以使用 UDF 格式(与上面提到的变量方法相同)。 SqlMetal 将为它生成一个 ISingleResult,因为只返回一个值。

CREATE FUNCTION [dbo].[fnODIds] 
(
    @Input INT
)
RETURNS INT
AS
BEGIN
    DECLARE @Result INT

    IF @Input = 1
        SET @Result = (SELECT TOP 1 UnitPrice FROM OrderDetails)
    ELSE
        SET @Result = (SELECT TOP 1 Quantity FROM OrderDetails ORDER BY Quantity DESC)

    RETURN @Result

END

伪造 SPROC 并将其关闭

这可行,但比以前的选项更乏味。此外,将来使用 SqlMetal 将覆盖这些更改并需要重复该过程。使用分部类并将相关代码移动到那里将有助于防止这种情况。

1)更改您的 SPROC 以返回单个SELECT语句(注释掉你的实际代码),例如SELECT TOP 1 OrderId FROM OrderDetails

2)使用 SqlMetal。它将生成一个 ISingleResult:

[Function(Name = "dbo.FakeODIds")]
public ISingleResult<FakeODIdsResult> FakeODIds([Parameter(Name = "Input", DbType = "Int")] System.Nullable<int> input)
{
    IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), input);
    return ((ISingleResult<FakeODIdsResult>)(result.ReturnValue));
}

3)将您的 SPROC 更改回其原始形式,但对返回的结果使用相同的别名。例如,我将返回both OrderId and ProductId as FakeId.

IF @Input = 1
    SELECT TOP 1 OrderId As FakeId FROM OrderDetails
ELSE
    SELECT TOP 1 Quantity As FakeId FROM OrderDetails ORDER BY Quantity DESC

请注意,我在这里没有使用变量,而是直接使用您最初开始使用的格式。

4)由于我们使用 FakeId 别名,因此我们需要调整生成的代码。如果您导航到在步骤 2 中为您生成的映射类(FakeODIdsResult就我而言)。该类将使用代码中步骤 1 中的原始列名称,OrderId就我而言。事实上,如果步骤 1 中的语句以别名开头,则可以避免这整个步骤,即:SELECT TOP 1 OrderId As FakeId FROM OrderDetails。如果你没有,你需要进去并调整一些东西。

FakeODIdsResult 将使用OrderId,它不会返回任何内容,因为它是别名FakeId。它看起来类似于:

public partial class FakeODIdsResult
{
    private System.Nullable<int> _OrderId;

    public FakeODIdsResult()
    {
    }

    [Column(Storage = "_OrderId", DbType = "Int")]
    public System.Nullable<int> OrderId
    {
        get
        {
            return this._OrderId;
        }
        set
        {
            if ((this._OrderId != value))
            {
                this._OrderId = value;
            }
        }
    }
}

你需要做的是重命名OrderId to FakeId and _OrderId to _FakeId。完成后,您可以像平常一样使用上面的 ISingleResult,例如:

int fakeId = dc.FakeODIds(i).Single().FakeId;

这总结了我在该主题上使用过并能够找到的内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SqlMetal 错误地生成我的存储过程的返回类型 (LINQ) 的相关文章

随机推荐

  • 在c中对二维数组进行排序

    我正在尝试对二维数组进行排序 原始数组是 5 0 3 4 1 2 3 1 1 4 2 2 3 3 1 排序后 应该是这样的 3 1 1 3 3 1 4 2 2 4 1 2 5 0 3 这是我用来尝试实现冒泡排序的代码 i 代表行数 int
  • JMeter 3.2 中不存在 SOAP/XML-RPC Sampler

    我有点惊讶我的 JMeter 3 1 脚本在 3 2 中不起作用 JMeter 3 2 中删除 SOAP XML RPC Sampler 的原因是什么 是否存在一些性能问题等 这是 JMeter 的一部分change http jmeter
  • 在 Windows 窗体应用程序中托管 ASP.NET Core API

    背景 我正在开发一个涉及 WinForms 应用程序的项目 客户端希望公开一个仅限本地的 HTTP 服务器 以允许其他应用程序通过 REST API 或类似 API 触发正在运行的 WinForms 应用程序实例上的功能 首选是使用 ASP
  • UIWebview、iOS 中的视频自动播放

    例如我有网址https www youtube com watch v c2ccXwwmcnA 如果我将此 URL 传递给UIWebView它会自动play视频 我尝试过以下方法 Option 1 property weak nonatom
  • 使用 for 循环初始化 C 结构

    我正在创建一个质量中心程序 并试图对其进行概括 它最多仅适用于 3D 使用具有 3D 和质量元素的结构 类型对象的变量数量 我希望由用户而不是我来定义 但我找不到使用循环创建变量的方法 也许有不同的方法可以做到这一点 但我只是不知道 这是我
  • Seam/JSF 表单提交触发按钮 onclick 事件

    我有一个带有查询生成器的搜索表单 构建器通过按钮激活 像这样的东西
  • std::vector 是否满足 Boost.Interprocess 分配器的容器要求?

    In boost interprocess文档称容器存储在共享内存中的要求 STL容器可能不会假设用分配器分配的内存可以用相同类型的其他分配器释放 仅当一个对象分配的内存可以与另一个对象一起释放时 所有分配器对象才必须比较相等 并且只能使用
  • Scala 中如何省略匹配词?

    在Scala中 你可以这样做 list filter item gt item match case Some foo gt foo bar gt 0 但您也可以通过省略来实现更快的方法match list filter case Some
  • Printf 即使它不应该

    我有 if 语句的这一部分 并且得到了奇怪的输出 int x 10 if 1 lt x lt 5 printf F n 为什么它打印 F 从逻辑上讲 if 语句不是假的 因为 x 大于 1 但不小于 5 在 C 语言中 你不能像这样链接比较
  • Twitter Bootstrap Carousel 插件能否在幻灯片过渡时淡入淡出

    我在我正在开发的网站上有一个非常基本的 Twitter Bootstrap Carousel 插件实现 http furnitureroadshow com http furnitureroadshow com 我只是想知道是否有人扩展了轮
  • std::sort 崩溃 - 没有严格弱排序的排序

    我正在尝试对项目向量进行排序 正如代码注释中提到的 顺序应该是 具有更多行动点的参与者 mAp 先走 当出现平局时 具有相同倾向的参与者 mDisposition 作为战斗的发起者 mBattleInitiator 先走 以下代码 简化示例
  • MongoError:'$push'中的美元($)前缀字段'$push'对于存储无效

    我在尝试着upsert数据集到 Mongo 集合 The intended document may or may not exist 如果确实存在 它将在嵌入文档 zip 中至少包含一项 并且应附加到该文档而不是覆盖它 如果不存在 则应将
  • 子类中是否有符合自定义协议的常规空白函数?

    我的应用程序中有两个主屏幕 目前两者都只是UIViewController 这两个视图控制器非常相似 它们都实现了我的自定义子类UIView called HeaderView负责显示信息并接受用户输入 就目前而言 这段代码是重复的 因为H
  • 为什么匿名联合不能包含具有重要构造函数/析构函数的成员?

    我可能是错的 但我发现的基本解释是联合无法初始化 因为它不知道要调用哪个成员的构造函数 编译器无法自动生成联合的构造函数 为什么不允许用户定义 union 构造函数 这将消除上述问题并允许具有重要构造函数 析构函数的工会成员的存在 另外 为
  • 从 iOS 上传多个图像到 S3 的有效方法

    我在应用程序中使用 Amazon S3 作为我的文件存储系统 我的所有项目对象都有多个与之关联的图像 每个图像仅存储图像 URL 以保持数据库的轻量级 因此 我需要一种有效的方法来直接从 iOS 上传多个图像到 S3 并在成功完成后将它们的
  • Drools - 使用累积来查找最小值和最大值

    我有一个流口水的问题 困扰我一段时间了 我想使用累积从 Item 对象列表 包含价格 中找出最低和最高价格 插入一个包含 Item 列表的 Member 对象 包含 Item 对象列表 groovy java source pseudo c
  • WordPress“REST API”-渲染 VisualComposer 内容

    我正在通过 REST API V2 插件从 WordPress 请求内容 这很好用 只剩下一个问题 由 VisualComposer 插件创建的内容不会在 de REST Response 中呈现 回应是 vc row Hello Worl
  • 如何使用vue + axios在get请求中使用async/await?

    我有以下代码 想知道如何使用 async await 执行相同的函数来实现 try catch import Vue from vue import axios from axios new Vue el app data skills m
  • 如何在 Powershell 中使用基于当前日期的名称创建文件夹?

    我有大约 50 个 xml 文件 每次运行特定逻辑时都会新生成这些文件 现在我希望将这 50 个文件存储在特定的日期时间文件夹中 无论我为某个特定日期运行该逻辑多少次 都应该仅针对该特定日期覆盖 xml 文件 基于 hhmmss 简单来说
  • SqlMetal 错误地生成我的存储过程的返回类型 (LINQ)

    您好 有一个存储过程 它总是根据参数返回一行 IF bleh 1 SELECT TOP 1 Xyz FROM Abc ELSE SELECT TOP 1 Def FROM Abc 我必须使用 SqlMetal 生成 DataContext