.net – SqlMetal错误地生成我的存储过程的返回类型(LINQ)
嗨有一个存储过程总是返回一行取决于一个参数:
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:IMultipleResults 这是微软的supported by Matt Warren:
在this blog post Dinesh Kulkarni评论了相反的情况,设计师没有添加IMultipleResults并使用ISingleResult.他说(重点补充):
此外,Scott Gu’s post和this MSDN article中标题为“处理来自SPROC的多个结果形状”的部分都显示IMultipleResults与使用相同结构的SPROC一起使用. 好的,现在怎么样?有一些解决方法,有些比其他更好. 重写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 – 使用案例陈述: 这与Mark’s suggestion相同. SELECT TOP 1 CASE WHEN @Input = 1 THEN OrderId ELSE ProductId END FROM OrderDetails 使用UDF而不是SPROC 您可以使用scalar-valued UDF并调整查询以使用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更改回其原始格式,但对返回的结果使用相同的别名.例如,我将OrderId和ProductId作为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作为FakeId来自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重命名为FakeId,将_OrderId重命名为_FakeId.完成后,您可以像往常一样使用上面的ISingleResult,例如: int fakeId = dc.FakeODIds(i).Single().FakeId; 这就结束了我已经使用过并且能够在主题上找到的内容. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |