1. Trang chủ
  2. » Công Nghệ Thông Tin

Mastering Microsoft Visual Basic 2010 phần 10 pdf

112 880 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 112
Dung lượng 907,52 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The clients of the service will communicate with our class by submit- ting objects from the Product and Product.Category classes, and the service will return data to the client applicati

Trang 1

of the service’s methods; instead of using the collections as its data source, the service will

contact a database In between sessions, you can persist the collections to an XML file, as cussed in Chapter 13, ‘‘XML in Modern Programming.’’

dis-Start a fresh instance of Visual Studio and select File New  New Project Click WCF inthe Installed Templates pane, and in the pane with the matching project types, select WCF Ser-

vice Library Name the new project WCFProducts and click OK to create the project The new

project that Visual Studio will create for you contains two files: the IService1.vb class, which

is an interface that contains the signatures of the service methods, and the Service1.vb class,which contains the implementation of the methods The methods are some extremely trivial

sample methods and you can delete them right away

The first step is the design of a class that represents the entities our service knows about

Obviously, we need a Product and a Category class and I have nested the Category class withinthe Product class Both classes contain just a few properties to identify products and categories.Add the Product class to the WCF project and insert in it the code of Listing 21.4

Listing 21.4: The Product.vb class

<DataContract()>

Public Class Product

<DataMember()> Public ProductID As Integer

<DataMember()> Public ProductName As String

<DataMember()> Public ProductPrice As Decimal

<DataMember()> Public ProductCategoryID As Integer

Public Overrides Function ToString() As String

Return ProductName & " (" & ProductID & ")"

End Function

<DataContract()> Public Class Category

<DataMember()> Public CategoryID As Integer

<DataMember()> Public CategoryName As String

Public Overrides Function ToString() As String

Return CategoryName & " (" & CategoryID.ToString & ")"

End Function

End Class

End Class

This is a very simple class that describes products and categories, if you ignore the

deco-rations of the various members The entire class is marked with the DataContract attribute,

which tells the compiler that the following class contains the service’s contract: the entities ourservice knows about The clients of the service will communicate with our class by submit-

ting objects from the Product and Product.Category classes, and the service will return data

to the client application using instances of these two classes The DataMember attribute tells

the compiler that the corresponding property is a member of the contract and that it should beexposed to the clients If you have properties that you want to use in your code but not expose

to clients, just don’t mark them with the DataMember attribute

Trang 2

The next step is the definition of the methods that the clients will use to contact our vice The methods must be defined in an interface class, which contains the method definitionsbut not their actual implementation This interface class contains the service’s metadata — theinformation required by a client to figure out the service’s capabilities Add the IProduct class

ser-to the project and insert the statements shown in Listing 21.5 in it (the IProduct.vb file)

Listing 21.5: Describing the Product class with an interface

This is another trivial class, except that it’s marked with the ServiceContract attribute,which tells the compiler that the class contains the service’s operations (as opposed to the ser-vice’s data structure, which was defined in the Product class) The methods are also markedwith the OperationContract attribute, which makes them available to clients Without thisattribute, the procedures would be internal methods and clients wouldn’t be able to see them

If the service exchanges simple data types with the client, this interface would be adequate.However, practical services are not limited to simple data types like integers and strings Theycommunicate with the client using business objects, which are based on custom classes Theseobjects represent customers, products, invoices, and the like If you want to make use of customobjects, you must declare them in a separate class like the Product class shown earlier

Finally, you must add yet another class to the project — this time a class that contains theactual code and implements the service This is the ProductService class in the sample project,and its code is shown in Listing 21.6 The ProductService class implements the IProduct inter-face, taking into consideration the classes defined in the Product class

Listing 21.6: The implementation of the ProductService class

<ServiceBehavior()> Public Class ProductService :

Implements IProductShared _products As New List(Of Product)

Shared _categories As New List(Of Product.Category)

Trang 3

Public Function AddProduct(ByVal prod As Product) As Product

Implements IProduct.AddProduct

‘ grab the next ID in _products list

prod.ProductID =

(From p In _productsSelect p.ProductIDOrder By ProductID Descending)

End Function

Public Function GetAllProducts() As

System.Collections.Generic.List(Of Product)Implements IProduct.GetAllProducts

Return _products

End Function

Public Function RemoveProduct(ByVal ID As Integer)

As Boolean Implements IProduct.RemoveProductproducts.Remove(_products.Find(Function(p) p.ProductID = ID))

End Function

Protected Overrides Sub Finalize()

MyBase.Finalize()

End Sub

Public Function GetCategoryProduct(

ByVal categoryID As Integer)

As List(Of Product)Implements IProduct.GetCategoryProductsReturn (From p In _products

Where p.ProductCategoryID = categoryID).ToList

End Function

Public Sub New()

Trang 4

_categories.Add(New Product.Category With{.CategoryID = 101, CategoryName = "Electronics"})_categories.Add(New Product.Category With

{.CategoryID = 102, CategoryName = "Cameras"})_categories.Add(New Product.Category With

{.CategoryID = 103, CategoryName = "Software"})End Sub

End Class

The data are stored in the _products and _categories collections, which are private to the

class, and no client can manipulate these collections directly This is the essence of the service:

It allows clients to view and manipulate the data through a well-defined interface, and the vice itself is in charge of maintaining the integrity of the data Since we don’t have a database

ser-at the back end, we’re also responsible for maintaining the IDs of the various entities Every

time a new product is added, the code retrieves the largest product ID from the _products

collection, adds 1 to it, and forms the ID of the new product The same is true for the IDs ofthe categories Notice also that every time the service is initialized, it adds three rows to the

_categories table It goes without saying that you can change the implementation of the vice so that it interacts directly with the Northwind database instead of custom collections To

ser-do so, you will change the implementation of the ProductService class without having to touchthe other two classes As a consequence, client applications will continue using your service,but with the new implementation of the service, they will be seeing the data of the Northwinddatabase

The two collections must be declared with the Shared keyword so that all instances of theservice will see the same data Had we declared the two collections with a Dim statement, anew set of collections would be created for each instance of the class invoked by a client Inother words, every client application would see its own data source

Your WCF service is ready to service clients To test it, press F5 and you will see an icon

in the lower-right corner of your screen informing you that the WcfSvcHost utility has started.This utility, which comes with Visual Studio, hosts the service and makes it available to clients

at a specific IP address and port Since WcfSvcHost is meant for testing purposes, only cations running on the same machine can connect to it Once the service has been debugged, itcan be deployed as an IIS application

appli-A few moments later you will see another window, the WCF Test Client utility, whichallows you to test your new service without writing a client application The first time yourun the project you’ll see an error message to the effect that the service doesn’t expose anymetadata This happened because you haven’t configured your application yet Right-clickthe App.config file in the Solution Explorer, and from the shortcut menu, select Edit WCFConfiguration The Configuration Editor window appears, as shown in Figure 21.11

Configuring WCF Services

A WCF service is defined by three parameters: an address where it can be reached (the point), a binding protocol, and a contract All three parameters are configurable, and you neednot edit the service code to redeploy it or to support additional bindings You only need to editthe configuration file

end-The address is an IP address or URL that specifies where the service is located It’s theaddress of the machine on which the service is running and, consequently, the address to

Trang 5

which clients must connect to make requests The binding determines how the clients will

talk to a service and WCF supports multiple bindings The contract, finally, specifies what theservice does; in other words, the methods it provides The contract is the service interface,

much like the classes and methods of a namespace If you want to totally abstract a WCF

service, think of it as a namespace that’s being hosted on a remote computer Just as you cancall a method in a namespace, you can call a method of a WCF service As you saw in the firstexample of this chapter, you can access a remote service from within your project by adding

a reference to the service With that reference in place, Visual Studio will take care of the

housekeeping needed to connect to the remote service (what’s also known as the plumbing)

Figure 21.11

The Configuration

Edi-tor’s window allows you

to configure the

parame-ters of a WCF service

The binding tells the client how the messages will be transmitted between the client and theservice Web services use HTTP to exchange data with the clients This, however, is not perfectfor all cases HTTP is a universal protocol, and it’s been implemented on every operating sys-tem, but it’s the most generic protocol Windows, as well as other operating systems, supportmessaging: a mechanism for reliably transmitting information between two computers, even ifone of them is offline When the receiving computer is connected, the message will be deliveredand processed This mechanism, which relies on Microsoft’s Message Queues, is the most reli-able mechanism for exchanging data between two computers, but this type of communicationisn’t synchronous

