当前位置: 首页 > 编程语言 > C#

使用LINQ共享时VBTryCast和C#“as”运算符的区别

时间:2023-04-11 02:39:09 C#

使用LINQ时VBTryCast和C#“as”运算符的区别我有一个LINQ查询来检索整数列的最大值。该列在数据库中定义为NOTNULL。但是,在SQL中使用MAX聚合函数时,如果查询没有返回任何行,您将得到NULL结果。下面是我在Northwind数据库上使用的LINQ查询示例,用于演示我在做什么。varmaxValue=(frompinnw.Productswherep.ProductID<0selectp.ProductIDasint?).Max();C#正确解析此查询,而maxValue是int类型?.此外,生成的SQL是完美的:SELECTMAX([t0].[ProductID])AS[value]FROM[Products]AS[t0]WHERE[t0].[ProductID]<@p0问题是,如何使用VB.NET并得到相同的结果?如果我直接翻译:dimmaxValue=(frompinProductswherep.ProductID<0selectTryCast(p.ProductID,integer?)).Max()我得到一个编译错误。TryCast仅适用于引用类型,不适用于值类型。TryCast和“as”在这方面略有不同。C#为装箱处理值类型做了一些额外的工作。因此,我的下一个解决方案是使用CType而不是TryCast:dimmaxValue=(frompinProductswherep.ProductID>0selectCType(p.ProductID,integer?)).Max()这有效,但它会生成以下内容SQL:SELECTMAX([t1].[value])AS[value]FROM(SELECT[t0].[ProductID]AS[value],[t0].[ProductID]FROM[Products]AS[t0])AS[t1]WHERE[t1].[ProductID]>@p0虽然这是正确的,但不是很干净。当然,在这种特殊情况下,SQLServer可能会将查询优化为与C#版本相同,我可以想象情况可能并非如此。有趣的是,在C#版本中,如果我使用普通转换(即(int?)p.ProductID)而不是使用“as”运算符,我会得到与VB版本相同的SQL。有谁知道VB中是否有办法为这种类型的查询生成最佳SQL?简短的回答:可以。那么长答案:我能看到你可以做到这一点的唯一方法是显式创建包含TypeAs转换的lambda。您可以使用以下扩展方法来帮助您:_PublicModuleTypeAsExtensions_PublicFunctionSelectAs(OfTElement,TOriginalType,TTargetType)(_ByValsourceAsIQueryable(OfTElement),_ByVal选择器AsExpression(OfFunc(OfTElement,TOriginalType)))_AsIQueryable(OfTTargetType)ReturnQueryable.Select(source,_Expression.Lambda(OfFunc(OfTElement,TTargetType))(_Expression.TypeAs(selector.Body,GetType(TTargetType)),_选择器.Parameters(0)))EndFunction_PublicFunctionSelectAsNullable(OfTElement,TTypeAsStructure)(_ByValsourceAsIQueryable(OfTElement),_ByValselectorAsExpression(OfFunc(OfTElement,TType)))_AsIQueryable(OfTType?)ReturnSelectAs(OfTElement,TType,TType?)(source,selector)EndFunctionEndModuleSelectAs导致任何T的TryCast(value,T),包括Integer?。你会说,使用它DimmaxValue=Products_.Where(Function(p)p.ProductID这不是很漂亮,但它有效。(这会生成与C#相同的查询。)只要你不在子查询中调用SelectAsNullable,就是这样。另一种选择可能是使用DimmaxValue=(FrompInProducts_Wherep.ProductID这个问题是你得到一个双重选择,即从pinProductswherep.ProductIDinC#。引用LINQtoSQL仍然可以be这会生成一个子查询。无论如何,为此你可以创建一个额外的扩展方法TType,TType,TType?)(source,Function(x)x)EndFunction进一步简化LINQ查询DimmaxValue=(FrompInProducts_Wherep.ProductID但正如我所说,这取决于LINQ提供者。DimmaxValue=ctype((FrompIndb.Products_Wherep.ProductID>0_Selectp.ProductID).Max(),Integer?)天哪,PITADimmaxValue=(FrompIndb.Products_Wherep.ProductID>300_SelectnewWith{.id=CType(p.ProductID,Integer?)}).Max(Function(p)p.id)有更好的方法吧?这具有所需的查询计划,没有空错误,但有人可以看到并清理它吗?C#varmaxValue=nw.Products.Where(p=>p.ProductIDp.ProductID).DefaultIfEmpty(int.MinValue).Max();VBDimmaxValue=nw.Products_.Where(Function(p)p.返回Nullable的ProductID函数怎么样?(如果语法不太正确,请见谅。)函数GetNullable(OfT)(valasObject)If(valIsNothing)ThenReturnnewNullable(OfT)()ElseReturnnewNullable(OfT)(DirectCast(val,T))EndIfEndFunctiondimmaxValue=(frompinProductswherep.ProductID为什么不在查询中构建一个等效的isnull检查?dimmaxValue=(frompinProductswhereIIf(p.ProductID=Null,0,p.ProductID)对不起,如果这个doesn'tworkwhatitdoes-我并没有在这方面实际测试它,只是向墙上扔意大利面!如果对大家有用,需要了解更多C#学习教程,希望大家多多关注---本文收集自网络,不代表立场,如涉及侵权,请右击联系管理员删除,如有转载请注明出处: