' 1St step
Dim irregularWeldSpots = From row In spotsTable.AsEnumerable()
Where (CStr(row("FUNCJOINTCODE")) = currentJointKey
And ((Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) >= defectiveSpotIfSizeLessThanPercent
And (Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) < insufficientSpotIfSizeLessThanPercent)
Or (Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT")) < defectiveSpotIfSizeLessThanPercent))
Select Case row
, IsInsufficient = ((Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) >= defectiveSpotIfSizeLessThanPercent
And (Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) < insufficientSpotIfSizeLessThanPercent)
, IsDefect = (Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) < defectiveSpotIfSizeLessThanPercent
' 2nd step
EvaluateDistanceBetweenIrregularSpots(resultTable,definitionsTable,currentJointKey,allWeldSpots,allWeldSpotsCount,defectiveWeldSpotsCount,
insufficientWeldspotsCount,irregularWeldSpots)
' 3rd step
Private Sub EvaluateDistanceBetweenIrregularSpots(ByRef resultTable As DataTable, ByRef definitionsTable As DataTable, As String, allWeldSpots As IEnumerable, allWeldSpotsCount As Integer, As Integer, insufficientWeldspotsCount As Integer,
As IEnumerable)
If Not ((insufficientWeldspotsCount + defectiveWeldSpotsCount) > 1) Then Return
For Each spot1 In irregularWeldSpots
If spot1.row("XUNIT") Is Nothing Then Continue For
For Each spot2 In irregularWeldSpots
If spot1.row("SPOTDESC") = spot2.row("SPOTDESC") Then Continue For
Dim x0 As Double = spot1.row("XUNIT")
Dim x As Double = spot2.row("XUNIT")
Dim y0 As Double = spot1.row("YUNIT")
Dim y As Double = spot2.row("YUNIT")
Dim z0 As Double = spot1.row("ZUNIT")
Dim z As Double = spot2.row("ZUNIT")
Dim distance As Double = Math.Sqrt((x - x0) ^ 2 + (y - y0) ^ 2 + (z - z0) ^ 2)
If distance >= spot1.row("LENSDIAMUNIT") Then Continue For
Dim message As String = String.Empty
If spot1.IsDefect And spot2.IsDefect Then
message = "One defect spot was found inside the sphere around another defect spot"
ElseIf (spot1.IsDefect And spot2.IsInsufficient) Or (spot1.IsInsufficient And spot2.IsDefect) Then
message = "One insufficient spot was found inside the sphere around a defect spot"
End If
If message.Length > 0 Then
Dim newRow As DataRow = resultTable.NewRow()
newRow("JointNo") = jointNumber
newRow("StatusMessage") = message
newRow("SpotCount") = allWeldSpotsCount
newRow("Insufficient") = insufficientWeldspotsCount
newRow("Defective") = defectiveWeldSpotsCount
newRow("SphereRadius") = "-"
resultTable.Rows.Add(newRow)
End If
Next
Next
End Sub
在“ spot1.row(..)&spot2.row(..)”上将选项strict设置为ON后,进行后期绑定的第三步问题
答案 0 :(得分:0)
您应该能够从之前的代码中找出要做什么。在步骤1中,您似乎已经认识到索引row
返回的可能是Object
引用的事实,因此,如果要使用值作为其实际类型,则需要强制转换/转换为该值类型。在步骤1的代码中,您具有:
CStr(row("FUNCJOINTCODE"))
和:
(Convert.ToDecimal(row("RESULTUNIT"))
要在其中使用值作为类型String
或Decimal
的地方,那么为什么在第3步中要在其中使用值作为类型Double
的地方有什么不同,例如
Dim x0 As Double = CDbl(spot1.row("XUNIT"))
虽然没什么大不了的,但实际上您只需要在实际需要转换数据类型时才使用Convert
。例如,如果row("RESULTUNIT")
实际上包含一个String
,并且您需要将其转换为Decimal
,则Convert.ToDecimal
是合适的,但是如果数据已经是Decimal
那么您只需要执行转换,因为不需要转换。在这种情况下,您应该使用CDec
。
此外,您不应该一遍又一遍地使用相同的复杂表达式。在步骤1中,您多次使用(Convert.ToDecimal(row("RESULTUNIT"))
,这很不好。我会像这样写第1步代码:
Dim irregularWeldSpots = From row In spotsTable.AsEnumerable()
Let resultUnit = CDec(row("RESULTUNIT")),
lensDiamUnit = CDec(row("LENSDIAMUNIT"))
Where (CStr(row("FUNCJOINTCODE")) = currentJointKey AndAlso
resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent) OrElse
resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent
Select row,
IsInsufficient = resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent,
IsDefect = resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent
请注意,现在通过缩进更好,使用Let
子句在查询本地创建变量,现在更容易阅读,并且还使用更正确的AndAlso
和{{1} },而不是'And OrElse
Or`。我还删除了多余的括号,但您可能希望保留这些括号。
关于括号,我想知道您在and
子句中是否正确。请注意,Where
和And
运算符总是优先于AndAlso
和Or
运算符进行评估,因此,无论是否有多余的括号,都将匹配记录,其中前三个条件匹配或最后一个条件匹配。也许这就是您想要的,但我怀疑您实际想要的是第一个条件以及第二个,第三个或第四个条件都匹配。如果是这样,那么:
OrElse
会来这的
Where (CStr(row("FUNCJOINTCODE")) = currentJointKey AndAlso
resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent) OrElse
resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent
编辑:
现在,问题更加清楚了,我意识到该代码来自多种方法。而不是使用匿名类型,您应该定义自己的类型:
Where CStr(row("FUNCJOINTCODE")) = currentJointKey AndAlso
((resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent) OrElse
resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent)
然后,您可以更改LINQ查询以创建该类型的实例,而不是匿名类型的实例:
Public Class SpotRow
Public Property Row As DataRow
Public Property IsInsufficient As Boolean
Public Property IsDefect As Boolean
End Class
然后,您可以将生成的列表作为Select New SpotRow With {.Row = row,
.IsInsufficient = resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent,
.IsDefect = resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent}
而不是IEnumerable(Of SpotRow)
进行传递。我不会尝试提供方法声明,因为您发布的代码是荒谬的,因为它具有没有参数名称的参数类型。只需更改相关参数的类型即可。您会发现现在可以访问每个项目的IEnumerable
属性。