There are situations where the WCF service and its client are deployed on the same local

area network For these cases, there are protocols, such as Named Pipes, that perform much

faster than HTTP I can’t discuss the merits of all available bindings in this chapter This is

an advanced topic, and the goal of this chapter is to introduce you to a technique for writingapplications as services The basic techniques are within the reach of the average VB devel-

oper, and I will limit the discussion to the basic techniques for building WCF services and

Trang 6

deploying them on a web server WCF allows you to build a service following the steps cussed so far and then configure them The configuration involves the specification of the end-point (the service’s address) and the binding protocol You can even implement multiple bind-ings on the same service so that different clients can contact the same service using differentprotocols.

dis-To configure the sample WCF service, you must first change the name of the service.Although you changed the default name of the service, the configuration file still remembersthe original name, Service1, which was the name of the sample class that was generated auto-matically and that we removed from the project Click the WCFProducts.Service1 item in theleft pane of the Configuration Editor, which was shown in Figure 21.11, and then select theName property in the right pane Click the button with the ellipsis next to the service’s nameand the Service Type Browser dialog box will open, as shown in Figure 21.12 This dialog box

is similar to the Open dialog box, which allows you to select a file Navigate to the project’sBin/Debug folder and select the WCFProducts.dll file Click open, or double-click the file’sname to see the names of all services implemented in the DLL You will see a single service

name, the WCFProducts.ProductService name Select it and the close the dialog box by

clicking the OK button

to WCFProducts.IProduct interface While configuring the first endpoint, set its name to

HTTPBinding.Now select the second endpoint and you’ll see that it implements the mexHttpBinding, asshown in Figure 21.13 This binding provides the service’s metadata and you need not change

its settings Just set its name to MEXBinding, so that it won’t be displayed as (Empty Name).

Trang 7

Figure 21.13

Configuring an endpoint

of a WCF service

Save the configuration with the Save command from the File menu and close the

Config-uration Editor Now you’re ready to test the service Press F5 again and this time the WCF

Test Client window appears, as shown in Figure 21.14 The WCF Test Utility window

con-sists of two panes: on the left pane you see all the methods of the service (you must expand

the service’s interface to see the names of the methods), and on the right pane you can call theselected method and see the results To see the categories shown in Figure 21.14, for example,

I double-clicked the GetAllCategories item in the left pane and then I clicked the Invoke ton The utility called the GetAllCategories method and displayed the results in the lower

but-part of the pane

You can use the WCF Test Client utility to test the methods of your new service, but tually you must host your service to a web server, or an application, and call it from anotherWindows or web client

even-You can also test the methods that submit data to the service If you double-click the

AddProductmethod name, a new tab will open in the right pane, as shown in Figure 21.15, andyou’ll be prompted to enter values for the method parameters Specify the parameter values

(you don’t have to provide a value for the ProductID parameter; this value is assigned

auto-matically by the service) and then click the Invoke button The utility will call the AddProductmethod, and if executed successfully, it will display the new product in the lower half of thetab, as shown in the figure

Note that the new product’s ID is included in the result of the method because the methodreturns an object of the Product type that represents the newly inserted row

Implementing a web or WCF service is no different from implementing a class that exposescertain functionality through a set of methods and communicates with another application byexchanging specific types The only difference between a class you’d use in a Windows applica-tion and a service is that the members of the service are marked with special attributes More-over, when it comes to WCF services, you must also configure them with the Configuration

Editor

Trang 8

Figure 21.14

Testing the methods of

the new WCF service

in the WCF Test Client

utility

Figure 21.15

Submitting a new

product to the

Product-Service service through

the WCF Test Client

ADO.NET Data Services

Before ending this chapter, I’d like to show you briefly how to create services that expose anentire database This type of service comes as a special project component of Visual Studio, theADO.NET Data Services component An ADO.NET Data service is a web service that exposes

an entire database, or part of it, as a web service What’s special about this component is thatit’s generated automatically for you; all you have to do is specify the tables you want to expose

Trang 9

and a wizard will generate the service for you The data source can be a database, an Entity

Data Model (EDM), or a collection of custom objects There’s nothing new to learn and you cancreate and use data services immediately, with the exception of some techniques for securingyour data The data service will expose methods to both query and update the data source, butyou obviously don’t want to give access to your database to anyone on the Web

Let’s start the exploration of data services by building a new project, the DataService project;you can download it from this URL: www.sybex.com/go/masteringvb2010 Create a new pro-ject of the ASP.NET Web Site type, since your data will be exposed over HTTP As you will

see, you have no need for a website per se, just a web service that will expose the data of a

specific database (or part of it) As soon as the project is created, delete the ASPX page that

Visual Studio adds by default to any project of this type

First, you must create a data source For the purpose of this example, you’ll expose data

from the Northwind database, and to do so, you’ll create an ADO.NET Entity Data Model

by adding a new component of this type to the project Keep the default name, which is

Model1.edmx When the wizard starts, select all of the tables in the database, as you learned

in Chapter 19 For this example, I’ve included all 12 tables of the Northwind database I just

dropped them on the EDM design surface and Visual Studio generated the Model1.edmx data

model

Now that you have the data source, you can add an ADO.NET Data Service component toyour project to expose the selected tables through a web service Right-click the project nameand select Add New Item When the Add New Item dialog box opens, select the ADO.NET

Data Service Name the new service NWWebDataService Visual Studio will create the

NWWebDataService.svc file for you and will open the new data service’s code window You

will see that the new class contains just a few lines of code:

Imports System.Data.Services

Imports System.Linq

Imports System.ServiceModel.Web

Public Class NWWebDataService

‘ TODO: replace [[class name]] with your data class name

Inherits DataService(Of [[class name]])

‘ This method is called only once to initialize service-wide policies

Public Shared Sub InitializeService(

ByVal config As IDataServiceConfiguration)

‘ TODO: set rules to indicate which entity sets

‘ and service operations are visible, updatable, etc

The NWWebDataService inherits from another class, whose name you must supply

by replacing class name in the code line that reads: Inherits DataService(Of [[class

name]]) The class it derives from should be NorthwindEntities, which is the name of the

Trang 10

Data Entity class you created as the project’s data source Technically, you didn’t specify theNorthwindEntities name, but Visual Studio created this class and named it after the database.The statements that are commented out specify the data you want to expose through yourdata service By default, the data service won’t expose any data unless you tell it to do so.Replace the last two statements of the InitializeService routine with the following:

config.SetEntitySetAccessRule("*", EntitySetRights.All)

This statement instructs the service to expose all resources Obviously, this is the last thingyou want to do with a real service that will be accessed from outside your test machine,and I’ll come back to the issue of security, but for now let’s grant unconditional access to alltables through your service For the purpose of this chapter, the service will be hosted by theASP.NET Development Server, which can be accessed from the same machine only

You’re probably thinking it’s time to add some real code, or look at a few thousand lines ofcode generated by the wizard This isn’t the case; your data service is complete Right-click theNWWebDataService component name, and from the context menu, select View In Browser Afew seconds later you will see a new Internet Explorer window displaying a list of all tables inthe database, as shown in Figure 21.16

Figure 21.16

The service exposes the

names of all tables in its

data source

Each table, which is an EntitySet in the data source, is exposed as a collection By appendingthe entity name to the base URL of the service, you can view the rows in the correspondingtables Change the URL in the browser address bar to any of the following to see the products,categories, and customers in the Northwind database:

http://localhost:51000/NWWebDataService.svc/Products

Trang 11

http://localhost:51000/NWWebDataService.svc/Customers

As you will recall from our discussion of the Entity Framework in Chapter 17, ‘‘Using the

Entity Data Model,’’ the Products table is translated into the Products EntitySet, which is made

up of Product entities The port will be different on your machine, but you will see it on yourbrowser’s address bar as soon as you open the service in the browser This port number will

be different every time you start the application, so it wouldn’t be a bad idea to set a specificport for the service Select the DataService project in the Solution Explorer, open the Project

menu, and select DataService Properties On the Project Properties window that opens, selectthe Web tab, which is shown in Figure 21.17 On this tab, you can set the start action (what

happens when you start the project) as well as the server that will host your server For now,select the Specific Port option and set its value to the number of an unused port (I’ve used theport number 51000) If you decide to make the service public, don’t forget to limit the access

