Documente Academic
Documente Profesional
Documente Cultură
com
Taking it to .NET
In this issue:
Taking it to .NET: Introduce .NET applications with a custom splash screen VB Classic: Deftly decipher binary les, part 1: Data formats in a MIDI header Key binary terms every developer should know Avoid duplicate coding: Place common classes in a .NET class library Maximize performance by executing SQL stored procedures with a DataReader
We often refer to a splash screen as if its a special type of component. In actuality, its just a plain old form that you load before you load your primary form. In this article, well give you a few pointers on how to create and use a splash type form. First, well help you create a simple splash form. Then, well show you how to load it from another form in your project. Well also offer some tips to make your splash screen more dynamic and keep the information it contains up to date.
In Visual Basic 6, the Application Wizard can generate a splash screen for you, complete with all the proper labels for your application information. Of course, as you can see in Figure B on the next page, it isnt much to look at. Actually, you really dont need any help generating a splash screen. All you need are a few well-placed Label controls for the application information, maybe a PictureBox control for a company logo, and a Timer component to control the length of time the splash screen is visible.
to provide users with important version information and give your application a more rened feel.
common choices. Well leave it up to you to come up with a dazzling design. For our purposes, just add a single Label control to the new form and set its Name property to lblVersion. Then, add a Timer component to the forms system tray.
eight seconds has passed, the Timer Tick() event res. To stop the Timer and close the form, place the next set of code in the Timers Tick() event:
Timer1.Enabled = False Me.Close()
To launch a splash screen, you simply load it just as you would any other form. However, in .NET, loading a form isnt as simple as just coding splash.show. Instead, you have to create a new instance of the form and then show it, like so:
Dim objForm as new formname objForm.Show
In our example, we use the splash screen for informational purposes only. So, we load the main form and then display the splash screen over it. To use your splash screen in this manner, add the following code to the code window after the Windows generated code:
Private doSplash As Boolean = True Private Sub Form1_Activated(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Activated If doSplash Then doSplash = False Dim frmSplash As New Splash frmSplash.ShowDialog(Me) End If End Sub
The rst line of code in the forms Load() event tells the Timer to click for eight seconds. The next line sets the version, and the last line starts the Timer. Once
Figure B: Visual Basic 6 saves you a little time by offering a default splash form, but you could design something much better.
There are a few things wed like to point out about this code. First, instead of using just the Show() method, we use the ShowDialog() method to keep the main form off-limits while the splash form is visible. Also, since we used the CenterParent property value in the StartPosition of the Splash form, we pass a reference for the current form to the splash form to iden-
tify the current form as the parent. Finally, we used a Boolean variable to make sure the splash screen res only once. Note: If you do need a splash screen to ll time before your form loads, instead of using the forms Activated() event, add the code that creates and shows the form below the call to InitializeComponent() in the New() method. This loads the splash screen before loading the form. Also, be sure to use the plain Show() method and call Me.SendToBack() in the Activated event of the main form.
If you were to press [F5] and launch the program, youd probably see your bare-bones splash screen followed by the empty default form. However, if you recall, we hard-coded the version number in the splash form. In Visual Basic 6, you can keep your splash screen data fresh using the App class. In Visual Basic .NET, you have the Application class.
Figure D: Pass
the application information to the splash screen to keep it fresh and up to date.
shorten the amount of time the splash screen displays, use the setTimer variable to assign a smaller number of milliseconds to the Timer s Interval property.
Figure D shows our sample screen with the version number we obtained from .NET. If youd like to
In this article, weve shown you how easily you can create a splash screen for your .NET application. Although some users and developers frown on splash screens, theyre still an excellent way to introduce your application and keep the user aware of the current version and licensing information. Just keep the design simple and the display time short, and your splash screen is sure to make a great rst impression.
Meet people, get advice, find resources, share ideas, and make friends! You and your fellow EKJ Forum members create the contentreal, current, and always changing. Moderated by our expert editors, there are many different EKJ Forums to choose from. Check them out today!
January 2005
VB Classic
hen your program needs to read or manipulate les from another program, its nice if the les are in text or a standard data format. But sometimes your code will have to make sense of a binary le. For instance, if your software replaces or supplements a legacy program that uses a proprietary data format and has no adequate import/export capability or API, you may wonder how youre going to get the data. Some people just throw up their hands and re-enter records by hand. Of course, if the le in question is in a standardized binary format, such as MIDI for music or JPEG for graphics, APIs and ready-made COM objects often exist to interpret these les for you. But even then, you may want the exibility to alter the le in ways the makers of the ready-made solutions didnt anticipate. But, while its easy to obtain documentation on the basics of working with binary les, its harder to nd rich, real-world examples written in Visual Basic. So, well present a case study for you involving the simplied Musical Instrument Digital Interface (MIDI) processor shown in Figure A to give you a realistic overview of whats involved.
In this article, well focus on some key techniques for working with binary formats. The main commands well use are Open, Close, Get, and Seek. While youll see the syntax of these commands in action through some simple examples, well focus on the process of working with binary les. Well start with a comparison between the simple table-structure les you might nd under Help and the more complex binary les you may need to deal with on the job.
To give you the avor of real-life binary formats, we created a bare-bones utility that reads simple les in the MIDI format. While our utility, which you can obtain by downloading the le midi.zip from the URL listed at the beginning of the article, simplies things quite a bit (i.e., it assumes theres one track, no instructions on what instrument to use, no pedaling, and none of what the MIDI standard calls system exclusive messages), it does demonstrate basic techniques. For instance, well use our example to show how to work with various forms of data, such as bytes, unsigned integers, and signed integers. Well also show how handy the And operator is for working with binary data. Although well only be reading les, the concepts we cover will be crucial if you want to go to the next step and add data to a le, repair corrupted les, or change les in ways not possible through existing software. Note: This article contains many binary terms that, if youve never worked with binary les or havent worked with them since your teenage years, may seem unfamiliar. For this reason, weve provided a binary cheat sheet of sorts in the article Key binary terms every developer should know, which youll nd in this months issue.
The Visual Basic binary le examples youre liable to encounter generally make the assumption that the le is constructed of segments that share the same organization, much like rows (or records) in a database
table. For instance, a typical example may involve a le for storing sales items, containing a series of records that each store a sequence of elds, such as ID, item name, category number, and priceeach stored using a particular data type that Visual Basic supports (Integer, String, etc.). Given this scenario, you can create a user-dened type similar to the following:
Public Type SalesItems ID As Integer ItemName As String CatNumber As Integer Price As Currency End Type
A reasonable question is: Are the binary les you encounter in real life going to be like that? The answer is yes and no. Clearly, a table structure is an extraordinarily useful way of organizing binary les, and its a good place to start if you have to decipher an undocumented le format for storing tabular information. But it isnt the only possible approach. Binary les in real life may be more complicated. Often they have some sort of header identifying the le as a certain type, and they may have footer information. In addition, there may be a number of different suborganizations within the lesimilar to having many database tables instead of one. And since one of the
You can then dimension a variable of that type and an array to hold instances of that variable:
Dim StoreItems As SalesItems Dim arrayItems() As SalesItems Dim lCount As Long
Doing so enables you to read the data in chunks, one record at a time, into your array, like so:
Open c:\store.texmex For Binary _ Access Read As #1 While LOF(1) > Loc(1) ReDim Preserve arrayItems(lCount) Get #1, , StoreItems arrayItems(lCount) = StoreItems lCount = lCount + 1 Wend Close #1
Variable
*Technically, only the seven bits to the right of the rst bit form the signed integer for what MIDI calls SMPTE format (Society of Motion Picture and Television Engineers). But, if the leftmost bit is 1, taking the next seven bits as a signed integer is mathematically equivalent to taking all eight. Similarly, if the leftmost bit is 0, taking the entire two bytes is the same as taking only the rightmost 15 bits.
www.elementkjournals.com
January 2005
main uses for binary les is to store information compactly, there may be certain rules whereby a eld may be skippedsort of like a database table with a different number of lled columns in each row. Finally, the data may not correspond to any data types that Visual Basic provides. In which case, youd need to interpret the data yourself from the bytes, following the documentation you have for the le structure.
One of your rst tasks for interpreting data from a binary le is to set up any code youll need to call repeatedly, such as the SalesItems type we created in the previous example. However, in many cases, your setup activity will be quite a bit different. For example, consider the MIDI specication. MIDI les start with a header, which follows the format specied in Table A on the previous page. A few things stand out in the table. First, some of the information is in the format of unsigned integers, which dont correspond to any data type in Visual Basic. Second, if youre writing a program to read such a le, there are conditional decisions your code has to make to determine how to proceed.
The most basic task youll need to complete is grabbing a byte of data. This way, if you need data that doesnt correspond to any Visual Basic data type, you can always construct what you need from the bytes. Listing A shows a ready-made function that allows you to grab a byte from any position in a le. This function takes two arguments: intF is the le number you used in the Open statement to open the le. lPos (included for exibility in case you want to skip to a byte) is the byte in the le to start at (e.g., 1 if youre reading the le from the beginning, 9 if youve read 8 bytes so far and want to read the next one). TakeAByte() uses the Seek() function to nd what the next byte is if you havent specied lPos.
Taking a byte
Next, well look at the concept of an unsigned integer. The distinction between signed and unsigned may not make a difference for the small numbers youll usually encounter in MIDI headers, but the concept is fundamentaland its something youll need to know to deal with the rest of a MIDI le or to work with other binary formats. Visual Basics Integer and Long types represent signed integers; that is, they can be positive or negative. To represent both positive and negative numbers, computers generally use the twos complement system, meaning simply that you count the largest bit negatively. For instance, consider a typical 16-bit signed integer. (Well consider a generic case, not a Visual Basic Integer , since theres a slight complication, which youll see soon.) The rightmost, or 0 th bit, represents 1 if in the on position. Any other bit n in the on position represents 2 n, with the exception of the leftmost (15th) bit, which represents not 2 15, but -2 15. So, 1,000,000,000,000,011 represents -32,765 (i.e., -32,768 + 2 + 1). In contrast, in a 16-bit unsigned integer, the leftmost bit represents 2 15meaning that 1,000,000,000,000,011 represents 32,771 (i.e., 32,768 + 2 + 1). The idea of inverting the largest bit (also known as the most significant bit, or MSB) to represent signed integers is a great way to simplify the algorithm the computer uses to add numbers. Unfortunately, it can pose problems if your file format specifies unsigned integers and youre trying to interpret these with signed data types. There are three valid strategies for dealing with unsigned integers in Visual Basic: Use deduction to determine that the data will look the same whether you interpret as signed or unsigned. Loop through the bytes to generate the number. Mathematically convert from a signed integer.
As As As As As
There are three big problems with this, however: If a le violates your assumptions, you may end up with a bug at the most inconvenient moment. Visual Basics Long and Integer types store their bytes with the MSB on the right (i.e., the bytes for an Integer 1 are 10, not 01); whereas, in MIDI, its on the leftanother complication. In our experience, reading and writing with a userdened type all at once wont give you the bytes in the order you expect. Reading les with individual variables (or individual members of a Type) gives you more control and predictability.
This function takes three arguments, including two similar to our TakeAByte() function, and an argument called intLen containing the number of bytes for representing the number. To understand how this function works, remember that each next byte (counting back from the right) represents eight places (bits) over from the last byte, so the value of each next bytes bits is 28 (i.e., 256) times the bits of the previous byte. Of course, since we get the data from left to right, we start with the highest numbers rst. We know the number of bytes from intLen, so we can simply populate the variable lCount to represent the appropriate exponent of 256, and loop back using Step - 1. Certainly, this simplied example is far from perfect because were still using Long, so we really only get the data for 3 7 8 bytes. A 4-byte unsigned integer can be as large as 4,294,967,295; whereas, ours can only be 2,147,483,647. To get around that, you may need to store the results as Currencyor as arrays of bytes, using your own algorithms for any calculations you need to do.
www.elementkjournals.com
January 2005
One important technique in Listings C and D is the use of the And operator. If the variables x and y represent numbers, then the expression (x And y) returns the number youd form by taking all the bits that are the same in both x and y. This means that if you want to know if a number contains a certain bit (i.e., power of 2), you can use And , as shown in the listings. Another use of And is to extract data from a larger chunk that youve already collected. For example, consider the second to last row of Table A, which specifies what the MIDI standard calls the Division. Suppose youve extracted that information either by using the Integer data type and converting to unsigned using our IntToUnsignedLong(), or by calling our ReadFixdLenPosNum() function. In either case, you have more work to do, because the standard says youre supposed to
Using And to compare bytes and extract data from larger chunks
read the leftmost bit and then interpret the rest of the data accordingly. Listing E demonstrates one way to do this. Simply feed your MIDI header values into an object youve dened with a class module, and use a Property Let to perform any remaining calculations. In our Property Let, we store the raw value to a module-level variable for future reference. Then we compare the value with 215 to see what the rst bit is. If the leftmost bit is 1, we set a property in the class to signal that the data is stored using the second of the two possibilities shown in Table A for Division. You can see from the table that the leftmost byte is supposed to be a signed integer and the rightmost an unsigned integer. Now heres the clincher: To get the rightmost (i.e., lowest value) byte, we simply take (lVal And 255). The 255 value is the sum of the bits in a byte (mathematically, 20 + 21 + 22 + +2n-1 = 2n - 1). So that gets us our second byte. We subtract to get the rst byte, which we convert back to twos complement notation. (We cant use CInt() to do that because were working with numbers in Visual Basic, not with memory directly.) Of course, we could probably make this more elegant so we arent converting to an unsigned integer and then back to a signed one, but the process here is more useful for demonstration purposes. (In most MIDI les, the leftmost bit is 0 anyway.) Warning: When you use And and other similar operators to compare or manipulate bits, make sure your expression results in the correct data type and has parentheses as needed. Consider the following incorrect versions of the If statement from Listing C:
If intSigned And 32768 Then If intSigned And 32768 > 0 Then
The rst always acts as if the expression is False, because the expression returns a number instead of a Boolean. Visual Basic reads the second as if it said this:
If intSigned And (32768 > 0) Then
While weve only begun the journey of reading a MIDI le, weve highlighted much of the conceptual territory youll need to work with binary les. No doubt, some les you work with will have more complex or unique ways of representing data. However, once youre able to extract bytes, write functions to interpret data from a le, and use math to convert data in any way you need, youll have little problem reading or editing just about any binary format.
ts no secret that applications often need to share functionality. For example, you might build a web page and a Windows application that both need to access the same database component to retrieve a product catalog. In the world of .NET, you solve this problem by building a shared class library. The class library, when built, becomes a separate DLL le that any other .NET application can use, regardless of its language. Best of all, there are absolutely no versioning or conguration headaches, thanks to .NETs newfound love of metadata.
www.elementkjournals.com
January 2005
In this article, youll see how you can use Visual Studio .NET to quickly build your own class library. Youll learn the rules you need to follow to build and deploy class libraries to the clients that use them. Best of all, youll nd that all of these steps are much simpler than they were with traditional Visual Basic 6 and COM programming.
A class act
Technically, a .NET class library, or component, is nothing more than a collection of one or more classes compiled together as a unit. For example, when you install .NET, you install just over a dozen Microsoft-authored assemblies that provide all the tools youll use for building Windows applications, web applications, connecting to a database, reading les, and so on. The most important thing to understand about a class library is that a user cant directly launch it. Instead, a class library groups together some related features that another .NET application uses. Class libraries have many benets. Most importantly, they allow you to create pluggable applications, where you can debug, enhance, replace, and modify components individually without having to rebuild the entire application. Theyre also a great way to reuse code in different applications.
To create a new class library project in Visual Studio .NET, follow these steps: 1. Select File | New | Project from the menu, if you arent already at the New Project dialog box. 2. Under the Visual Basic group, choose Class Library. 3. Choose your directory and project name (just as you would with any other project), and click OK. By default, youll start off with one class file, although you can add as many classes or modules as you want. Inside your class library, you can put the same code you would use in a Windows or web application. The difference is that you wont interact with user interface at all. Instead, youll write functions that read les, retrieve data from databases, perform calculations that are specic to your business, and so on.
10
The next line of code shows how the client might call this method. Notice that you use the name of the class, rather than creating a new object:
AccountUtility.Deposit(342-42, 34.99)
2. Right-click on References in the Solution Explorer, and choose Add Reference. Then, click the .NET tab. Dont bother searching through the list provided for you; it corresponds to all the assemblies in the GAC (Global Assembly Cache), not the private assemblies designed for internal use. 3. To add your reference, click the Browse button at the .NET tab, and hunt for the DLL le from your class library project. 4. Once youve chosen the right le, click OK to continue. Visual Studio .NET copies the DLL le to the bin directory of the current project. This is an important fact to remember, because any new changes in your class library project wont be available in your client project until you copy the newly compiled DLL le and overwrite the previous copy in the client project. Visual Studio .NET takes this step automatically if the assembly at the source location has been modied. Note: As a shortcut, add both the class library and the client project to the same solution. Then, when you add the reference, choose the Projects tab, and pick the class library project name from the list. This way, Visual Studio .NET ensures that the client always gets the most recent version of the class library every time you build the solution.
To understand class libraries, it helps to consider a simple component. Listing A shows portions of a sample class that consists of two instance methods. These methods allow you to encrypt data and store it in a le, or decrypt data and retrieve it from the le. Note: For a complete listing of our test program, navigate to the URL listed at the beginning of the article and download classlibrary.zip. This component is useful, because it combines two tasks: cryptography and le I/O. (In a full-edged application, you might take even more steps, such as validating the data.) Note that when you create an instance of the FileEncryptor class, you need to supply the password you want to use. If you dont use the same password to read data as you used to write it, youll receive scrambled information. This makes the FileEncryptor class a handy way to keep information safe from prying eyes! Once youve perfected your class library, you can build it. (Just right-click on your project in the Solution Explorer and choose Build.) Visual Studio .NET will compile all your code into a single DLL assembly le. However, before you can actually test this class library component, youll need to build an executable application, as we describe in the next section.
The classes dened in your class library project are now automatically available in your current project, just as though you had dened them in that project. The only difference is that you need to use the namespace of your project library to access its classes. Heres what you need to access the EncryptLibrary class library:
Imports EncryptLibrary
Any .NET application can use your class library, even if its written in another language. (This makes perfect sense, of course, as all the .NET libraries are written in C#, and theyre easily usable in Visual Basic .NET programs.) To create a client for your class library, follow these steps: 1. Open an existing project or create a new Windows Application.
Now, its easy to respond to a button click and encrypt some text to a le. Just take a look at the following code to encrypt some text:
Private Sub cmdEncrypt_Click( _ sender As Object, e As EventArgs) _ Handles cmdEncrypt.Click Dim Encryptor As New _ FileEncryptor(txtPassword.Text) Encryptor.EncryptFile( _ encrypt.bin, txtText.Text) End Sub
www.elementkjournals.com
January 2005
11
Decrypting text is just as easy. The code in Listing B simply displays the decrypted text in a message box. You can play with this example to get a better understanding of how class libraries work. Clearly, you could have added the encryption code directly to the client, but this separation gives much more exibility for dividing the problem (and reusing your hard work).
become easier as Microsoft streamlines the upgrade process and probably starts sneaking the .NET les into such applications as Microsoft Internet Explorer and Windows operating system upgrades.
When you decide to deploy your new client project, youll notice how dramatic the differences are between COM and .NET. In COM development, you would need to rst copy the custom component to the Windows system directory on the new computer, register it, and then use the client program.
Most programmers are familiar with a programming problem affectionately known as DLL Hell. This problem is experienced most acutely when you install a new software product that updates a shared component used by other applications with an incompatible version. The end result is that a seemingly innocent taskupdating a system componentbackres miserably, rendering one or more applications unusable.
No registration required
In .NET development, no registration is required. You can copy the class library DLL and client EXE les to any directory on the new computer, and theyll work automatically. The EXE le has all the information that .NET needs about dependencies. It will automatically locate the class library DLL, as long as its present in the same directory. (In fact, you can even replace the class library with a new version, and it will work seamlessly, provided you dont change the name of the methods youre using, or the number or type of parameters each method uses.)
Got .NET?
Any client that you want to share your class library with must have .NET installed. To complete this step, just use the Windows Update feature by following these steps: 1. Go to the Windows Update website. You can select Windows Update from the Start menu, or just point your browser to http: //windowsupdate.microsoft.com. 2. Scan for updates. 3. Select .NET Framework Version. 4. Install it.
12
.NETs DLL hell, which shows you how to place the FileEncryptor class library in the GAC.
In this article, weve shown you how to take advantage of .NETs class library feature to catalog your reusable classes. When you use class libraries, you avoid duplicate coding and can take advantage of other .NET features, such as the GAC, which allow you to store all your classes in a nice and orderly fashion.
Matthew MacDonald is an author, educator, and MCSD developer with a passion for emerging technologies. Hes a contributor to several books about .NET, including titles at OReilly and Apress. Email him at matthew@prosetech.com, or browse his website at www.prosetech.com. In addition, check out The Book of VB .NET from No Starch Press, which demysties .NET development for VB programmers.
QL stored procedures have been around for quite some time. Developers routinely use them to retrieve data from a SQL database more securely and efciently. If youre using SQL stored procedures for the performance boost, then you should be mindful that you can lose part of those gains by choosing the wrong method to execute the stored procedure and retrieve the data in .NET. In most cases, an ADO.NET DataReader works just ne for these tasks and it carries less baggage than a DataSet, giving you a little extra performance boost. (Were using the generic ADO.NET terms here. Keep in mind that in code, youll precede these terms with a specic provider, like SQLDataReader.)
Both the DataReader and the DataSet are excellent tools for retrieving data from a stored procedure. However, if you only need to retrieve small amounts of data for the purpose of displaying it, all the overhead of the DataSet to support two-way communication between the database and your .NET program is unnecessary. With the .NET DataReader, you can retrieve a readonly, forward-only stream of data from a stored procedure and dump it out one row at a time, as weve done in Figure A. In this article, well provide a couple of examples on how to retrieve data from a SQL stored procedure using a SQLDataReader. First, well show you how to execute a parameterized stored procedure and return the data shown in Figure A. Then, well go a step further and use a DataReader to retrieve multiple result sets from a stored procedure.
However, this is where the similarities stop. For the DataReader, you dont need to pass the command to a DataAdapter or call the Fill() method to populate a DataSet. You just need to call the ExecuteReader command. The following lines of code illustrate the process:
Dim cn As SqlConnection =New SqlConnection( _ connection info) Dim myCMD As SqlCommand = _
A DataReader primer
The rst few steps for creating a SQLDataReader are exactly the same as those youll take to create a Data-
www.elementkjournals.com
January 2005
13
New SqlCommand(sql query, cn) myCMD.CommandType =CommandType.Text Dim myReader As SqlDataReader = _ myCMD.ExecuteReader()
nal syntax we provided. First, youll replace the sql query in the Command with a stored procedure name. Then, youll change the CommandType to StoredProcedure, and nally to access the parameter youll create a Parameter object and supply the name of the parameter and its SQL data type, as the following code snippit illustrates:
Dim myCMD As SqlCommand =New SqlCommand( _ storedprocedurename, cn) myCMD.CommandType = CommandType.StoredProcedure Dim param As SqlParameter =myCMD.Parameters.Add( _ parametername, parametertype) param.Direction = ParameterDirection.Input
The DataReader returns False when there are no rows left to retrieve. To obtain the column information, call the DataReaders GetSring() or GetValue() methods inside the loop with a column index value, like so:
myReader.GetString(0)
Youll use the SqlDbType enumeration to select a valid parameter type. Also, set the Direction property to Input to show data going into the stored procedure.
As you know, a parameterized stored procedure requires additional input before it can execute properly. Consider the following stored procedure against the SQL Server Northwind database:
Create procedure dbo.[n Most Expensive Products] @GetRowCount int AS SET ROWCOUNT @GetRowCount SELECT Products.ProductName AS nMostExpensiveProducts, Products.UnitPrice FROM Products ORDER BY Products.UnitPrice DESC GO
The name of this stored procedure is n Most Expensive Products. It retrieves the most expensive items from the Northwind products database. The parameter @GetRowCount controls how many records the query retrieves.
Weve just shown you a parameterized stored procedure and earlier we showed you how to load a DataReader using one. In Listing A, we put the two pieces together inside a Buttons Click() event to produce the debug data shown in Figure A. (If testing this code, be sure to create the stored procedure in SQL Server, add a TextBox control to the form, and import System.Data.SQLClient in your .NET code.)
Oftentimes, it may be necessary to return multiple result sets in a single stored procedure. For example, the stored procedure in Listing B named Ten Best and
14
Worst returns the top 10 best-selling items and the top 10 worst selling items for the Northwind OrderDetails table. Youre sure to see a performance difference between the DataSet and the DataReader in procedures like this one. The DataAdapter would create two DataTables and return both result sets at once. However, the DataReader allows you to retrieve the result sets one at a time using the NextResult() method, like so:
myReader.NextResult()
Windows Application and add two ListView controls and a Button control to the default form. Next, right-click on the form and select View Code from the shortcut menu. Add the following line to the top of the code window:
Imports System.Data.SqlClient
Then, copy the code from Listing C into your Button1_Click() event subroutine. Be sure to adjust the connection information to reect valid ones on your system. Note: At any time, you may navigate to the URL listed at the top of this article and download the sample code in the le datareader.zip.
Back Issues
To order a back issue, call Customer Relations at (800) 223-8720. You can pay with MasterCard, VISA, Discover, or American Express.
Editorial
Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sheila M. Davis
Customer Relations
U.S. toll-free . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Canada toll-free . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Outside the U.S. and Canada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Customer Relations fax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (800) 223-8720 (877) 203-5248 (585) 240-7301 (585) 292-4392
For subscriptions, fulllment questions, and requests for group subscriptions, address your letters to Element K Journals Customer Relations 500 Canal View Blvd. Rochester, NY 14623 Or contact Customer Relations via our website at www.elementkjournals.com/contact.asp.
Managing Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mike D. Jones Copy Editors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Christine Hunt Carrie Weih Contributing Editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Matthew MacDonald Jonathan Rabson Graphic Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Amy Palermo
Copyright
2005 Element K Journals, a division of Element K Press LLC (Element K). Element K and the Element K logo are trademarks of Element K LLC. This work is an independently produced publication of Element K Journals, the content of which is the property of Element K or its afliates or third-party licensors and which is protected by copyright law in the U.S. and elsewhere. The right to copy and publish the Content is reserved, even for Content made available for free such as sample articles, tips, and graphics, none of which may be copied in whole or in part or further distributed in any form or medium without the express written permission of Element K. Questions or requests for permission to copy or republish any content may be directed to contentreuse@elementk.com. Visual Basic is a trademark of Microsoft Corporation. IBM is a registered trademark of IBM Corporation. Windows is a registered trademark of Microsoft Corporation. All other product names or services identied throughout this journal are trademarks or registered trademarks of their respective companies. Printed in the U.S.A.
You may address tips, special requests and other correspondence to The Editor, Inside Microsoft Visual Basic Element K Journals 500 Canal View Blvd. Rochester, NY 14623 Editorial Department fax. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (585) 292-4391 Or contact us via internet email at ivb_editor@elementk.com. Sorry, but due to the volume of mail we receive, we cant always promise a reply, although we do read every letter.
Element K Journals
Publisher. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Doreen Bieryla Associate Publisher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Michelle Rogers Manager of Customer Relations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nicole Pate Manager, Journals Production . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Danielle Rumsey Graphic Design Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chuck Willey Director of Marketing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lynne Dundas Product Marketing Manager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sean McPartland
Price
Domestic. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . $147/yr. Outside the U.S.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . $157/yr. Our Canadian GST # is 88903 7958 RT0001. CPM # is 40031405. Our QST # is 1018491237.
Postmaster
Postmaster: Send address changes to Inside Microsoft Visual Basic P.O. Box 92880 Rochester, NY 14692
www.elementkjournals.com
January 2005
15
Coming up:
Exploring COM+ with Visual Basic 6 More on working with stored procedures in .NET
2035
This code is pretty much the same as the previous code to load a DataReader, except theres no parameter in this version and we use the NextResult() method to obtain the second result set.
the column headings for the list views, we use the GetName() method of the DataReader. Add this code to your code window after the Button Click() event.
After youve added the stored procedure to your SQL Server database and added all the code, press [F5] to build and run the application. When you click the button, .NET executes the stored procedure, retrieves the data from each result set and loads the two ListView control. If all goes well, your form should resemble the one shown in Figure B.
In this article, weve shown you how to obtain data from a SQL Server stored procedure using a DataReader. In general, stored procedures are designed to be more efcient than outside queries. The DataReader can also increase an applications performance because it returns the data one row at a time rather than big globs like the DataSet. Pairing these two structures together create a perfect performance match.
Figure B: With the DataReader, you retrieve data from multiple result sets one at a time.
16