I’m implementing a poor-man’s ORM an a legacy application (.NET 2.0 web app, hand-coded SQL queries). I have two data classes: Customer and 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
I’m using a SqlDataReader to manually map the SQL results to an instance of the Customer class:
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()
To populate the Customer.Orders, I call a function that returns a List(Of Order):
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
I’m concerned about the performance of this method, namely if I’m pulling multiple Customer‘s. For each Customer pulled, I have to hit the database again (opening another connection), and getting the orders for that given customer. If I’m not mistaking, it wouldn’t take many records to accumulate a large number of open connections.
My question is two-fold:
- How can I determine the number of new connections being made and whether or not I’ll encounter any connection pooling or other such .NET-imposed limits?
- Is there a better way? (see comment below)
One thought I’ve had is to pass the SQLConnection object created in the calling class to the getOrdersByCustomerId function and have that function use the (apparently?) already-open connection. I have not tested it namely because I don’t know how to determine if it’s better than my existing method. Thoughts?
Background:
I’m creating a search web service that returns JSON for processing by the client. The service takes a single search parameter, performs multiple lookups on different tables, then returns a custom JSON object. For example, if the user puts in what appears to be a name, I search both the Customers table for a list of the top n customers and the Orders table for the top n orders that have a customer with that name.
Opening and reopening a connection is virtually free. Thus it’s good practice to open a connection and dispose it ASAP, preferably in a using block.
You can test for connection leaks by adding
Max Pool Size=1;to your connection string. That will limit the number of available connections to 1. You’ll get an error if you leak a connection. Be sure not to use this setting in production.For performance, you’d normally avoid hitting the database for every row in a large set. So you could write a new query or procedure that returns all orders for all relevant customers. However in practice that’s an unusual query. You’d normally present a list of customers and only when the end user zooms in on that customer would you retrieve the list of orders.