to the service (you don’t want people changing your data at will) You’ll see shortly how youcan restrict access to specific tables and even how to intercept certain operators, like insertions,modifications, and deletions, and determine whether to allow or block them from within

your code

Figure 21.17

Configuring the server

that will host the data

service

Figure 21.18 shows how the first customer, the ubiquitous ALFKI customer, is displayed

The output of the service is just XML, and you can write a client application to access the vice and process the selected rows with LINQ Notice the links to the related tables Each cus-tomer has two related tables with the following relative URLs:

ser-Orders:

Customers(’ALFKI’)/Orders

CustomerDemographics:

Customers(’ALFKI’)/CustomerDemographics

Trang 12

Figure 21.18

Requesting a specific

customer through a URL

made up of the service’s

URL and the table name

To view the orders of the customer ALFKI, enter the following URL in your browser:

Trang 13

a specific order by its ID and request its detail lines The following URL does exactly that (theURL should be entered as a single line; it’s been broken here to fit the printed page):

http://localhost:51000/NWWebDataService.svc/Customers(’BLAUS’)/

Orders(10501)/Order_Details

The service will return the following XML document:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>

Trang 14

If you examine it, you’ll see that it includes two related entities: the Order entity (the order

to which all detail lines belong) and the Product entity (the product listed in each detail line)

By default, the data service doesn’t move the related rows from the database to the client Ifyou want to view the related data, you must use the expand keyword followed by the name(s)

of the entities you wish to retrieve along with each product The following URL will bring asingle product, along with its category and supplier:

http://localhost:51000/WebDataService1.svc/

Products(12)?$expand=Category,%20Supplier

If you examine the XML returned by this query, you’ll see that it has three <link> elements,which represent the related rows in other tables: the Order Details, Categories, and Supplierstables The links to the Categories and Suppliers tables have a plus symbol in front of them,and if you click it to expand the corresponding entity, you’ll see the details of the product’scategory or supplier, as shown in Figure 21.19

Figure 21.19

Retrieving related rows

with the $expand

Trang 15

the filter keyword, which must be followed by a filtering expression The following statementwill return all products with a price that exceeds $100:

http://localhost:51000/WebDataService1.svc/Products?$filter=UnitPrice gt 100

Note that the comparison operator is not the greater than sign (>) but the gt operator The

fil-tering expressions can get quite complicated because the URL syntax isn’t flexible enough forexpressing multiple criteria, joining tables together, and so on The data service allows us to getthe data we need with a simple HTTP request, but for many operations you’ll have to down-load the desired data at the client and process them locally with LINQ

The data service works very nicely, and it took us no time at all to write You’ll see shortlyhow to write client applications against this service and how to submit updates to the database

as well For now, keep in mind that an ADO.NET Data service exposes (or ‘‘surfaces’’) the data

in a data source We have used a Data Entity Model as our data source in this example, but

you can use any data source such as LINQ to SQL, or even a collection of custom objects Nomatter how you specify the data source, the data service will expose it through HTTP requests

The Basic Query Operators

For those of you who are interested in exploring the notation for URL querying further,

Table 21.1 provides a quick overview of the various operators

Table 21.1: Basic query operators

Logic operators eq (equals), ne (not equals)

gt (greater than), gteq (greater than or equal to)

lt (less than), lteq (less than or equal to)and, or, and not

Arithmetic operators add (addition), sub (subtraction), mul (multiplication), div (division),

mod (remainder)round (round decimal digits)floor (returns the largest integer that doesn’t exceed a value)ceiling (returns the smallest integer that exceeds a value)

String operators contains, endswith, startswith, length, indexof, insert,

replace, substring, tolower, toupper, trim, concat

Date/time operators Second, hour, minute, day, month, year

Type operators Isof, cast

Here are a few simple examples of the operators you can use in your filtering

