Linq to Sql将varchar(x)参数调整为varchar(8000)

时间:2015-02-14 19:25:51

标签: vb.net linq visual-studio-2010

寻找我们服务器最近遇到的性能问题的可能原因(SQL Server 2008),我们发现了一些奇怪的东西:我们的一些系统使用LINQ to SQL来执行SELECTINSERT,{ {1}}和UPDATE次操作。事实是,如果表具有DELETE个字段,即使DBML将这些字段映射为varchar且表字段的大小相同,Linq也会使用varchar参数生成其查询。例如,我们说我有下一张桌子:

varchar(8000)

该表的DBML设计代码如下所示:

SampleTable
-----------------------------------
Field1        int
Field2        smallint
Field3        varchar(15)
Field4        varchar(50)

在我的程序中,在该表中插入行的方法具有以下代码:

<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_Field1", DbType:="Int NOT NULL")>  _
Public Property Field1() As Integer
    Get
        Return Me._Field1
    End Get
    Set
        If ((Me._Field1 = value)  _
                    = false) Then
            Me.OnField1Changing(value)
            Me.SendPropertyChanging
            Me._Field1 = value
            Me.SendPropertyChanged("Field1")
            Me.OnField1Changed
        End If
    End Set
End Property

<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_Field2", DbType:="SmallInt NOT NULL", IsPrimaryKey:=true)>  _
Public Property Field2() As Short
    Get
        Return Me._Field2
    End Get
    Set
        If ((Me._Field2 = value)  _
                    = false) Then
            Me.OnField2Changing(value)
            Me.SendPropertyChanging
            Me._Field2 = value
            Me.SendPropertyChanged("Field2")
            Me.OnField2Changed
        End If
    End Set
End Property

<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_Field3", DbType:="VarChar(15) NOT NULL", CanBeNull:=false)>  _
Public Property Field3() As String
    Get
        Return Me._Field3
    End Get
    Set
        If (String.Equals(Me._Field3, value) = false) Then
            Me.OnField3Changing(value)
            Me.SendPropertyChanging
            Me._Field3 = value
            Me.SendPropertyChanged("Field3")
            Me.OnField3Changed
        End If
    End Set
End Property

<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_Field4", DbType:="VarChar(50) NOT NULL", CanBeNull:=false)>  _
Public Property Field4() As String
    Get
        Return Me._Field4
    End Get
    Set
        If (String.Equals(Me._Field4, value) = false) Then
            Me.OnField4Changing(value)
            Me.SendPropertyChanging
            Me._Field4 = value
            Me.SendPropertyChanged("Field4")
            Me.OnField4Changed
        End If
    End Set
End Property

简化了代码

但Linq使用Public Sub InsertOnSampleTable(ByVal intValueForField1 As Integer, ByVal shortValueForField2 As Short, ByVal stringValueForField3 As String, ByVal stringValueForField4 As String) Dim dataContext as New SampleDataContext dataContext.Connection.Open() Dim sampleRow As New SampleTable With _ {.Field1= intValueForField1, _ .Field2 = shortValueForField2, _ .Field3 = stringValueForField3, _ .Field4 = stringValueForField4} dataContext.SampleTable.InsertOnSubmit(sampleRow) dataContext.SubmitChanges() datacontext.Connection.Close() dataContext.Dispose() End Sub 参数执行INSERT

varchar(8000)

通过互联网查看我发现this post表示它显然是Linq到Sql 4的错误,因为Visual Studio 2008创建的参数大小与DBML中的字段相同。它最终变成this bug report处于关闭状态,并表示该错误无法解决。

现在,虽然我不认为这可能导致我们服务器中出现所有性能问题,但这实际上是否会导致任何性能问题?这种大小变化是否会对实际查询执行产生任何影响?有没有人有这方面的问题和/或找到了解决方法?更多的好奇心而不是其他任何东西,这个 bug 是在更新版本的Visual Studio中解决的吗?我认为这实际上是一种奇怪的行为,如果问题没有得到解决,它会以某种方式使得在DBML中定义varchar字段的大小相当无用。

1 个答案:

答案 0 :(得分:0)

只要数据具有相同的基本类型,就不会导致任何性能问题。但请注意类型转换(varchar到nvarchar或nvarchar到varchar),因为它们绝对会破坏性能。

至于定义DBML中的大小是无用的,在某种程度上它是 - 一个包含20个字符的varchar(max)列,占用与varchar(8000)或varchar(20)一样多的空间。不同之处在于,最后一个说明了输入的可接受大小并且允许有效的索引(索引具有900个字符的限制)。

因此,该列的大小对具有概念性性能影响,使它们成为适当的大小。对于存储过程或批处理中的局部变量,没有性能影响,对于参数没有性能影响,但存在概念上的影响。

对于LINQ或任何其他ORM,请不要担心大小与此无关,请确保TYPE匹配。