Usage of query in other procedures (public scope)

gs99

Active member
Joined
May 8, 2010
Messages
42
Programming Experience
Beginner
Using Express VB 2010 and SQL 2008.

When a query is made, how can the results be made available to other procedures?
For example, in Module:
VB.NET:
Sub makeQuery()
    dim myQuery ...
End sub

Sub useQuery()
    for each p in myQuery ...
End sub
 
outside of makeQuery
Two reasons: How do I execute myQuery if it’s not within a sub? Also, if the Dim myQuery is within a sub, it’s recognized as System.Linq.IQueryable(Of <anonymous type>); elsewhere it’s only Object.

I’ve tried the following:

VB.NET:
Module Module1
Public myQuery = Nothing

Sub MakeQuery()
	myQuery = From p in db.Persons…

Sub UseQuery()
	For each pq in MyQuery…
Everything seems to work OK. However, myQuery is recognized only as Object.
The new extension methods such as Count are not available.

This is what prompted my post: If .Count is not available, how do I determine if the query returned no items?
 
I think you need to read some MSDN about scope in .Net, like this: Variable and Method Scope in Microsoft .NET

To go back to your example, you would write:

Private myQuery As System.Linq.IQueryable(Of <Insert your datatype used here (likely String)>)

Sub MakeQuery()
    myQuery = From p in db.Persons ...
    ...
End Sub

Sub UseQuery()
    For Each pq In MyQuery ...
    ...
End Sub


The only time you should use Public is if you need to make the variable or procedure available outside your own program, as you would in a library for example. Otherwise try to stick to Private and Friend.
 
@Herman

this is accepted:
VB.NET:
Private myQuery As System.Linq.IQueryable
but the Count method is still not available.

this causes drastic complaints - the whole module is invalid:
VB.NET:
Private myQuery As System.Linq.IQueryable(Of <String>)

@JohnH
I tried Selecting to New Output With ...
I was hopeful with this because it sounded like a new object would be created.
But I could not do anything with Output. It's only a Data Type, not an object.
Is there a way to make it an object?

It's obvious that I haven't read all the manuals, but I'm happy to see effective results with Linq to SQL.
I'm developing my first SQL application.

Do you know of another way to get count of a Linq query?
 
Last edited:
When you use the New keyword new objects are created, the difference is "New With" compiler creates and infers an anonymous type and "New <your type> With" creates an object of <your type>. The latter is the named type that you have to define first. The With part is used to set properties of the object.
 
So then, with this code:
VB.NET:
Public Class ParentData1
    Property firstName As String
    Property personIDChild As Integer
    Property personIDDad As Integer
    Property personIDMom As Integer
    Property mateID As Integer
End Class

Sub MakeQuery()
    ...
    Select New ParentData1 With {.firstName = p.firstName, .personIDChild = parents.personIDChild, _
                    .personIDDad = parents.personIDDad, .personIDMom = parents.personIDMom, _
                    .mateID = m.mateID}

What is the object that is created?
 
gs99 said:
Select New ParentData1 ...
What is the object that is created?
A new ParentData1 object is created for each match in query.
gs99 said:
if the Dim myQuery is within a sub, it’s recognized as System.Linq.IQueryable(Of <anonymous type>)
So what is it now when you're not using anonymous type?
 
A new ParentData1 object is created for each match in query.
I don’t understand where the objects are stored for later access.
For comparison, this is a way to instantiate objects for class Person1.
VB.NET:
Public Class person1
    Property firstName As String
    Property lastName As String
End Class

Module Module2
    Dim person1Col As New Collection

    Sub MakeObjects(ByVal _firstName As String, ByVal _lastName As String)
        Dim person1 As New Person1 With {.firstName = _firstName, .lastName = _lastName}
        person1Col.Add(person1)
    End Sub
The objects are stored in person1Col.
In the Linq query, what is the object container?
 
That article describes the difference between Immediate and Deferred execution (see below).
It does not address named types; it does not answer the immediate question.
You stated: “A new ParentData1 object is created for each match in query.”
I replied: “I don’t understand where the objects are created.
In the Linq query, what is the object container?”

The article says in part:
Query execution is separate from creating a query. After a query is created, its execution is triggered by a separate mechanism. A query can be executed as soon as it is defined (immediate execution), or the definition can be stored and the query can be executed later (deferred execution).

By default, when you create a query, the query itself does not execute immediately. Instead, the query definition is stored in the variable that is used to reference the query result. When the query result variable is accessed later in code, such as in a For…Next loop, the query is executed. This process is referred to as deferred execution.
Introduction to LINQ in Visual Basic
Another site explains the basic parts of a Linq query.
Writing Your First LINQ Query (Visual Basic)

VB.NET:
' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}

' Query creation.
Dim evensQuery = From num In numbers
                 Where num Mod 2 = 0
                 Select num

' Query execution.
For Each number In evensQuery
    Console.Write(number & " ")