expres-sions (I’m only showing the part of the URL that follows the service’s address, which is

http://localhost:51000/WebDataService1.svc/)

Trang 16

Products?$filter=startswith(ProductName, Sir’)Orders?$filter=month(OrderDate) eq 2

Orders?$filter=endswith(ShipName,’markt’)

ADO.NET Data Services allows you to expose (or surface) an entire database and buildclient applications that use the service as the data source The database has already beenexposed, and you can write code to exploit the data using the HttpWebRequest/HttpWebResponse objects, as you saw in the preceding chapter The data are exposed through thesimplest possible mechanism, namely through HTTP But expressing conditions and statements

to retrieve our data using the URL syntax is rather awkward There are more structured tools,LINQ being one of them Can you access the data exposed by your service with LINQ? Theanswer is Yes! And LINQ can translate the standard query operators into the equivalent URLsyntax This URL querying syntax is convenient for testing the service, but no one expects you

to write applications using the query syntax (not in this day and age, at least) There are tools

to use the same data as business objects from a client application, and this is what you’re about

to do next

Building a Windows Client

In this section, I’ll guide you through the process of building a Windows client that consumesthe data of the data service As you can guess, Microsoft didn’t go to the trouble of developingADO.NET Data Services so we would have to process the XML returned by the queries on ourown There are tools that simplify the process enormously, and you’ll see them in this section.The tool that will allow us to see the entities of the new Entity Data Model at the client is acommand-line tool This tool is the DataSvcUtil.exe utility, which reads the service’s meta-data and creates a class that encapsulates the functionality of the service Open a commandprompt window and run the DataSvcUtil.exe utility, which resides in the folder Windows\

Microsoft.NET\Framework.NET\v.4.0.xxx , where xxx is the latest revision of the framework.

This value as of this writing is 4.0.30138, but it will most likely be a little different by the timeVisual Studio 2010 is released Choose the most recent version of the Framework and switch

to that folder In this folder you’ll find the DataSvcUtil.exe utility, which you must execute,passing as an argument the URL of the data service for which you want to generate a proxy (aproxy is a class that exposes the data model and the appropriate methods to access the service’sdata)

To generate the proxy, start the DataSvcUtil.exe utility with a statement similar to the lowing in the command prompt window:

fol-DataSvcUtil.exe /out:"C:\Project\DataServices\NWProxy.vb"

/uri:"http://localhost:51000/NWWebDataService.csv" /language:vb

This creates the proxy file in the root folder of one of my drives, so I can locate it easily later

Be sure to change the path to a folder that’s easy for you to locate later because you will have

to include this file with your solution

Before you execute this command, however, you must start the service for the new port totake effect Open the service in the browser as usual, and as soon as you see the list of tablesexposed by the service, close the browser The service will continue to run in Visual Studio andthe browser is not required The DataSvcUtil.exe utility will generate the file NWProxy.vb

in the specified folder Move this file to the folder that contains the Windows project you’re

Trang 17

building, and then add it to the same project with the Add Existing Item command You

could add the proxy to your current project without moving it, but then the project files will

be scattered all over your drives

To simplify matters, I’ve added a Windows project to the solution, and its main form is

shown in Figure 21.20 This is the client application that will contact the data service to act with the Northwind database To see the newly created data model in action, you must addthe auto-generated proxy file to the Windows project by copying the NWProxy.vb file into thefolder of the Windows application Then place a button on the main form of the test project,

inter-the Read Data From Service button, and create a variable to reference inter-the proxy class with inter-thefollowing declaration in your code (just make sure to change the port to the appropriate value):

Dim service As New NorthwindModel.NorthwindEntities(

Trang 18

allows you to access the data With the service variable in place, you can access the tables in

the Northwind database as collections of typed objects

To access a table, use a loop like the following, which iterates through the rows of the tomers table:

Cus-For Each p In service.ProductsDebug.WriteLine(p.ProductName)Next

As you can see, the collections returned by the service are typed and so the p variable exposes

the names of the columns of the Customers table as properties

In a similar manner, you can iterate through the Categories table:

For Each c In categoriesDebug.WriteLine(c.CategoryName)Next

If you want to access the products in each category, you must explicitly request these rows

of the Products table as you iterate through the categories The data service doesn’t moveall data to the client To request the matching rows of a related table, use the LoadPropertymethod, which accepts two arguments: an entity name, which is a row of the current table, andthe name of the related table To iterate through the categories and their related products, writetwo nested loops like the following:

For Each c In categoriesDebug.WriteLine(c.CategoryName)service.LoadProperty(c, "Products")For Each p In c.Products

Debug.WriteLine(p.ProductName & vbTab & p.UnitPrice.ToString)Next

Next

Since you’re working with typed collections, you can use all LINQ operators to process yourdata The following loop selects the customers from Germany and then the orders they haveplaced:

For Each c In service.Customers.Where(Function(cust) cust.Country = "Germany")service.LoadProperty(c, "Orders")

Debug.WriteLine(c.CompanyName)For Each o In c.Orders

Debug.WriteLine(vbTab & o.OrderID)Next

Next

To use the data service efficiently, you must execute the appropriate queries and retrieveonly the relevant data and not entire tables or even related rows that aren’t needed Let’s sayyou want to retrieve the orders from all customers in Germany that were placed in a specificyear Instead of using the LoadProperty method to move all related rows from the Orderstable on the server to the client, you can use the CreateQuery method to pass a query to the

Trang 19

server You’ll specify your query in LINQ, but the data service will translate it to the ate SQL query and execute it against the server The following expression retrieves the rows ofthe Orders table as a DataServiceQuery object, which is a typed collection:

appropri-service.CreateQuery(Of NorthwindModel.Order)("Orders")

Then you can apply any filtering on this query to limit the number of rows with the Whereoperator:

Dim selOrders = service.CreateQuery(Of NorthwindModel.Order)("Orders").Where( _

Function(o) Year(o.OrderDate) = 1998 And

o.Customer.CustomerID = c)

Let’s say you need all customers in Italy ordered by their company name To request this

information from the database, you’d write a query like the following:

Dim ItalianCustomers = From c In service.Customers

Where c.Country = "Italy"

OrderBy c.CompanyNameSelect c

The preceding LINQ expression was translated into the following URI query:

{http://localhost:51000/NWWebDataService.svc/

Customers()?$filter=Country eq ‘Italy’&$orderby=CompanyName}

Your regular LINQ statements are being automatically translated into URIs that can be cessed by the service It looks like a new variation of LINQ, LINQ to URI, but I haven’t seenthis term being used in the documentation Anyway, the LINQ component knows how to talk

pro-to ADO.NET Data Services, but not always with success because not all expressions you can

use with LINQ have a counterpart in SQL To retrieve the orders with a freight charge of morethan $20, use the following trivial LINQ query:

Dim q = From o In service.Orders

Where o.Freight > 20Select o

The preceding LINQ query is translated into the following URI by the service:

http://localhost:51000/NWWebDataService.svc/

Orders()?$filter=cast(Freight gt 10M,’Edm.Boolean’)

In general, it’s much simpler to write queries using LINQ than to try to construct the properURL for any given query The following LINQ query retrieves the products that contain the

word sauce in their name, regardless of spelling:

Dim q = From p In service.Products

Where p.ProductName.Contains("sauce")

Select p

Trang 20

When this query is translated into a URI query, the service makes use of the substringof ator, as shown here:

oper-{http://localhost:51000/NWWebDataService.svc/Products()?$

filter=substringof(’Sauce’,ProductName)}

If you’re wondering how I found the URI query for these LINQ queries, it’s really simple.Place a breakpoint before the LINQ query you want to monitor, and when the program breaks,

add a new watch on the variable that represents the result of the query (the q variable in most

of this section’s examples) As soon as the LINQ statement is executed, the SQL statement thatwill be executed against the database will appear in the Watches window

Submitting Updates

Using an ADO.NET data service to explore the data in a database is a fairly straightforwardapproach Surfacing your data with a data service is ideal for reporting and other applicationsthat need not modify the database Of course, the data service allows you to submit updates aswell, although this isn’t the best implemented feature of an ADO.NET data service — not yet,that is My main objection to updating a database through a data service is that the methodsthat perform the updates do not return the error messages generated by the database Whatyou get back is a generic error telling you that ‘‘an error occurred while processing thisrequest.’’ Whether the error occurred because the data violated some constraint or whether

it occurred because a field value was inappropriate for the corresponding column, the errormessage is the same If you decide to use a data service to submit updates to the database, beprepared to validate the data as best as you can at the client, because the server won’t helpyou determine the source of the update errors

Since it’s only a question of time before Microsoft brings ADO.NET Data Services up to parwith the other data access technologies, let’s look at the process of submitting updates to thedatabase Since the underlying data source is an Entity Data Model, the process of submittingdata to the service is more or less familiar to you To insert new rows, you create new entities

at the client and submit them to the server with the service’s SaveChanges method To updateexisting rows, you just change the desired fields and then call the same method To delete rows,you delete entities at the client and then call the SaveChanges method

To create a new product, for example, you must first create a Product object:

Dim prod As New NorthwindModel.Product

And then set the object’s properties with statements like the following:

prod.ProductName = "NEW PRODUCT NAME"

prod.UnitPrice = 11.2prod.UnitsInStock = 1prod.UnitsOnOrder = 12

Some of the properties are also entities, and they must be set to the appropriate entity Theproduct category is specified in the database with the CategoryID field, but the entity Product

is related to the entity Category, so you must create a new Category entity and assign it to

the Category property of the prod variable The same is true for the product’s supplier: You

Trang 21

can set the prod.SupplierID field; you must set the Supplier property to an entity of the

Supplier type The following statements create the Category entity by reading a row from theCategoriestable and set up the Category property of the new product:

Dim cat = service.Categories.Where(Function(c) c.CategoryID = 4).First

prod.Category = cat

For the product supplier, I followed a different approach to better demonstrate the process

of updating the Data service This time I created a new Supplier entity, which provides onlyscalar properties, and then I set the new product’s Supplier property to this value:

Dim supplier As New NorthwindModel.Supplier

supplier.CompanyName = "New Supplier"

supplier.ContactName = "Contact name"

supplier.ContactTitle = "Contact title"

supplier.Address = "Supplier address"

supplier.City = "City"

supplier.Country = "Country"

service.AddToSuppliers(supplier)

service.SetLink(prod, "Supplier", supplier)

Note that this time the new entity is added to the Suppliers entity set at the client with the

AddToSuppliersmethod The last statement associates the product with its supplier This linkdoes not exist at the client and must be added explicitly Note that you don’t have to specifythe fields that take part in the relationship

At this point you can submit the new product to the database by calling the SaveChangesmethod The SaveChanges method doesn’t accept any arguments; it submits all changes to thedata service Obviously, it will first submit the new supplier and then the new product But thisisn’t something you have to worry about; the data service knows how to insert the rows in thecorrect order

You may have noticed that the code didn’t set the IDs of the two new rows The IDs are

assigned by the database and the client has no way of knowing the next available ID in the

database Other users may have inserted rows into any table and the client can’t make any

assumptions as to the next available ID You could also use globally unique identifiers (GUIDs)

as primary keys, which would allow you to generate the primary key values at the client, butfor most databases in use today this isn’t the case Windows generates a long string that’s

unique every time you create one (as the term suggests, it’s a globally unique identifier, not inyour computer or your network)

After the SaveChanges method is called, the properties prod.ProductID and supp.Supplier

IDwill have the correct values, which will be transmitted to the client by the data service This

is why we had to explicitly add the appropriate links between the entities at the client with theSetLink method As a reminder, this is necessary for new rows only If the ID of the relatedrow is known, as was the case with the Category entity, there’s no need to call the SetLink

method

The Simple Updates button of the sample application contains the statements presented sofar in this chapter Open the project to see the code that implements the simple operations, likeupdates and deletions

Trang 22

Performing Transactions

Real data-driven applications perform updates in a transactional manner As you will recallfrom Chapter 15, ‘‘Programming with ADO.NET,’’ an order has to be committed to the data-base in a transactional manner; the entire order must fail if a single row fails to be committed

to the database Data services allow you to perform multiple updates in the context of a action as long as all the updates that belong to the transaction are submitted with a single call

trans-to the SaveChanges method In addition, you must set the SaveChangesDefaultOptions

prop-erty of the entity set to Batch.

Let’s consider the example of committing an order to the Northwind database, a ratherfamiliar example in this book You have seen how to perform transactions with ADO.NET aswell as with data entities To perform a transaction with a data service, you first create all theobjects that take part in the transaction: the order’s header and its detail lines You should notcall the SaveChanges method until all entities have been created at the client, as discussed inthe preceding section When the entire order has been set up at the client, you can submit it

to the database by calling the SaveChanges method

Let’s review the actual code that submits a new order to the database You can find the codediscussed in this section in the Transactional Updates button of the DataServices project As

usual, start with a reference to the data service, the service variable:

Dim service As New NorthwindModel.NorthwindEntities(

New Uri("http://localhost:51000/NWWebDataService.svc"))

Then, create a new Order object, the newOrder variable, and add it to the Orders table The new

row is appended to the Orders entity set at the client Moreover, the new order has no ID yet

The OrderID value will be assigned by the database when the transaction is submitted to the database Here are the statements that create the newOrder object:

Dim newOrder As New NorthwindModel.Orderservice.AddToOrders(newOrder)

Now create a customer object that represents the customer that placed the order In a realapplication, the user will most likely select the customer from a list, but since this application

doesn’t have an elaborate user interface, I retrieve a row from the Customers entity set at the client You can’t simply set the newOrder.CustomerID property, even though the newOrder variable exposes the CustomerID property The newOrder object has a Customer property too,

and there’s a relationship between the Orders and Customers tables To associate a customerwith the new order, we must set the order’s Customer property to a Customer object and thenestablish a relationship between the two The following statement creates the Customer objectthat represents the Customer ANTON:

Dim cust = service.Customers.Where(Function(p) p.CustomerID = "ANTON").First()

Next, assign the cust object to the new order’s Customer property and then create a link

between the order and the customer:

newOrder.Customer = custservice.SetLink(newOrder, "Customer", cust)

Trang 23

Follow similar steps to associate an employee with the order:

Dim emp = service.Employees.Where(Function(p) p.EmployeeID = 3).First

newOrder.Employee = emp

service.SetLink(newOrder, "Employee", emp)

And then you can set the remaining (scalar) properties of the order with simple statements likethe following:

newOrder.OrderDate = Now

newOrder.ShipAddress = cust.Address

newOrder.ShipCity = cust.City

Now you can create the order details Each detail is a variable of the Detail type, and each

must be added to the Order_Details property of the newOrder object The Order_Details

property is a collection, and as such it provides an Add method The following statement creates

a new variable, the dtl variable, that represents an order detail:

Dim dtl As New NorthwindModel.Order_Detail

This variable must be added to the Order_Details entity set:

Dim dtlProd = service.Products.Where(Function(p) p.ProductID = 31).First

Set the Product property of the new order to the dtlProduct object:

dtl.Product = dtlProd

And create a link between the detail line and the corresponding row in the Products entity set:

service.SetLink(dtl, "Product", dtlProd)

Then, you can set the remaining properties of the detail line with simple statements like the

following:

dtl.Product = dtlProd

dtl.UnitPrice = 11.2

dtl.Quantity = 9

Trang 24

And finally, associate the new detail line with the new order:

service.SetLink(dtl, "Order", newOrder)

Let’s add a second detail line to the order with the following statements:

dtl = New NorthwindModel.Order_DetaildtlProd = New NorthwindModel.ProductdtlProd = service.Products.Where(Function(p) p.ProductID = 56).First()dtl.Order = newOrder

dtl.Product = dtlProddtl.UnitPrice = dtlProd.UnitPrice * 0.9dtl.Discount = 0.1

dtl.Quantity = -5service.AddToOrder_Details(dtl)newOrder.Order_Details.Add(dtl)service.SetLink(dtl, "Product", dtlProd)service.SetLink(dtl, "Order", newOrder)

This time I’ve chosen to include a discount as well Other than that, the process of creating a

new detail line is the same The new detail line is linked to a Product entity because it contains the ID of a product and to the Order entity to which is belongs.

At last, you can commit the new order to the data service by calling the SaveChanges

method of the service variable All the objects you have created at the client will be submitted

to the database in the proper order by the data service To ensure that all rows will be inserted

in a transactional manner, you must also set the service.SaveChangesDefaultOptionsproperty to the value shown in the code:

service.SaveChangesDefaultOptions = Services.Client.SaveChangesOptions.BatchTry

service.SaveChanges()Catch ex As Exception

MsgBox("FAILED TO COMMIT NEW ORDER")End Try

To see for yourself that the order is submitted in a transactional manner, set the price of theproduct of the first detail line to a negative value The database will reject this value and theentire transaction will fail The error that will be raised by the data service will have a verygeneric description, which won’t help you locate the bug in your code With a straight ADOtransaction, you get back the error message generated by the database, which clearly states thevalue that the database couldn’t accept

Once the transaction has been committed, the data service will return the ID of the order aswell as the IDs of all entities involved in the transaction In this case, there’s only one ID value

to be set by the database

Through the examples in this section, it’s clear that a data service is quite trivial to build andvery easy to use for selection queries When it comes to updating the database, however, thedata service doesn’t provide all the mechanisms you’ve come to expect with other data accesstechnologies You must establish relationships between entities in your code and you can’t rely

on meaningful error descriptions to debug your code

Trang 25

Securing Your Data Service

Exposing a database as a web service on the Internet is not the best idea To secure the

database from malicious users, you must set up some security measures As you recall, the

SetEntitySetAccessRule method sets the access rule for the various entities exposed by theservice So far, you allowed users to access all entities for all operations with the following

statement:

config.SetEntitySetAccessRule("*", EntitySetRights.All)

The first argument is the name of an entity and the second argument is a member of the

EntitySetRight enumeration: None, All, AllRead, AllWrite, ReadMultiple, ReadSingle,

WriteAppend , WriteDelete, WriteMerge, WriteReplace The names of most members are

self-descriptive The ReadMultiple and ReadSingle members determine whether users can

read multiple rows or a single row of the corresponding entity set

Limiting Data Access

Whenever possible, you should limit the number of rows a client application can request

because sloppy developers will retrieve an entire table to select a few rows at the client The

following method call enables clients to read all rows, insert new rows, and replace existing

rows in the Orders entity set:

config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead Or

EntitySetRights.WriteAppend Or EntitySetRights.WriteReplace)Notice that multiple options are combined with the Or operator

The SetServiceOperationAccessRule specifies the access rules for the various operations

The first argument is a method name and the second argument is a member of the

ServiceOperationRights enumeration: All, AllRead, None, OverrideSetEntityRights,

ReadMultiple, or ReadSingle.

The two methods are quite useful for specifying simple access rules but not nearly adequate

enough for implementing more advanced security rules Typical access rules, such as allowing

users to view their own orders only, must be implemented with the appropriate procedures

These procedures are called interceptors because they intercept a query and alter the query’s

default behavior To intercept a selection query, for example, use the QueryInterceptor

attribute followed by the name of an entity set in parentheses:

<QueryInterceptor("Orders")>

Public Function OnQueryOrders() As Expression(Of Func(Of Orders, Boolean))

‘ statements

End Function

The OnQueryOrders function will be called every time a client selects one or more rows from

the Orders table and it’s implemented as a lambda expression that accepts as arguments a

Trang 26

collection of the Orders entity set (the original result of the query) and a Boolean variable.The function’s body should set the second argument to True or False for each member ofthe collection, depending on whether the member should be included in the result or not.Note that the interceptor applies to all queries to the specific table, whether they query theOrders entity set directly or they query the same set indirectly — for example, a query to theCustomers table that expands the customer’s orders.

The following interceptor for the Orders entity set eliminates all orders except for the onesplaced by the customer that makes the request It assumes that the service is hosted as an IISapplication with authentication and the user has connected to the service with the same user-name as the company name, which is rarely the case In a realistic scenario, the service wouldlook up the user’s company name in a table and then use it to filter the results of the query:

<QueryInterceptor("Orders")>

Public Function OnQueryOrders() As Expression(Of Func(Of Orders, Boolean))Return Function(o) o.Customers.ContactName =

HttpContext.Current.User.Identity.NameEnd Function

You can implement interceptors for all types of queries, including insertion, modification,and deletion queries To define a change interceptor for the Products entity set in the North-wind data service project, open the Northwind.svc file and define a service operation methodnamed OnChangeProducts as follows:

<ChangeInterceptor("Products")>

Public Sub OnChangeProducts(ByVal product As Products,

ByVal operations As UpdateOperations)

The interceptor for operations that submit edits to the database includes an argument thatdetermines the update operation that fired the interceptor You can determine the type ofoperation from within the interceptor code and react differently to different operations Youmay reject a delete operation, for example, but accept insertions and updates The methodthat intercepts all modifications is the ChangeInterceptor, and it provides two arguments:the row that’s about to be modified and the operation The operation is a member of theUpdateOperations enumeration, whose members are Add, Update, Change, and Delete What

makes this type of interceptor especially useful is that you can access the fields of the rowbeing modified and reject certain operations based on the value of the row’s columns Thisinformation is passed to the method as a row of the corresponding table and it’s the firstargument of the ChangeInterceptor interceptor

The Products table of the Northwind database, for example, has a column that specifieswhether a product has been discontinued or not, the Discontinued column It probably doesn’tmake a lot of sense to create a new product that’s already discontinued This is a business deci-sion, of course, but here’s an interceptor for the Add operation that disallows the insertion of aproduct that has its Discontinued column set to True:

<ChangeInterceptor("Products")> _Public Sub OnChangeProducts(

Trang 27

ByVal product As Products, ByVal operation As UpdateOperations)

If operation = UpdateOperations.Add Then

If product.Discontinued Then

Throw New DataServiceException(

400, "Can’t modify a discontinued product!")End If

End If

End Sub

If this exception is raised, the service will return an error message with the specified tion If the same error were raised while testing the service from the browser, the error wouldhave been a 400 error (the ‘‘page not found’’ error)

descrip-The Bottom Line

Create a simple ASP.NET web service. Creating ASP.NET web services is straightforwardwith Visual Studio ASP.NET web services provide a great method for delivering data and

functionality within a distributed environment, including the Internet

Master It Develop an ASP.NET web service that enables the user to add two numbers

Consume an ASP.NET web service. Adding a web reference or service reference to a web

service is a key element to creating an application that can consume the web service

Master It Create a new website and add a service reference to a web service on your

machine

Create a WCF service. WCF services are similar to web services, but they give developers

more options for deployment and they support more data exchange protocols

Master It Outline the steps involved in building a WCF service

Work with ADO.NET Data Services. ADO.NET Data Services is a project component thatexposes, or surfaces, data as a service through HTTP Data services are built automatically byVisual Studio based on any data source, and you can access them through URI requests

Master It How do you access the methods of an ADO.NET data service?

Trang 29

The Bottom Line

Each of The Bottom Line sections in the chapters suggest exercises to deepen skills and standing Sometimes there is only one possible solution, but often you are encouraged to useyour skills and creativity to create something that builds on what you know and lets youexplore one of many possible solutions

under-Chapter 1: Getting Started with Visual Basic 2010

Navigate the integrated development environment of Visual Studio. To simplify the cess of application development, Visual Studio provides an environment that’s common to alllanguages, known as an integrated development environment (IDE) The purpose of the IDE

pro-is to enable the developer to do as much as possible with vpro-isual tools before writing code TheIDE provides tools for designing, executing, and debugging your applications It’s your seconddesktop, and you’ll be spending most of your productive hours in this environment

Master It Describe the basic components of the Visual Studio IDE

Solution The basic components of the Visual Studio IDE are the Form Designer, whereyou design the form by dropping and arranging controls, and the code editor, where youwrite the code of the application The controls you can place on the form to design theapplication’s interface are contained in the Toolbox window To set the properties of acontrol, you must select it on the form and locate the appropriate property in the Propertieswindow

Understand the basics of a Windows application. A Windows application consists of avisual interface and code The visual interface is what users see at runtime: a form with con-trols with which the user can interact — by entering strings, checking or clearing check boxes,clicking buttons, and so on The visual interface of the application is designed with visualtools The visual elements incorporate a lot of functionality, but you need to write some code

to react to user actions

Master It Describe the process of building a simple Windows application

Solution First, you must design the form of the application by dropping controls fromthe Toolbox window onto the form Size and align the controls on the form, and then settheir properties in the Properties window The controls include quite a bit of functional-ity right out of the box A TextBox control with its MultiLine property set to True and itsScrollBarsproperty set to Vertical is a complete, self-contained text editor.

Trang 30

After the visual interface has been designed, you can start coding the application dows applications follow an event-driven model: Code the events to which you want yourapplication to react The Click events of the various buttons are typical events to which

Win-an application reacts

Then, there are events that are ignored by developers The TextBox control, for example,fires some 60 events, but most applications don’t react to more than one or two of them.Select the actions to which you want your application to react and program these eventsaccordingly When an event is fired, the appropriate event handler is automatically invoked

Event handlers are subroutines that pass two arguments to the application: the sender argument, which is the control that fired the event, and the e argument which carries addi-

tional information about the event (information such as the mouse button that was pressed,the character typed by the user, and so on) To program a specific event for a control,double-click the control on the design surface and the editor window will come up with thedefault event for the control You can select any other event for the same control to program

in the Events combo box at the top of the editor’s window

Chapter 2: Handling Data

Declare and use variables. Programs use variables to store information during their tion, and different types of information are stored in variables of different types Dates, forexample, are stored in variables of the Date type, while text is stored in variables of the Stringtype The various data types expose a lot of functionality that’s specific to a data type; the meth-ods provided by each data type are listed in the IntelliSense box

execu-Master It How would you declare and initialize a few variables?

Solution To declare multiple variables in a single statement, append each variable’s nameand type to the Dim statement

Dim speed As Single, distance As Integer

Variables of the same type can be separated with commas, and you need not repeat the type

of each variable:

Dim First, Last As String, BirthDate As Date

To initialize the variables, append the equals sign and the value as shown here:

Dim speed As Single = 75.5, distance As Integer = 14902

Master It Explain briefly the Explicit, Strict, and Infer options

Solution These three options determine how Visual Basic handles variable types, and theycan be turned on or off The Explicit option requires that you declare all variables in yourcode before using them When it’s off, you can use a variable in your code without declaring

Trang 31

it The compiler will create a new variable of the Object type The Strict option requires thatyou declare variables with a specific type If the Strict option if off, you can declare variableswithout a type, with a statement like this:

Dim var1, var2

The last option, Infer, allows you to declare and initialize typed variables without

speci-fying their type The compiler infers the variable’s type from the value assigned to it Thefollowing declarations will create a String and a Date variable as long as the Infer option is

on Otherwise, they will create two object variables:

Dim D = #3/5/1008#, S=my name

Use the native data types. The CLR recognized the following data types, which you can use

in your code to declare variables: String, numeric data types (Integer, Double, and so on), Date,Char and Boolean types

All other variables, or variables that are declared without a type, are Object variables and canstore any data type or any object

Master It How will the compiler treat the following statement?

Dim amount = 32

Solution The amount variable is not declared with a specific data type With the default

settings, the compiler will create a new Object variable and store the value 32 in it If the

Infer option is on, the compiler will create an Integer variable and store the value 32 in it Ifyou want to be able to store amounts with a fractional part in this variable, you must assign

a floating-point value to the variable (such as 32.00) or append the R type character to thevalue (32R)

Create custom data types. Practical applications need to store and manipulate multiple dataitems, not just integers and strings To maintain information about people, we need to store

each person’s name, date of birth, address, and so on Products have a name, a description, aprice, and other related items To represent such entities in our code, we use structures, whichhold many pieces of information about a specific entity together

Master It Create a structure for storing products and populate it with data

Solution Structures are declared with the Structure keyword and their fields with the

Dimstatement:

Structure Product

Dim ProductCode As String

Dim ProductName As String

Dim Price As Decimal

Dim Stock As Integer

End Structure

Trang 32

To represent a specific product, declare a variable of the Product type and set its fields,which are exposed as properties of the variable:

Dim P1 As ProductP1.ProductCode = SR-0010

P1.ProductName = NTR TV-42

P1.Price = 374.99P1.Stock = 3

Use arrays. Arrays are structures for storing sets of data as opposed to single-valuedvariables

Master It How would you declare an array for storing 12 names and another one for ing 100 names and Social Security numbers?

stor-Solution The first array stores a set of single-valued data (names) and it has a single mension Since the indexing of the array’s elements starts at 0, the last element’s index forthe first array is 11, and it must be declared as follows:

di-Dim Names(11) As String

The second array stores a set of pair values (names and SSNs), and it must be declared as atwo-dimensional array:

Dim Persons(100,1) As String

If you’d rather avoid the index 0, you can declare the two arrays as follows:

Dim Names(1 To 11) As StringDim Persons(1 To 100, 1 To 1) As String

Chapter 3: Visual Basic Programming Essentials

Use Visual Basic’s flow-control statements. Visual Basic provides several statements forcontrolling the flow of control in a program: decision statements, which change the course ofexecution based on the outcome of a comparison, and loop statements, which repeat a number

of statements while a condition is true or false

Master It Explain briefly the decision statements of Visual Basic

Solution The basic decision statement in VB is the If…End If statement, which executesthe statements between the If and End If keywords if the condition specified in the If part

is true A variation of this statement is the If…Then…Else statement

If the same expression must be compared to multiple values and the program should cute different statements depending on the outcome of the comparison, use the Select Casestatement

exe-Write subroutines and functions. To manage large applications, break your code into small,manageable units These units of code are the subroutines and functions Subroutines performactions and don’t return any values Functions, on the other hand, perform calculations andreturn values Most of the language’s built-in functionality is in the form of functions

Trang 33

Master It How will you create multiple overloaded forms of the same function?

Solution Overloaded functions are variations on the same function with different ments All overloaded forms of a function have the same name, and they’re prefixed withthe Overloads keyword Their lists of arguments, however, are different — either in the

argu-number of arguments or in the argument types

Pass arguments to subroutines and functions. Procedures and functions communicate withone another via arguments, which are listed in a pair of parentheses following the procedure’sname Each argument has a name and a type When you call a procedure, you must supply

values for each argument, and the types of the values should match the types listed in the cedure’s definition

pro-Master It Explain the difference between passing arguments by value and passing ments by reference

argu-Solution The first mechanism, which was the default mechanism with earlier versions

of the language, passes a reference to the argument Arguments passed by reference are

prefixed by the keyword ByRef in the procedure’s definition The procedure has access tothe original values of the arguments passed by reference and can modify them The sec-

ond mechanism passes to the procedure a copy of the original value Arguments passed byvalue are prefixed with the keyword ByVal in the procedure’s definition The procedure

may change the values of the arguments passed by value, but the changes won’t affect thevalue of the original variable

Chapter 4: GUI Design and Event-Driven Programming

Design graphical user interfaces. A Windows application consists of a graphical user face and code The interface of the application is designed with visual tools and consists of

inter-controls that are common to all Windows applications You drop inter-controls from the Toolbox

window onto the form, size and align the controls on the form, and finally set their propertiesthrough the Properties window The controls include quite a bit of functionality right out of thebox, and this functionality is readily available to your application without a single line of code

Master It Describe the process of aligning controls on a form

Solution To align controls on a form, you should select them in groups, according to

their alignment Controls can be aligned to the left, right, top, and bottom After selecting agroup of controls with a common alignment, apply the proper alignment with one of the

commands of the Format Align menu Before aligning multiple controls, you should

adjust their spacing Select the controls you want to space vertically or horizontally and just their spacing with one of the commands of the Format Horizontal Spacing and

ad-Format Vertical Spacing menus You can also align controls visually, by moving them

with the mouse As you move a control around, a blue snap line appears every time the

control is aligned with another one on the form

Program events. Windows applications follow an event-driven model: We code the events towhich we want our application to respond For example, an application reacts to Click events

of the various buttons You select the actions to which you want your application to react andprogram these events accordingly

When an event is fired, the appropriate event handler is automatically invoked Event handlers

are subroutines that pass two arguments to the application: the sender argument (which is

Trang 34

an object that represents the control that fired the event) and the e argument (which carries

additional information about the event)

Master It How will you handle certain keystrokes regardless of the control that receivesthem?

Solution You can intercept all keystrokes at the form’s level by setting the form’s Previewproperty to True Then insert some code in the form’s KeyPress event handler

Key-to examine the keystroke passed Key-to the event handler and Key-to process it To detect the keypresses in the KeyPress event handler, use an If statement like the following:

If e.KeyChar = "A" Then

’ process the A keyEnd If

Write robust applications with error handling. Numerous conditions can cause an tion to crash, but a well-written application should be able to detect abnormal conditions and

applica-handle them gracefully To begin with, you should always validate your data before you attempt

to use them in your code A well-known computer term is ‘‘garbage in, garbage out,’’ whichmeans you shouldn’t perform any calculations on invalid data

Master It How will you execute one or more statements in the context of a structuredexception handler?

Solution A structured exception handler has the following syntax:

Chapter 5: Basic Windows Controls

Use the TextBox control as a data-entry and text-editing tool. The TextBox control is themost common element of the Windows interface, short of the Button control, and it’s used

to display and edit text You can use a TextBox control to prompt users for a single line oftext (such as a product name) or a small document (a product’s detailed description) You can

Trang 35

actually implement a functional text editor by placing a TextBox control on a form and setting

a few of its properties

Master It What are the most important properties of the TextBox control? Which ones

would you set in the Properties windows at design time?

Solution The first property you’ll most likely change is the MultiLine property, whosedefault value is False To set the initial text on the control, use the Text or Lines properties.The Text property returns or sets the text on the control The Lines property is an array

of string that holds each text line in a separate element To interact with the user, use the

text-selection properties SelectedText, SelectionLength, and SelectionStart You canuse these properties to retrieve and manipulate the text selected by the user on the control

or to select text from within your code

Master It How would you implement a control that suggests lists of words matching thecharacters entered by the user?

Solution Use the autocomplete properties AutoCompleteMode, AutoCompleteSource, andAutoCompleteCustomSource The AutoCompleteMode property determines whether the

control will suggest the possible strings, automatically complete the current word as you

type, or do both The AutoCompleteSource property specifies where the strings that will

be displayed will come from and its value is a member of the AutoCompleteSource

enu-meration If this property is set to AutoCompleteSoure.CustomSource, you must set up

an AutoCompleteStringCollection collection with your custom strings and assign it to theAutoCompleteCustomSourceproperty

Use the ListBox, CheckedListBox, and ComboBox controls to present lists of items. The

ListBox control contains a list of items from which the user can select one or more, depending

on the setting of the SelectionMode property

Master It How would you locate an item in a ListBox control?

Solution To locate a string in a ListBox control, use the FindString and FindString

Exactmethods The FindString method locates a string that partially matches the one

you’re searching for; FindStringExact finds an exact match Both methods perform

case-insensitive searches and return the index of the item they’ve located in the list

We usually call the FindStringExact method and then examine its return value If an exactmatch is found, we select the item with the index returned by the FindExact method If

an exact match is not found, in which case the method returns –1, we call the FindStringmethod to locate the nearest match

Use the ScrollBar and TrackBar controls to enable users to specify sizes and positions with the mouse. The ScrollBar and TrackBar controls let the user specify a magnitude by scrolling

a selector between its minimum and maximum values The ScrollBar control uses some visualfeedback to display the effects of scrolling on another entity, such as the current view in a longdocument

Master It Which event of the ScrollBar control would you code to provide visual feedback

to the user?

Solution The ScrollBar control fires two events: the Scroll event and the ValueChangedevent They’re very similar and you can program either event to react to the changes in the

Trang 36

ScrollBar control The advantage of the Scroll event is that it reports the action that caused

it through the e.Type property You can examine the value of this property in your codeand react to actions like the end of the scroll:

Private Sub blueBar_Scroll(

ByVal sender As System.Object,ByVal e As System.Windows.Forms.ScrollEventArgs)Handles blueBar.Scroll

If e.Type = ScrollEventType.EndScroll Then

‘ perform calculations and provide feedbackEnd If

End Sub

Chapter 6: Working with Forms

Visual form design Forms expose a lot of trivial properties for setting their appearance Inaddition, they expose a few properties that simplify the task of designing forms that can beresized at runtime The Anchor property causes a control to be anchored to one or more edges

of the form to which it belongs The Dock property allows you to place on the form controlsthat are docked to one of its edges To create forms with multiple panes that the user can resize

at runtime, use the SplitContainer control If you just can’t fit all the controls in a reasonablysized form, use the AutoScroll properties to create a scrollable form

Master It You’ve been asked to design a form with three distinct sections You should alsoallow users to resize each section How will you design this form?

Solution The type of form required is easily designed with visual tools and the help of theSplitContainer control Place a SplitContainer control on the form and set its Dock property

to Fill You’ve just created two vertical panes on the form, and users can change their

rel-ative sizes at any time To create a third pane, place another SplitContainer control on one

of the first control’s panes and set its Dock property to Fill and its Orientation property

to Horizontal At this point, the form is covered by three panes and users can change each

pane’s size at the expense of its neighboring panes

Design applications with multiple forms. Typical applications are made up of multipleforms: the main form and one or more auxiliary forms To show an auxiliary form from withinthe main form’s code, call the auxiliary form’s Show method, or the ShowDialog method if youwant to display the auxiliary form modally (as a dialog box)

Master It How will you set the values of selected controls in a dialog box, display them,and then read the values selected by the user from the dialog box?

Solution Create a Form variable that represents the dialog box and then access any control

on the dialog box through its name as usual, prefixed by the form’s name:

Dim Dlg As AuxFormDlg.txtName = "name"

Trang 37

Then call the form’s ShowDialog method to display it modally and examine the

Dialog-Resultproperty returned by the method If this value is OK, process the data on the dialogbox; if it isn’t, do not process the dialog box:

If Dlg.ShowDialog = DialogResult.OK Then

UserName = Dlg.TxtName

End If

To display an auxiliary form, just call the Show method This method doesn’t return a

value, and you can read the auxiliary form’s contents from within the main form’s code

at any time You can also access the controls of the main form from within the auxiliary

form’s code

Design dynamic forms. You can create dynamic forms by populating them with controls atruntime through the form’s Controls collection First, create instances of the appropriate con-trols by declaring variables of the corresponding type Then set the properties of each of thesevariables that represent controls Finally, place the control on the form by adding the corre-

sponding variable to the form’s Controls collection

Master It How will you add a TextBox control to your form at runtime and assign a dler to the control’s TextChanged event?

han-Solution Create an instance of the TextBox control, set its Visible property and then add

it to the form’s Controls collection:

Dim TB As New TextBox

TB.Visible = True

’ statements to set other properties,

’ including the control’s location on the form

Me.Controls.Add(TB)

Then write a subroutine that will handle the TextChanged event This subroutine, let’s call itTBChanged(), should have the same signature as the TextBox control’s TextChanged event.Use the AddHandler statement to associate the TBChanged() subroutine with the new con-trol’s TextChanged event:

AddHandler TB.TextChanged, _

New SystemEventHandler(AddressOf TBChanged)

Design menus. Both form menus and context menus are implemented through the

Menu-Strip control The items that make up the menu are ToolMenu-StripMenuItem objects The ToolMenu-Strip-MenuItem objects give you absolute control over the structure and appearance of the menus ofyour application

ToolStrip-Master It What are the two basic events fired by the ToolStripMenuItem object?

Solution When the user clicks a menu item, the DropDownOpened and Click events are

fired in this order The DropDownOpened event gives you a chance to modify the menu that’sabout to be opened After the execution of the DropDownOpened event handler, the Click

event takes place to indicate the selection of a menu command We rarely program the

Trang 38

DropDownOpenedevent, but every menu item’s Click event handler should contain somecode to react to the selection of the item.

Chapter 7: More Windows Controls

Use the OpenFileDialog and SaveFileDialog controls to prompt users for filenames.

Windows applications use certain controls to prompt users for common information, such

as filenames, colors, and fonts Visual Studio provides a set of controls that are grouped inthe Dialogs section of the Toolbox All common dialog controls provide a ShowDialog method,which displays the corresponding dialog box in a modal way The ShowDialog method returns

a value of the DialogResult type, which indicates how the dialog box was closed, and youshould examine this value before processing the data

Master It Your application needs to open an existing file How will you prompt users forthe file’s name?

Solution First you must drop an instance of the OpenFileDialog control on the form Tolimit the files displayed in the Open dialog box, use the Filter property to specify the rele-vant file type(s) To display text files only, set the Filter property to Text files|*.txt

If you want to display multiple filename extensions, use a semicolon to separate sions with the Filter property; for example, the string Images|*.BMP;*.GIF;*.JPG willcause the control to select all the files of these three types and no others The first part of theexpression (Images) is the string that will appear in the drop-down list with the file types.You should also set the CheckFileExists property to True to make sure the file specified

exten-on the cexten-ontrol exists Then display the Open dialog box by calling its ShowDialog method,

as shown here:

If FileOpenDialog1.ShowDialog =Windows.Forms.DialogResult.OK{process file FileOpenDialog1.FileName}

tech-is an array of strings

OpenFileDialog1.Multiselect = TrueOpenFileDialog1.ShowDialog()Dim filesEnum As IEnumeratorListBox1.Items.Clear()filesEnum =

Trang 39

While filesEnum.MoveNext

‘ current file’s name is filesEnum.Current

End While

The other technique is to use the FolderBrowserDialog control, which prompts users to

select a folder, not individual files Upon return, the control’s SelectedPath property tains the pathname of the folder selected by the user from the dialog box, and you can usethis property to process all files of a specific type in the selected folder

con-Use the ColorDialog and FontDialog controls to prompt users for colors and typefaces. TheColor and Font dialog boxes allow you to prompt users for a color value and a font, respec-

tively Before showing the corresponding dialog box, set its Color or Font property according

to the current selection, and then call the control’s ShowDialog method

Master It How will you display color attributes in the Color dialog box when you open it?How will you display the attributes of the selected text’s font in the Font dialog box whenyou open it?

Solution To prompt users to specify a different color for the text on a TextBox control,

execute the following statements:

ColorDialog1.Color = TextBox1.ForeColor

If ColorDialog1.ShowDialog = DialogResult.OK Then

TextBox1.ForeColor = ColorDialog1.Color

End If

To populate the Font dialog box with the font in effect, assign the TextBox control’s Font

property to the FontDialog control’s Font property by using the following statements:

FontDialog1.Font = TextBox1.Font

If FontDialog1.ShowDialog = DialogResult.OK Then

TextBox1.Font = FontDialog1.Font

End If

Use the RichTextBox control as an advanced text editor to present richly formatted text.

The RichTextBox control is an enhanced TextBox control that can display multiple fonts andstyles, format paragraphs with different styles, and provide a few more-advanced text-editingfeatures Even if you don’t need the formatting features of this control, you can use it as an

alternative to the TextBox control At the very least, the RichTextBox control provides more

editing features, a more-useful undo function, and more-flexible search features

Master It You want to display a document with a title in large, bold type, followed by acouple of items in regular style Which statements will you use to create a document like

this on a RichTextBox control?

Document’s Title

Item 1 Description for item 1

Item 2 Description for item 2

Solution To append text to a RichTextBox control, use the AppendText method This

method accepts a string as an argument and appends it to the control’s contents The text is

Trang 40

formatted according to the current selection’s font, which you must set accordingly throughthe SelectionFont property To switch to a different font, set the SelectionFont propertyagain and call the AppendText method.

Assuming that the form contains a control named RichTextBox1, the following statementswill create a document with multiple formats In this sample, I’m using three different type-faces for the document

"Description for item 1" & vbCrLf)Editor.SelectionFont = fntItem

