Asp.net 在穷人';s ORM

Asp.net 在穷人';s ORM,asp.net,sql-server,vb.net,performance,Asp.net,Sql Server,Vb.net,Performance,我正在用遗留应用程序(.NET2.0Web应用程序,手工编码的SQL查询)实现一个穷人的ORM。我有两个数据类:Customer和Order: Public Class Customer Public Property CustomerId As Integer Public Property CustomerName As String Public Property Orders As List(Of Order) End Class Public Class Or

我正在用遗留应用程序(.NET2.0Web应用程序,手工编码的SQL查询)实现一个穷人的ORM。我有两个数据类:
Customer
Order

Public Class Customer
    Public Property CustomerId As Integer
    Public Property CustomerName As String
    Public Property Orders As List(Of Order)
End Class

Public Class Order
    Public Property OrderId As Integer
    Public Property OrderItem As String
End Class
Private Function getOrdersByCustomerId(ByVal customerId As Integer) As List(Of Order)

    Dim connection As New SqlConnection(connectionString)
    Dim command As New SqlCommand(sql, connection)
    Dim reader As SqlDataReader()

    connection.Open()

    reader = command.ExecuteReader()

    Dim orders As New List(Of Order)

    While reader.Read
        Dim order As New Order
        With order
            .OrderId =   reader("OrderId")
            .OrderItem = reader("OrderItem")
        End With
        orders.Add(order)
    End While

    connection.Close()

    Return orders

End Function
我正在使用
SqlDataReader
手动将SQL结果映射到
Customer
类的实例:

Dim connection As New SqlConnection(connectionString)
Dim command As New SqlCommand(sql, connection)
Dim reader As SqlDataReader()

connection.Open()

reader = command.ExecuteReader()

Dim customer As New Customer()

While reader.Read
    With customer
        .CustomerId =   reader("CustomerId")
        .CustomerName = reader("CustomerName")
        .Orders =       getOrdersByCustomerId(reader("CustomerId"))   ' get orders
    End With
End While

connection.Close()
为了填充
Customer.Orders
,我调用了一个函数,该函数返回一个
列表(订单)

我担心这个方法的性能,也就是说,如果我拉多个
客户
。对于每个
客户
,我必须再次点击数据库(打开另一个连接),并获取该客户的订单。如果我没有弄错的话,积累大量打开的连接不需要很多记录

我的问题有两个方面:

  • 如何确定正在建立的新连接的数量,以及是否会遇到任何连接池或其他.NET强加的限制
  • 有更好的办法吗?(见下文评论)

  • 我的一个想法是将调用类中创建的
    SQLConnection
    对象传递给
    getOrdersByCustomerId
    函数,并让该函数使用(显然?)已打开的连接。我没有测试它,因为我不知道如何确定它是否比我现有的方法更好。想法


    背景:


    我正在创建一个搜索web服务,它返回JSON供客户端处理。该服务接受单个搜索参数,对不同的表执行多个查找,然后返回一个自定义JSON对象。例如,如果用户输入的似乎是一个名称,我将在
    客户
    表中搜索前n名客户的列表,并在
    订单
    表中搜索前n名客户的名称。

    打开和重新打开连接实际上是免费的。因此,最好是在使用块中打开连接并尽快进行处理

    您可以通过添加
    Max Pool Size=1来测试连接泄漏到您的连接字符串。这会将可用连接数限制为1。如果你泄漏了一个连接,你会得到一个错误。请确保不要在生产中使用此设置


    为了提高性能,您通常会避免对大型集合中的每一行访问数据库。因此,您可以编写一个新的查询或过程来返回所有相关客户的所有订单。然而在实践中,这是一个不寻常的问题。您通常会显示客户列表,只有当最终用户放大该客户时,您才会检索订单列表。

    首先,您缺少使用语句的
    ,因此您的代码应该是这样的,而不是依赖
    垃圾收集器来自动处理它

    Using connection As New SqlConnection("connectionString")
        Using command As New SqlCommand("sql", connection)
            Using reader As SqlDataReader = Nothing
    
                connection.Open()
    
                reader = command.ExecuteReader()
    
                Dim customer As New Customer()
    
                While reader.Read
                    If True Then
                        customer.CustomerId = reader("CustomerId")
                        customer.CustomerName = reader("CustomerName")
                        customer.Orders = getOrdersByCustomerId(reader("CustomerId"))
                    End If
                End While
                connection.Close()
            End Using
        End Using
    End Using
    

    返回原始性能查询

    如果记录数量很大,我会使用
    DataTable
    。请记住,
    DataTable
    对象是在使用后以与上述类似的方式使用语句进行处理的。因此,不需要为添加记录而进行迭代

    再次转到数据库

    可以考虑使用<代码> VIEWSTATE/<代码>或<代码>会话<代码>,如果您发现数据有任何更改,您也可以使用<代码> SqLaseAs/<代码> < < /P> getOrdersByCustomerId(读卡器(“CustomerId”))


    您是否可以将所有与客户相关的信息(以加载表单时获取的信息为准)保存在
    ViewState
    ?在数据读取器中,反复访问数据库是不可取的。因此,最后在DataReader迭代中访问
    ViewState
    变量。

    处理此问题的数据库端。
    您不会显示用于检索记录的sql命令的任何内容

    例如,当您按ID加载客户时,尝试同时加载其订单

    SELECT CUSTOMERS.*, ORDERS.* 
    FROM CUSTOMERS LEFT JOIN ORDERS 
         ON CUSTOMERS.ID = ORDERS.CUSTOMERID
    WHERE CUSTOMERS.ID = @custID
    

    将这些数据存储在内存中可以创建客户及其订单,而无需两次访问数据库。

    不要担心连接,除非您已经关闭了池,如果您已经关闭了,您也不会问这个问题

    如果你想让事情变得更清楚一点,使用块是个好主意

    Using connection = new SqlConnection(ConnectionString)
    ' Insert code here 
    End Using
    
    连接将在最后使用进行处理,因为您处于默认行为,所以连接将返回到池中,以便在下次代码(实际上池是由appdomain完成的)需要时重用。如果在默认时间段(我似乎记得2分钟)内没有任何东西需要它,那么它将在该时间点完全释放

    PS对任何实现IDisposable的方法使用块是一个好主意,该方法是本地的

    每次点击服务器,都没有明确的答案。获取订单页面,然后从中创建订单对象集合将提高性能,只要您没有获得大量不太可能需要的东西。
    ie只获取显示所需的数据,如果有更多的负载,请使用某种延迟加载方案,在需要时获取数据,或者使用不同的类,例如OrderSummary、OrderDetail

    这段代码是返回JSON对象的可重用搜索web服务的一部分,因此我必须使用自定义类而不是
    DataTable
    ,并且不能使用
    ViewState
    @paperjam之类的东西。没问题。您可以更新标记和描述以获得更精确的答案…实际上,我是根据ASP.NET标记提出我的意见的。我正在尽量避免
    JOIN
    s,因为一些SQL可能使用
    执行表扫描,如“%input%”
    。请看我刚才添加到问题中的“背景”评论。认真考虑一下这种解决方案。信息技术它是在测试数据库或启动时非常有效的工具之一。当你最大的压力