Next
My first issue with the article is “the query can be executed later”.
What does “later” mean? My interpretation is: in another Sub that’s called later.
That’s what my main question relates to: “how can the results be made available to other procedures?”
For this to happen, the Dim must be module-wide, correct?
VB.NET:
Module
Dim Query1 = Nothing

Sub MakeQuery()
 Query1 = From num In numbers ‘query is modified here
…

Sub UseQuery()
 For each p in Query1…
The availability of Query1 “later” is not affected by “anonymous” or “named” type options.

The second issue is “the query itself does not execute immediately”.
This is saying the query itself does not generate objects.
Only when the query is executed (e.g. in a For Each loop) is the query executed.
Contrary to your statement “A new ParentData1 object is created for each match in query.”
I don’t see objects created unless my explicit code does it.

As a novice, I see these steps to create objects from a Linq to SQL query:

VB.NET:
Public Class Person1
    Property firstName As String
    Property lastName As String
End Class

Module Module2
    Dim db As New MyFamilyDataContext
    Dim person1Col As New Collection

    Sub dbGetData3()
        'SQL table Person2
        Dim Query3 = From p In db.Person2s
         Select p.firstName, p.lastName 'anonymous type

        Dim cnt = Query3.Count 'Query is declared locally; .Count is available

        For Each p In Query3
            MakeObject(p.firstName, p.lastName) 'Makes instance of class Person1
        Next
    End Sub

Sub MakeObject(ByVal firstName As String, ByVal lastName As String)
    Dim person1 As New Person1 With {.firstName = firstName, .lastName = lastName}
        person1Col.Add(person1)
    End Sub
The person1Col collection is available for later queries.
The “extra” code is class Person1, not needed otherwise.
This code seems to work and answers my original question.
If there is an easier or better way to do this with “named types” that I fail to understand, please let me know.
 
Contrary to your statement “A new ParentData1 object is created for each match in query.”
Well, how can there be a match in query if you don't execute the query? There may not be a match, but if there is the query states that instances is created when you use the New keyword.
What does “later” mean?
Writing Linq queries is not any different that writing a SQL statement, for example "SELECT firstName FROM Person", writing this query (a plain string) will not connect to database and execute the command, only when you do that is the query executed and database can return result set. The article link explains when Linq query is executed.
The availability of Query1 “later” is not affected by “anonymous” or “named” type options.
Yes it is, because you can't declare the variable type if the result is an anonymous type, you can only use Object type and that is not something you can work with later.
If there is an easier or better way to do this with “named types” that I fail to understand, please let me know.
Yes, you can use a Linq query with a named type, like you posted before:
result = From p In db.Person2s Select New Person With {.firstName = p.firstName}

result type is IQueryable(Of Person) as I can infer from you posts, and Person instances are created each time you execute the query.
If you want to execute the query right away, or perhaps avoid executing the query multiple times, you can execute and convert result set to a list or array using ToList or ToArray for example, this was also explained in article.
list = result.ToList()

list would then be type List(of Person)
 
I would like to address only one point in this post, relating to the “later” question.

The article explained three main parts:
VB.NET:
' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}

' Query creation.
Dim evensQuery = From num In numbers
                 Where num Mod 2 = 0
                 Select num

' Query execution.
For Each number In evensQuery
    Console.Write(number & " ")
Next
I thought when it said “later”, the Query deferred execution could reside in a separate Sub procedure, called as needed. But for this to occur, the Query must have Module scope. And in that sense, the “anonymous” or “named” type options within the Query definition do not matter. That’s what I meant in:
The availability of Query1 “later” is not affected by “anonymous” or “named” type options.

Should the Query creation and Query execution always occur in the same procedure?
The example doesn’t provide that detail:

VB.NET:
Dim numberArray() = {0, 1, 2, 3, 4, 5, 6}

Dim evensQuery2 = From num In numberArray
                  Where num Mod 2 = 0
                  Select num

+++++++++++++++++++++++++++++++++++++++++ Execution #1 (++++ lines added by me)
Console.WriteLine("Evens in original array:")
For Each number In evensQuery2
    Console.Write("  " & number)
Next
Console.WriteLine()

+++++++++++++++++++++++++++++++++++++++++ Change data 
' Change a few array elements.
numberArray(1) = 10
numberArray(4) = 22
numberArray(6) = 8

+++++++++++++++++++++++++++++++++++++++++ Execution #2
' Run the same query again.
Console.WriteLine(vbCrLf & "Evens in changed array:")
For Each number In evensQuery2
    Console.Write("  " & number)
Next
Console.WriteLine()
In a business application, the “Change data” step details are certainly not known in advance.

Could the Query creation and Query execution (in same sub) be called each time data is changed?
Altho the creation step is needed only once, repeating it doesn’t hurt, correct?

Therefore, “later” execution does not require separate Sub procedures.
Obviously I’m working with very simple examples.
 
Back
Top