Editor.SelectionIndent = 20Editor.AppendText("Item 2" & vbCrLf)Editor.SelectionFont = fntTextEditor.SelectionIndent = 40Editor.AppendText(

"Description for item 2" & vbCrLf)

Create and present hierarchical lists by using the TreeView control. The TreeView control

is used to display a list of hierarchically structured items Each item in the TreeView control

is represented by a TreeNode object To access the nodes of the TreeView control, use theTreeView.Nodescollection The nodes under a specific node (in other words, the child nodes)form another collection of Node objects, which you can access by using the expressionTreeView.Nodes(i).Nodes The basic property of the Node object is the Text property, whichstores the node’s caption The Node object exposes properties for manipulating its appearance(its foreground/background color, its font, and so on)

Master It How will you set up a TreeView control with a book’s contents at design time?

Solution Place an instance of the TreeView control on the form and then locate its Nodesproperty in the Properties window Click the ellipsis button to open the TreeNode Editordialog box, where you can enter root nodes by clicking the Add Root button and child nodesunder the currently selected node by clicking the Add Child button The book’s chaptersshould be the control’s root nodes, and the sections should be child nodes of those chapternodes If you have nested sections, add them as child nodes of the appropriate node While

a node is selected in the left pane of the dialog box, you can specify its appearance in theright pane by setting the font, color, and image-related properties

Ngày đăng: 12/08/2014, 21:20

TỪ KHÓA LIÊN QUAN