Northwind Pocket Service: Field Service for Windows Mobile-based Pocket PCs

 

Andy Sjostrom and Christian Forsberg

Business anyplace

Contribution from: Odyssey Software

July 2004

Applies to:
   Windows Mobile-based Pocket PCs
   Microsoft® Visual Studio® .NET 2003
   Microsoft .NET Compact Framework version 1.0

Summary: Learn about enterprise mobile solution business aspects and how to develop mobile enterprise applications for Windows Mobile-based Pocket PCs using Visual Studio .NET, .NET Compact Framework, and the Windows Mobile 2003 SDK. The source code in this white paper implements server components, database, and a Pocket PC client. (58 printed pages)

Download Windows Mobile Developer Samples - Field Service for Pocket PC.msi from the Microsoft Download Center.

Contents

Introduction
Enterprise Mobile Solutions: Speed and Value
Northwind Field Service Business Process
System Architecture Design
Server Walkthrough
"Northwind Pocket Service" Client Walkthrough
Code Walkthrough
Conclusion

Introduction

This white paper is about designing and developing a mobile field service application based on the Microsoft® .NET Framework, the Windows Mobile™ platform and the Microsoft .NET Compact Framework.

This white paper will also explain key business aspects of mobile solutions in the enterprise. The reason to include business related discussions in a developer article is to provide you with thoughts and ideas on how to "talk" to decision makers and managers about what you are working with and perhaps are suggesting should be funded. Some paragraphs in this white paper originate from the book Pocket PC Development in the Enterprise (Addison-Wesley Pub Co, ISBN: 0201750791) by Christian Forsberg and Andreas Sjostrom.

The sample solutions will address the needs of the fictitious company Northwind Traders. A sample database containing customers, products, employees, orders, suppliers, shippers, and related tables is shipped with Microsoft Access and Microsoft SQL Server. Northwind Traders will be provided with a mobile solution, targeting Windows Mobile-based Pocket PCs supporting their core business processes. Application features, on both client and server, will be sufficiently complex to cover key .NET Framework and .NET Compact Framework technologies and will illustrate how to meet the primary mobile enterprise application objectives.

Figure 1 illustrates a mobile solution infrastructure including the Pocket PC and Smartphone clients, server components, common services, and the Northwind database. This figure includes potential clients for other business services such as Field Sales, Logisitics, Decision Support and Transportation. These are not covered in this article.

Click here for larger image

Figure 1. Common system architecture supporting many scenarios. Click the thumbnail for a larger image.

Figure 1 shows that some client features are commonly shared both on the Pocket PC and on the Smartphone clients. Some client features are exclusively delivered for Smartphones while other features are exclusively delivered for Pocket PCs. The driving factors behind the division are different use cases, scenarios, and users, combined with the fact that the two form factors are very different but share some similarities. In solution design and development, it is important to identify what features are best deployed to each form factor.

As Northwind Traders mobilize their employees, business process by business process and solution sample by solution sample, the common mobile server infrastructure and common services can be improved and updated.

More information on mobile application development can be found on the following pages:

Windows Mobile Development Center

Microsoft MSDN Mobility & Embedded Development Center

Microsoft .NET Compact Framework

Enterprise Mobile Solutions: Speed and Value

Speed and Value

Speed — Everything happens faster in a world where information is exchanged digitally and people who need the information are connected to it. Customers can find the right vendors faster, businesses can interact with each other faster, and companies face swifter competition and can more quickly respond to new challenges in the marketplace.

Mobile technologies contribute significantly to the speed of business in many ways. Companies can reach their customers with their proposals — regardless of where the customer is — because mobile technologies are connecting and converging with the Web. For corporate use, mobile solutions make it possible to get rid of unnecessary manual steps throughout business operations. Business processes meet mobility, and the system integration that occurs as a result extends existing back office systems to users wherever they are.

Value — Entire ranges of administrative activities and manual processing of collected data are on the verge of extinction. Proposals for goods and services become possible from anywhere in the world.

Mobile technologies add tremendously to the speed of business in many ways. More importantly, corporate back office (people and systems) as well as any connected mobile worker can be made available at the point of mission critical activity, leading to freely exchanged internal and external (customers and partner) interaction. The digitalization of communication will not lead to the end of normal voice telephone calls from the field to the back office. But messaging, such as e-mail or specific knowledge management systems, is appropriate when the person out in the field needs to reach a group of people, for example a group of specialists.

Be a Hero

Developers' solution development skills and practices are undergoing rapid change. In businesses where technology is the business, this is even truer. The more we learn about the business aspects of software development, the faster we can move. The faster we can move, the more we can do business. World-class developers have already learned about and realized business-driven aspects of software development. It is clear that this trend must continue. The heroes of today's and tomorrow's corporations are individuals who are either business-savvy developers or technology-savvy business decision makers (or best of all, a combination of these backgrounds) — with a focus on the benefits of mobile computing.

Definition of Mobile Enterprise Solution

The following definition of a mobile solution in the enterprise is by no means a scientific or industry standard. It is, however, derived from a number of mobile application development projects:

A mobile solution is technology enabling a user to digitally participate in business processes regardless of location. The mobile solution may support wireless connectivity, although it does not have to. It does not require wired connectivity, although it might.

From a business solution standpoint, a mobile solution is likely to encompass strategy and process support — not just technology. Keep in mind, though, that technology is the key enabler.

Online and Offline Scenarios

To be able to be online from anywhere, using unlimited wide area wireless bandwidth is a commonly depicted scenario. But since ubiquitous wireless network coverage won't be realized very soon, it is important that mobile solutions should not have to rely on being constantly online if not absolutely necessary. A mobile platform for your solution needs to support disconnected scenarios. The future will be both online and off-line, just as today. To maximize the value of a mobile solution, from a connectivity standpoint, you need to include both local offline as well as remote online access.

There has been a significant shift in the attitude towards mobile devices in the last couple of years, and the Windows Mobile platform has been a deciding factor in this shift. The shift is about whether a mobile device is just a digital calendar or whether it is a vital element of an enterprise extension of process and system. Windows Mobile-based devices embrace both connected and disconnected scenarios, which mean that the platform adheres to the value-adding factor: information available at anytime, from anywhere. Rolling out Windows Mobile-based devices does bring mobile calendar, e-mail, and note taking capabilities to a work force, but these do not drive business benefits. A true mobile mindset considers the mobile devices to be portable containers for mobile solutions, with the added conveniences of digital calendars and notebooks.

Cost Saving and Revenue Increases

Companies implement mobile extensions to business systems to gain competitive edge. Core processes, such as field service, sales, warehouse operations, and so on can be made to operate faster and more efficiently by using mobile extensions. While some mobile solutions make products and services available to customers and partners and generate increased sales, the two most critical keywords related to mobile solutions are speed and efficiency. Workers get through processes and activities faster, with fewer dependencies on location and manual paper work. Field service is therefore the most common business scenario that companies choose to mobilize.

Mobile business solutions never stand alone. They are built to support business objectives that often have existed for a long time and to extend back office systems. The success of a mobile solution is fundamentally dependent on how solid and well designed its architecture is. The architecture of a mobile solution addresses a number of critical aspects that need to be managed throughout design, development, deployment, and management. To assist in staying tuned to the key business objectives while at the same time addressing functional requirements and solving specific mobile application development challenges, this white paper will provide comprehensive architecture design and coding guidelines.

What Drives the Mobile Solution Growth?

There are a number of driving factors and trends behind the growth of mobile solutions. The following figure illustrates some of the most significant.

Click here for larger image

Figure 2. Driving factors and trends. Click the thumbnail for a larger image.

To stay competitive, a company has to continuously improve its offerings and its operations. Growth in mobile solutions is seen as largely due to the desire of businesses to gain the competitive lead, obtain new revenue channels, and improve productivity and efficiency for a workforce that is increasingly mobile. A major driving factor behind mobile solutions is the convergence between the Internet and mobile devices. Microsoft's mobile platform strategy favors the view that, in the mix of products resulting from this ongoing convergence, one type of device will not fit all needs.

When designing and developing solutions, you must never lose sight of the user. This is true regardless of whether you plan to design a mobile consumer solution for the masses or a solution aimed at only a few people in one company department. When you combine this awareness of the user with the understanding of the pros and cons of each type of device and protocol, you are well prepared to design your solution platform.

Mobile Field Service Automation

Companies invest a significant amount of resources to deploy and manage digital customer relationship management systems. However, the vital link between the company and the customer, the "last mile" of service, is for most companies still paper and pencil. Few companies have systems that will automate the link between the service technicians and the company. Companies can ensure a high level of customer service quality by addressing this last mile of customer service. Enabling the field force to be an effective extension of back office systems is a fundamental piece of the solution.

Field Service Automation enables more precise dispatching and service order completion. Service technicians who have access to service order and customer records in the field and who don't have to rely on multiple phone calls to back office to get the information they need to complete a job are more productive.

Planned Maintenance or Urgent Breakdowns

Field service is about fixing things in a planned maintenance schedule or because of a breakdown situation. The efforts involved have to be carefully noted, in terms of steps taken, the time and effort required, and parts used. At the end of the process, illustrated in Figure 3, an invoice is usually created and the customer receives the invoice.

Click here for larger image

Figure 3. Business Process. Click the thumbnail for a larger image.

Field technicians everywhere around the globe, with or without mobile solutions, perform these general functions. A mobile solution supports their work and information needs, the chain of events necessary to their tasks, and enables the field technician to be digitally a part of all these events. In addition, the field technician can play an active, connected role in processes such as record keeping, billing, accounting, and customer service. Whenever a service need has been detected, by schedule or by a customer call, the most experienced field technician, equipped with a Windows Mobile-based device, can from anywhere play a crucial role in determining the efforts required before they are committed.

For example, a mobile solution can, from a field service perspective, provide the field technician with exact stock levels or expected availability of parts when the technician is out in the field. It can also estimate installation times for the part, and thus accurate expected completion times can be given to the customer. For more complex routines, the mobile solution can even provide step-by-step instructions to the field technician. After the work is done, the mobile solution can be used to note the parts replaced and the time required. Once transmitted to the office, the completed work order immediately triggers an invoice to the customer, with no extra administration.

A digital dataflow means faster turnaround. The more information systems can capture business data at the point of origin and in every interaction with worker, customer, and partner, the more value they provide. Mobile solutions are key enablers to more effective business processes and better customer service, since they speed up and simplify entire processes from beginning to end.

These features enable the field technician to play an active role in the business processes wherever he or she may be, and they enable the rest of the company to participate in the actual field service activities as well. The field technician can, using a Windows Mobile-based device, consult with product experts via the corporate network, in real time. No longer is it just the lonely field technician at the customer's site. The collective knowledge of the entire team of experienced specialists can be there too. The data collected out in the field can, in real time, be analyzed by managers and responsible supervisors. Service levels can be upheld and monitored on a minute-by-minute basis for excellent customer satisfaction.

Tangible Benefits

Broad industry data from leading research firms and our own experience in large mobile application deployments indicates that a mobile solution in field service leads to the following value-add contributions:

  • A 30 – 40 percent reduction in field service back office support.
  • A 2 – 3 day decrease in invoice cycle.
  • 15 – 20 percent improvement in field service productivity.

The digitalization of data collection, processing, and management is driven by the fact that a number on a piece of paper is a one-way ticket to nowhere, while a figure stored digitally is the beginning of strategic thinking. This is an old truth within the entire IT industry, but it is not until the user is enabled to capture, use, and easily share data and information from anywhere that we can close the circle.

The reason why mobile solutions in the enterprise hold such solid promise is that they enable today's activities to take place more efficiently and more effectively, anywhere. Furthermore, while the first wave of mobile solutions might not revolutionize business or systems, it will certainly extend existing processes and systems by making them available to a mobile workforce.

Conclusion

Systems for mobile service technicians that let them feed work orders, parts, time, labor, mileage, customer comments, and other information directly to back office systems provide a competitive edge. Such information can be shared across the enterprise within minutes when transmitted over a wireless network, or within hours via dock or modem on a wired network.

With wireless configurations, the reduced time it takes the system to react or respond to an event offers a competitive advantage. The organization is aware of events occurring in real time and can make decisions to maximize resource utilization or proactively deal with potential issues.

Northwind Field Service Business Process

No More Empty Vending Machines

Northwind Traders owns a number of vending machines that are placed in malls, supermarkets, train stations, airports, and so on. The company has a field service staff responsible for making sure these vending machines are refilled when needed. Take a look in the Northwind Trader's database, and you'll find that some of their products are chocolate, Grandma's Boysenberry Spread, Uncle Bob's Organic Dried Pears, and Ipoh Coffee. The challenge is to keep these vending machines up and running with a solid supply of products. The clients of Northwind Traders rent vending machines and expect a good return on their investments.

Field Service Process

The field service process is fundamentally built on planned and urgent vending machine refills. Northwind Traders has set up a maintenance contract with each vending machine client. Under this contract, the field service technicians visit each site at a defined schedule. The client can also contact Northwind Traders with an urgent refill service order.

Process Without Mobile Solution

The Northwind Traders field service process without a mobile solution involves paper and pencil — paper-based service orders and manual work at the head office. Each day, the technicians go to the head office and pick up service orders that are printed on paper forms. The technicians spend some time discussing who goes where and who does what. Urgent service orders are manually prioritized. When all is done at the head office, the field workers drive away for another day of vending machine refills.

If an urgent call comes in during the day, the head office staff has to call out to the field workers and hope one can come back to pick up the paper-based service order. Otherwise, the service order cannot be addressed until the next business day.

Process with Mobile Solution

The Northwind Traders field service process with a mobile solution is digital from beginning to end. The service orders are digitally created in the back office system and transferred to each and every service technician. This goes both for urgent and for planned refills. There is no need to travel to the head office to pick up the service orders because the service orders are downloaded to the Windows Mobile-based Pocket PC. The service orders are filled out in the field and transferred directly to the back office system. No need for double data entry or paper handling. This leads to quicker invoicing and less need for staff to manage paper forms.

System Architecture Design

Architecture design is, in the context of this white paper, about planning a successful mobile solution implementation. From a business perspective, the following architecture phases assist in achieving a successful implementation:

  • Contextual Architecture — Focuses on important characteristics and requirements and places the mobile solution into a business context.
  • Conceptual Architecture — Defines the functional requirements necessary to support the goals established in the contextual architecture. The Conceptual Architecture deals mainly with the question "What is to be developed?"
  • Logical Architecture — Defines the system architecture services that need to be in place, such as data storage, communication, security, integration, and so on. Object and data modeling occurs in the Logical Architecture phase, which mainly deals with the question "How will the solution be developed?"
  • Physical Architecture — Details components to be developed, sets development standards, and names products and tools to be used. The Physical Architecture mainly deals with the question "With what will the solution be developed?"

Contextual Architecture (Why/Scope)

During the Contextual Architecture phase, important business aspects of the mobile solution are defined. The main deliverables, the Architecture Scope and the Architectural Principles, are defined by working through the following aspects:

  • Specifications of important characteristics and requirements (business and IT principles)
  • Future requirements
  • Requirements and impact from other projects and initiatives
  • Corporate standards, policies, and guidelines

The Architectural Principles need to be articulated such that it is easy to map every effort, deliverable, component, and line of code to at least one of the principles. Matrixes with architectural principals on one axis and mobile solution features and aspects (such as order management, printing, automatic updates, context sensitive help, and so forth) on the other axis are produced throughout the project to ensure that nothing is done that does not strive towards the goals of the project.

For example, some principals can be defined as follows:

  • Improve productivity
  • Reduce cost
  • Bring information closer to the worker
  • Ensure maintainability
  • Minimize the architectural impact of existing back office system

A matrix containing these principals and fundamental project decisions can then be produced to map every decision to relevant principals, indicating which principle every decision supports.

The Architecture Scope contains both a definition of the architecture goal and the scope; that is, what is in the scope of the architecture and what is out of the scope. For example, the Architecture Scope can be defined as follows:

"Northwind Traders needs to operate the field service vending machine refill process in a more efficient way based on the increased customer demands and increased competition. Northwind Traders needs a basic solution that will improve the field force's productivity and reduce cost at the back office.

Table 1 describes aspects that are in scope versus those that are out of scope.

Table 1. Scope range

In Scope Out of Scope
All Northwind Traders offices

New company-wide IT integration platform

Northwind Traders sales people

Integration with phased out Cobol legacy systems

Table 2. Architecture principals

Type Decision Improve productivity Reduce cost Bring information closer to the worker Maintainability Minimize the architectural impact
Function View customer records X   X    
Function Manage orders online X X X    
Function Enable offline mode X        
Infrastructure Implement XML integration platform       X X
Code Use standard coding       X  

Conceptual Architecture (What)

The Conceptual Architecture is functional by nature. By answering the "What" questions, the functions required to address the goals of the solution can be identified and described. The activities to be performed in this phase are meant to define the following aspects:

  • Business process overview or model
  • Business information flow
  • Use-case view or model
  • Actors model
  • Functional requirements by
    • Reliability (for example, availability)
    • Supportability
    • Volumes (for example, number of users, data volumes)
  • Assessment of and references to as-is documentation of existing systems and applications

Business process modeling is the foundation of functional requirements design. Overview and detailed process descriptions can be authored by involving users and people with solid business experience. Figure 4 represents a high-level summary of the refill process.

Click here for larger image

Figure 4. Business process. Click the thumbnail for a larger image.

Each of the major business process steps then needs to be further analyzed into smaller steps, functional requirements, and information system dependencies. Figure 5 displays how this can be illustrated.

Click here for larger image

Figure 5. Business process, scenario, systems, and users. Click the thumbnail for a larger image.

Software logic flowcharts can be designed as each step of the overview business process gets more detailed with more sublevel activities. As each functional requirement gets described, it allows for quantifications to be made. Number of technicians, number of orders to be synchronized, total amount of data in Pocket PC database, amount of transactional data to be synchronized and so on, and available bandwidth (where, when, and how) are some quantifications that need to be addressed in the Conceptual Architecture phase.

Logical Architecture (How)

The Logical Architecture phase deals with services and mechanisms that need to be in place to eventually support the physical implementation of the solution. Logically, mobile solutions often relate to services such as connectivity, communication, storage, security, integration, and distribution. The three most challenging software development aspects related to mobile solutions are network dependency, integration, and security. The Logical Architecture phase aims at addressing these challenges and describes how to solve them. The main deliverables out of the Logical Architecture phase include the following:

  • Information services view
  • Component model view describing the structure of the application services and components (functional modules)
  • Integration views with description of logical interfaces
  • Data or object model (entity model)
  • Technical infrastructure view with logical platform services

A Logical Integration view, shown in Figure 6, provides an easy to understand and communicate illustration of system integration services that need to be in place.

Click here for larger image

Figure 6. Logical integration view. Click the thumbnail for a larger image.

The Logical Distribution view, shown in Figure 7, provides details about what information needs to reside and where and how often the information is transferred from one place to another.

Click here for larger image

Figure 7. Logical distribution view. Click the thumbnail for a larger image.

The solution design is further detailed as object and data modeling occurs in the Logical Architecture phase, using key findings from the preceding phases.

The observant reader might object to the above two figures. The Logical Architecture phase should not deal with physical implementations of services, such as "Pocket PC" or "XML Web Service," but instead with logical terms such as "mobile device" and "communication." However, it is not unlikely that findings in the Contextual Architecture define strategic choices of products, standards, tools, and platforms. Since the purpose of this white paper is to eventually arrive at a Pocket PC-based and .NET Compact Framework-based mobile solution, some physical decisions are made to begin with.

Physical Architecture (With What)

All the physical elements of the architecture are defined at the final architecture phase, the Physical Architecture phase. This includes platform, integration standards, tools, languages, and so on. The core deliverables of a physical architecture definition include the following:

  • Detailed information systems components
  • Hardware and software components (technical infrastructure) and how they are distributed (deployment view)
  • Product list (shopping list)
  • Physical integration, interfaces, and protocols
  • Definition of which standards to comply with
  • Development, test, and production environment
  • Development and management tools
  • Design and development guidelines
  • How can quality and system attributes be met (Service Level Agreement)
  • Security view

Figure 8 illustrates a physical deployment view. The purpose of this view is to show each physical element of the system architecture.

Click here for larger image

Figure 8. Physical deployment view. Click the thumbnail for a larger image.

The figures shown in the previous architecture phases can now be further detailed with physical entities and moved to the Physical Architecture deliverables. The "shopping list" contains all products, the type and quantity, tools, licenses, devices, and so on, that need to be purchased. Design and development guidelines will assist the developers in realizing the solution. The sample project can be used as such. Read on to learn more about the Northwind Pocket Service sample.

Server Walkthrough

For the personnel in the office, a Web application has been prepared to create new services assignments. This Web application is an ASP.NET application written with Microsoft Visual Studio .NET 2003 in C#, with data in SQL Server 2000.

The application shows how to support the initial steps in a service business process.

First Page

The first page is illustrated in Figure 9.

Figure 9. First page

On the first page you find a list of the service items and their respective status. The first item has the status "Open," which means that it has not yet been delivered. When you click on the "Required" date of this service item, you are presented with the service item details, as shown in Figure 10.

Figure 10. Service item details

The details for the service item include information about the products to be delivered.

Create New Service

Back on the first page, if you click the "Add new service" link, you will start the wizard to create a new service item. The first step, as shown in Figure 11, is to select a customer.

Figure 11. Select customer

First you enter part of the customer name, and when you click the Find button, the search results are shown. When you select one of the customers (in this walkthrough, White Clover Markets), the next wizard step, shown in Figure 12, is to enter the other service item details.

Figure 12. Enter service item details

Here you can select the machine, the date that the delivery is required, whether the service is Urgent, and who will perform the service. When you click the Next button, the last wizard step, shown in Figure 13, is to add the products to be delivered.

Figure 13. Add products with required delivery quantity

Each product has a required number of items to deliver and is added to the list by clicking on the New link. The Delete link on each row removes the respective product.

When you click the Finish button, you are returned to the first page and the service item is ready to be transferred to the field worker.

"Northwind Pocket Service" Client Walkthrough

The client application is a Pocket PC application written with Microsoft Visual Studio .NET 2003 in C#, and targeting the .NET Compact Framework.

The application shows how to support a service business process using a mobile handheld device. The design choices were made to align to the process as much as possible and thereby also maximize efficiency for the field worker. The various design choices will be commented during the walkthrough of the application.

First Run

The first time the application is run on the device, no database exists and you are notified with the message box shown in Figure 14.

Figure 14. No database found on first run

After the initial message box, you are routed to the Local tab on the Options screen where the local options (current user, database name and location) are available, as shown in Figure 15.

Figure 15. Local options with suggested database name

The Local database name can be changed, and server (or remote) options can be specified on the second tab, as shown in Figure 16.

Figure 16. Server options

Most important here is to make sure the Server database (URL) option is correct. This is the URL for the SQL Server CE RDA server functionality, and it will be used during the first synchronization with the server (right after the creation of the database). Make sure you have correctly set this functionality up according to the SQL Server CE help file. In a real-world scenario, these settings are preset during installation.

When you tap the Create New Database button in the Local options tab, shown in Figure 15, you are routed to the first screen in the synchronization wizard, shown in Figure 17.

Figure 17. Synchronize wizard for creating new database

Note that the only option available is to initialize (create) a new database, and when you tap the Next button, you will be prompted for the login user name and password, as shown in Figure 18.

Figure 18. Server authentication

When the Finish button is tapped, the first synchronization is started, as shown in Figure 19.

Figure 19. Synchronization is performed

During the synchronization, the wait cursor is shown and the progress is reported on screen. During this process, several calls are made to the server to retrieve data in XML format (DataSets).

When the synchronization is complete, the database is created and loaded with reference data. At this point, the Close button is available, as shown in Figure 20.

Figure 20. Synchronization done

When the Close button is tapped, you are returned to the main menu.

After the first run, and each subsequent time you start the application, you are presented with the main menu screen shown in Figure 21.

Figure 21. Main menu

The functionality of the application is aligned with the business process of the service field worker. The main steps in this process are to plan the service, to perform the service, and to report the performed service. A ListView control has been used to present the main menu options as tapable icons. All menu options are also available in the Menu MainMenu control, as shown in Figure 22.

Figure 22. Alternative menu

The purpose of having the same functionality available in many ways is that different users prefer different ways of doing the same thing. Although this level of redundancy is common in desktop applications, care should be taken not to have too many redundant ways of accessing functionality as it wastes screen estate.

Synchronization

When the database is created and initialized from the server, it includes only reference data. To load the current set of service items, you need to perform a synchronization of service items. This can be done by tapping the Sync icon on the Main menu screen, and the first step in the synchronization wizard appears, as shown in Figure 23.

Figure 23. Synchronization wizard to get new service items

The default choice, Synchronize services, is the correct option, so just tap the Next button to fill in the user name and password, as shown in Figure 24.

Figure 24. Server authentication

With the user name and password entered, a tap on the Finish button starts the synchronization of service items. Service items completed and reported are sent to the server, and new service items to perform are downloaded from the server. The synchronization is complete when the Close button appears, as shown in Figure 25.

Figure 25. Services synchronized

Tapping the Close button closes the synchronization wizard, and you are returned to the main menu.

Planning

The first step in the service process is to plan the service to be performed. The first step in the planning wizard, as shown in Figure 26, allows you to search for new service items to be performed.

Figure 26. Find service items to plan

Search criteria are entered (default values for the date search interval are from today and a month ahead), and when the Find button is tapped, the found service items are presented in the list. The list is sorted on the Required date, and the items that are checked as Urgent are marked with an asterisk. (*). When a service item is selected and the Next button is tapped, the service items details are displayed, as shown in Figure 27.

Figure 27. Service item details

Service item details include some basic information and a list of the products that are to be delivered. The required delivery quantity of each product is also included in the list. The customer name and machine description fields are links that can be tapped to show more details. If you tap the customer name, the information shown in Figure 28 is displayed.

Figure 28. Customer details

With the customer details presented, you are able to add the customer contact to the Contacts application. Figure 29 provides an example of how the application integrates with the standard applications of a Windows Mobile-based Pocket PC. The ability to integrate with the standard applications, such as Contacts, is very powerful as it helps the user maintain personal customer information. When the customer information is added to Contacts, the user can add more information (additional phone numbers, e-mail addresses, and so on) and the information is also more easily available to the user. When the Add to Contacts button shown in Figure 28 is tapped, the new contact is added and displayed in the Contacts application window.

Figure 29. Customer contact added to Contacts

When the new contact is closed (by tapping the OK button in the top-right corner of the screen), you are returned to the customer details screen, and when that screen is closed, you are returned to the service item details screen (step 2 in the planning wizard). If you tap the machine description link, the screen shown in Figure 30 is displayed.

Figure 30. Machine details

This screen includes the machine details, and when it is closed, you are returned once again to the service item details screen (step 2 in the planning wizard). As with the Contacts application described earlier, the ability to integrate with the standard Task application helps the user maintain a personal "to do" list generated from the information in the applications database.

If you tap the Add to Tasks button, shown in Figure 27, a new task in the standard Task application is created and displayed, as shown in Figure 31.

Figure 31. Service item added to Tasks

When the new task is closed and you tap the Add to Calendar button (see Figure 27), a new appointment in the standard Calendar application is created and displayed, as shown in Figure 32. This allows the user to make a personal appointment that can hold more information about the service (start and end time, reminder alarms, and so on).

Figure 32. Service item added to Calendar

As the new appointment is closed, you are once again returned to the service item details screen (step 2 in the planning wizard, shown in Figure 27). A tap on the Next button will take you to the final step in the planning wizard, shown in Figure 33.

Figure 33. Set new service item status

This screen allows you to select a new status for the service item. As you now can consider the service item planned (booked in Calendar, and so on), you change the status to Planned and the service item is ready for the next step in the process, performing the service.

Service

The service process deals with the actual delivery of products. As in the planning process step, the service process functionality is implemented as a wizard, and the first step is to find the service item to perform, as shown in Figure 34.

Figure 34. Find service items to perform

Just as in the planning wizard, search criteria are entered and service items found are presented in the list. When a service item to be performed is selected and the Next button is tapped, the service item details are displayed, as shown in Figure 35.

Figure 35. Service item details

The basic details are presented much in the same way as in the planning wizard, and again, both the customer name and machine description can be tapped to show details. The Next button takes you to the list of products to be delivered, as shown in Figure 36.

Figure 36. Service item products

Each product in the list has a required quantity, and when a product in the list is tapped, it becomes ready for update, as shown in Figure 37.

Figure 37. Deliver a product

The delivered quantity can be updated in the spin box control next to the Update button (the required quantity is supplied as the default value), and when that button is tapped, the quantity is updated in the list. In Figure 37, the selected product name is shown as a link that can be tapped to show the product details, as shown in Figure 38.

Figure 38. Products details

Product details include valuable information such as number of products in stock (possible to deliver) and number of products on order.

Figure 39. Products delivered

When all products are delivered (delivered quantities are entered), the Next button takes you to the final step in the service wizard, shown in Figure 40.

Figure 40. Set new service item status

Again, you can select a new status for the service item. As you now can consider the service item delivered (all products have delivered quantities), you change the status to Delivered and the service item is ready for the next step in the process, reporting the service. In using the important status setting, note how the user gets help from the text that describes what will happen when a particular status selection is made. The status setting control the service process steps and it is therefore a good idea to constantly remind the user how this process works.

Report

The final step in the service process is reporting the service — that is, the confirmation of the service performed, including customer signature. As in the previous process steps, the functionality is implemented as a wizard, and the first step is to find the service item to report, as shown in Figure 41.

Figure 41. Find service items to report

As in the previous wizards, search criteria are entered and service items found are presented in the list. When a service item to be reported is selected and the Next button is tapped, the service item report is displayed, as shown in Figure 42.

Figure 42. Service item summary report

This enables you to verify that the service performed is correct, and when the Next button is tapped, the customer confirmation screen shown in Figure 43 is displayed.

Figure 43. Client name, signature, and copy delivery

In step 3 of the wizard, shown in Figure 43, you can enter the name of the customer contact that will confirm the completion of the service (the default value is the customer contact name). The customer contact can then sign the confirmation directly on the screen. You also select how the customer will be notified that the service has been performed (by e-mail, fax, or directly to a connected printer). The Next button takes you to the final step in the report wizard, shown in Figure 44.

Figure 44. Set new service item status

In the final step, you can select a new status for the service item. As you now can consider the service item completed (planned, performed, and reported), you change the status to Reported and the service item is ready to be sent back to the server during the next synchronization of service items.

Products

As a support function, you can search for products in stock (that is, in the delivery vehicle) by name and category. The inventory list is filled when you tap the Find button, and each product found is displayed with name, number of products in stock, and number of products on order, as shown in Figure 45.

Figure 45. Find products

When you tap-and-hold a product in the list and select the View context menu option, the product details are displayed, as shown in Figure 46.

Figure 46. Product details

Product details include more information such as supplier and price.

Options

The available options are divided into two separate tabs: one for local options and one for server options. The Local options tab is shown in Figure 47.

Figure 47. Local options

On the Local tab, you can select the current user (Employee) and location of database file. The Server options tab is shown in Figure 48.

Figure 48. Server options

The Server tab provides the options for database synchronization using RDA, server login name and password, and service item synchronization using a Web Service.

About

All applications should include a screen with product name, version, copyright, and other legal information. The About option in the main menu takes you to such a screen, shown in Figure 49.

Figure 49. About the application

On the About screen, you can also include a link to a Web page with product or support information.

Code Walkthrough

The previous section provided an example client scenario for the Pocket Service application. Now it is time to look at the code behind the various forms. This code walkthrough is aligned as much as possible with the previous client walkthrough and will cover all the most relevant parts.

Client Walkthrough Code Highlights

When the application is run, the MainForm form is loaded, and its constructor begins like this:

try
{
    // Read settings (from Registry).
    string s = Common.Values.LocalDatabase;
}
catch (Exception)
{
    MessageBox.Show("Could not read settings from registry!", 
                    this.Text);
    this.Close();
}

The dummy string (variable s) is set only to load the singleton class (Common) into memory. Here's a look at the Common class constructor:

public static readonly Common Values = new Common();
private Common()
{
    Load();
}

The Common class includes only a private constructor, and the first time the public and static Values variable is accessed, it will be loaded with the only (single) instance that will be available to all classes in the application.

The private constructor's only purpose is to call the private Load method that includes the following code to load application settings from the registry:

RegistryKey key = Registry.LocalMachine.CreateSubKey(this.registryKey);
this.localDatabase = key.GetValue("LocalDatabase",
    @"\NorthwindX.sdf").ToString();
this.remoteDatabaseURL = key.GetValue("RemoteDatabaseURL",
    "https://server/ssce/sscesa20.dll").ToString();
this.remoteLogin = key.GetValue("RemoteLogin", @"ssceuser").ToString();

When the single instance is disposed (when the application ends), the application settings are saved to the registry in the Save method:

RegistryKey key = Registry.LocalMachine.OpenSubKey(this.registryKey,
    true);
key.SetValue("LocalDatabase", this.localDatabase); 
key.SetValue("RemoteDatabaseURL", this.remoteDatabaseURL);
key.SetValue("RemoteLogin", this.remoteLogin);

Both the Load and the Save methods both use the OpenNETCF.Win32.Registry class included in the Smart Device Framework from OpenNETCF that is also available with source code. The Common class also includes application definitions such as enumerations other constants. An example is the different statuses a service item can have:

public enum ServiceStatus : int
{
    Open, Planned, Delivered, Reported, Invoiced, Closed
}
public static readonly string[] ServiceStatusText = new string[]
    {"Open", "Planned", "Delivered", "Reported", 
     "Invoiced", "Closed"};

The string array is used to provide text for each of the ServiceStatus enum values. The Common class also provides properties for each application setting based on private variables:

private SqlCeConnection databaseConnection;
public SqlCeConnection DatabaseConnection
{
    get { return databaseConnection; }
    set { databaseConnection = value; }
}

private string localDatabase;
public string LocalDatabase
{
    get { return localDatabase; }
    set { localDatabase = value; }
}

Some of the properties are derived (calculated):

public string AppPath
{
    get 
    {
        return Path.GetDirectoryName
        (System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
    }
}

The preceding example provides the current application path as a property that is retrieved by using a very interesting technique included in the .NET Compact Framework called reflection. Reflection allows code to retrieve meta information about the code currently executing in runtime. This includes the ability to examine the name of the currently loaded assembly, types of class members and method parameters, and so on.

Ok, now to return to the MainForm constructor:

try
{
    // Open database connection.
    Common.Values.DatabaseConnection = new
        SqlCeConnection(Common.Values.LocalConnectionString);
    Common.Values.DatabaseConnection.Open();
}
catch (Exception)
{
    MessageBox.Show("Could not connect to local database!", this.Text);
    // Go to Options!
    Options(false);
}
Common.Values.DatabaseConnection.Close();

An attempt is made to open the database, and if everything goes well, the database connection is closed again. However, if no database exists, the options dialog is opened that allow a new database to be created. The code that creates the new database looks like this:

SqlCeEngine engine = 
    new SqlCeEngine(Common.Values.LocalConnectionString);
engine.CreateDatabase();

The initialization of the new database includes the download of reference data and transactional data. In the synchronization form, the tables are defined as two hash tables (one for reference data tables and one for transactional data tables):

// Reference tables.
rdaTables.Add("Categories", "Categories");
rdaTables.Add("Customers", "Customers");
rdaTables.Add("Employees", "Employees");
rdaTables.Add("Machines", "Machines");
rdaTables.Add("Products", "Products");
rdaTables.Add("Suppliers", "Suppliers");

// Transactional tables.
webserviceTables.Add("Services", "Services");
webserviceTables.Add("ServiceDetails", "ServiceDetails"); 

The actual download (pull) of the table data looks like this:

SqlCeRemoteDataAccess rda = new SqlCeRemoteDataAccess();
string sql = "";

rda.InternetLogin = remoteLogin;
rda.InternetPassword = remotePassword;
rda.InternetUrl = Common.Values.RemoteDatabaseURL;
rda.LocalConnectionString = Common.Values.LocalConnectionString;

if (!data)
    sql = " WHERE 'A'='B'";

// Loop through hashtable and pull tables from server.
foreach (DictionaryEntry table in tables)
{
    rda.Pull(table.Key.ToString(), "SELECT * FROM " +
        table.Value.ToString() + sql,
        Common.Values.RemoteConnectionString,
        RdaTrackOption.TrackingOffWithIndexes, "ErrorTable");
}

The preceding code uses a feature in SQL Server CE called RDA (Remote Data Access) that allow tables to be synchronized between a server SQL Server database and a local (device) SQL Server CE database. For more information, see the MSDN Library.

The parameter tables is either the reference or transactional hash table and the parameter data is a flag indicating whether data should be included in the download. For the transactional data tables, this value is false.

Once again, return to the MainForm, and the menu is implemented both as a normal MainMenu control and as a ListView connected to an ImageList with menu option icons:

ListViewItem lvi;
lvi = new ListViewItem("Plan");
lvi.ImageIndex = 0;
lvwMenu.Items.Add(lvi);
lvi = new ListViewItem("Service");
lvi.ImageIndex = 1;
// ...

The code that runs when the first menu option (Plan) is selected looks like this:

Cursor.Current = Cursors.WaitCursor;
PlanForm planForm = new PlanForm(this);
planForm.ShowDialog();

During the load of the new form, the wait cursor is shown. Also note that the current form instance is passed as a parameter to the child form (PlanForm) to allow the child form to control the parent form's visibility.

This is what the PlanForm constructor looks like:

public PlanForm(Form parentForm)
{
    InitializeComponent();
    this.parentForm = parentForm;
}

The parent form instance is saved in a private variable (parentForm) that is used in the form's load event:

private void PlanForm_Load(object sender, EventArgs e)
{
    // ...
    parentForm.Hide();
    Cursor.Current = Cursors.Default;
}

It is used to hide the parent form and remove the wait cursor. Also, it is used when the form closes:

private void PlanForm_Closing(object sender, CancelEventArgs e)
{
    parentForm.Show();
}

The parent form is shown again. The reason for doing this is that there will be only one instance of the application in the current running programs list (Start > Settings > System > Memory > Running Programs).

The PlanForm is implemented as a wizard using panels, and reasons for doing this in preference to having a separate form for each wizard step include the following:

  • The user experience is better because the form load time is removed.
  • Because the nature of a wizard is that you should be able to go back and forth, the control and variable values do not need to be transferred between the forms.
  • As each form takes a considerable amount of memory, this memory is saved.

However, an obvious drawback of this approach is that the form design and implementation in general are a bit more complex.

This is what the code for the Cancel and Back button looks like:

private void btnCancel_Click(object sender, System.EventArgs e)
{
    this.Close();
}

private void btnBack_Click(object sender, System.EventArgs e)
{
    switch (currentStep)
    {
        case 1:
            // Go to first step.
            lblHeading.Text = "Plan 1/3";
            pnlFirst.Visible = true;
            pnlSecond.Visible = false;
            pnlThird.Visible = false;
            btnBack.Enabled = false;
            currentStep = 0;
            break;

        case 2:
            // Go to second step.
            lblHeading.Text = "Plan 2/3";
            btnNext.Text = "Next >";
            pnlFirst.Visible = false;
            pnlSecond.Visible = true;
            pnlThird.Visible = false;
            currentStep = 1;
            break;
    }
}

Note how the panels are shown and hidden to simulate the change of steps in the wizard. Initially (in the form's load event), they are all moved to the same position because they are more easily designed if placed side-by-side in the forms designer.

The code for the Next button, with application logic stripped, looks like this:

private void btnNext_Click(object sender, System.EventArgs e)
{
    switch (currentStep)       
    {         
        case 0:   
            // Go to second step.
            lblHeading.Text = "Plan 2/3";
            pnlFirst.Visible = false;
            pnlSecond.Visible = true;
            pnlThird.Visible = false;
            btnBack.Enabled = true;
            currentStep = 1;
            break;                  
        
        case 1:
            // Go to last step.
            lblHeading.Text = "Plan 3/3";
            btnNext.Text = "Finish";
            pnlFirst.Visible = false;
            pnlSecond.Visible = false;
            pnlThird.Visible = true;
            currentStep = 2;
            break;           
    
        case 2:
            this.Close();
            break;
    }
}

Note how the buttons sometimes change visibility and also change names.

In the PlanForm first step (panel), the Find button is used to search for service items, and the code looks like this:

Cursor.Current = Cursors.WaitCursor;
string dateFrom = "";
string dateTo = "";

// Find values.
if (dtpDateFrom.Value != new DateTime(0))
    dateFrom = dtpDateFrom.Value.ToShortDateString();
if (dtpDateTo.Value != new DateTime(0))
    dateTo = dtpDateTo.Value.ToShortDateString();

try
{
    // Get service list data.
    DataSet ds;
    using (ServiceHandler serviceHandler = new ServiceHandler())
        ds = serviceHandler.GetList((int)Common.ServiceStatus.Open,
            dateFrom, dateTo, txtCustomer.Text, chkType.Checked);

    // Fill ListView from DataSet.
    ListViewItem lvi;
    lvwServices.BeginUpdate();
    lvwServices.Items.Clear();
    foreach (DataRow dr in ds.Tables[0].Rows)
    {
        lvi = new ListViewItem(((DateTime)
            dr["RequiredDate"]).ToShortDateString());
        lvi.SubItems.Add(dr["CustomerName"].ToString());
        lvi.SubItems.Add(dr["Urgent"].ToString());
        lvi.SubItems.Add(dr["ServiceID"].ToString());
        lvi.SubItems.Add(dr["CustomerID"].ToString());
        lvi.SubItems.Add(dr["MachineID"].ToString());
        lvi.SubItems.Add(dr["MachineDescription"].ToString());
        lvi.SubItems.Add(dr["MachineLocation"].ToString());
        lvwServices.Items.Add(lvi);
    }
    lvwServices.EndUpdate();
}
catch (Exception)
{
    MessageBox.Show("Could not find any service items!", this.Text);
}
Cursor.Current = Cursors.Default;

The search arguments (date interval, customer name, and so on) are passed to a business logic class—ServiceHandler (GetList method). The search result is returned in a DataSet, and the ListView is filled with the rows in the only table returned. (Actually, the returned table is a view containing data from several tables.)

This is the ServiceHandler.GetList method implementation:

public DataSet GetList(int status, string dateFrom, string dateTo,
    string customer, bool urgent)
{
    string sql;
    DataSet ds = new DataSet();
    sql = "SELECT S.RequiredDate, C.CompanyName AS CustomerName," +
        " CASE WHEN S.ServiceType=1 THEN '*' ELSE '' END AS Urgent," +
        " S.ServiceID, C.CustomerID, S.MachineID, M.Description AS" +
        " MachineDescription, M.Location AS MachineLocation," +
        " S.DeliveredDate, C.ContactName FROM Services S" +
        " INNER JOIN Machines M ON S.MachineID=M.MachineID" +
        " INNER JOIN Customers C ON M.CustomerID=C.CustomerID 
            WHERE 0=0";
    sql += " AND S.Status = " + status.ToString();
    if (dateFrom.Length  > 0)
        sql += " AND S.RequiredDate >= '" + dateFrom + "'";
    if (dateTo.Length > 0)
        sql += " AND S.RequiredDate <= '" + dateTo + "'";
    if (customer.Length > 0)
        sql += " AND C.CompanyName LIKE '%" + customer + "%'";
    if (urgent)
        sql += " AND S.ServiceType=1";
    sql += " ORDER BY S.RequiredDate";
    da.SelectCommand.CommandText = sql;
    da.Fill(ds, "ServiceList");
    da.SelectCommand.CommandText = defaultSQL;
    return ds;
}

A SQL statement is dynamically built, depending on which parameters contain any values. The result is a join of several table columns, and it is also sorted.

Now for a closer look at the ServiceHandler class. First, the private declarations:

private string defaultSQL = "SELECT * FROM Services";
private string defaultDetailSQL = "SELECT * FROM ServiceDetails";
private SqlCeConnection cn;
private SqlCeDataAdapter da;
private SqlCeDataAdapter daDetail;

As indicated by the variables holding default SQL statements, the ServiceHandler class is responsible for handling the data in the Services and ServiceDetails tables. The constructor looks like this:

public ServiceHandler()
{
    cn = Common.Values.DatabaseConnection;
    cn.Open();

    // Set up order adapter.
    da = new SqlCeDataAdapter(defaultSQL, cn);
    SqlCeCommandBuilder cb = new SqlCeCommandBuilder(da);
    da.InsertCommand = cb.GetInsertCommand();
    da.UpdateCommand = cb.GetUpdateCommand();
    da.DeleteCommand = cb.GetDeleteCommand();

    // Set up order detail adapter.
    daDetail = new SqlCeDataAdapter(defaultDetailSQL, cn);
    SqlCeCommandBuilder cbDetail = new SqlCeCommandBuilder(daDetail);
    daDetail.InsertCommand = cbDetail.GetInsertCommand();
    daDetail.UpdateCommand = cbDetail.GetUpdateCommand();
    daDetail.DeleteCommand = cbDetail.GetDeleteCommand();
}

The database connection is retrieved from the singleton Common class, and it is opened for the lifetime of the ServiceHandler instance. A data adapter is set up for the Services and ServiceDetails tables, and with the use of a command builder, the INSERT, UPDATE, and DELETE statements (SQL) are generated from the SELECT statement.

Since the ServiceHandler class implements the IDisposable interface, here's the code for the Dispose method:

public void Dispose()
{
    daDetail.Dispose();
    da.Dispose();
    cn.Close();
}

The Dispose method makes sure the data adapters are recycled and that the connection is closed.

Returning to the PlanForm, here's a look at the code executed after the last step in the wizard and when you have selected a new status:

using (ServiceHandler serviceHandler = new ServiceHandler())
{
    DataSet ds = serviceHandler.GetForID(serviceID);
    DataRow dr = ds.Tables[0].Rows[0];
    dr["Status"] = Common.ServiceStatus.Planned;
    serviceHandler.Save(ds);
}

Once again, a ServiceHandler instance is used to get the current service item and also to save it with an updated status.

The serviceHandler.GetForID method looks like this:

public DataSet GetForID(string serviceID)
{
    DataSet ds = new DataSet();
    da.SelectCommand.CommandText = defaultSQL + " WHERE ServiceID='" +
        serviceID + "'";
    da.Fill(ds, "Service");
    da.SelectCommand.CommandText = defaultSQL;
    return ds;
}

The SELECT statement is modified to include a WHERE clause, a DataSet is filled using the data adapter, and the DataSet is returned.

This is the code to save the DataSet after the update (serviceHandler.Save method):

public void Save(DataSet dataSetToSave)
{
  da.Update(dataSetToSave, "Service");
}

The data adapter's update method is used with the passed DataSet.

The service details screen displays a button to add a service item to the standard Calendar application of the Windows Mobile-based Pocket PC (using the Pocket Outlook Object Model [POOM]). The code behind the Add to Calendar button looks like this:

// Add appointment.
OlApplication poom = new OlApplication();
poom.Logon();
OlAppointment appointment =
    (OlAppointment)poom.CreateItem(OlItemType.olAppointmentItem);
appointment.Start = DateTime.Parse(lblRequiredDate.Text + " 09:00");
appointment.End = DateTime.Parse(lblRequiredDate.Text + " 11:00");
appointment.Subject = lilMachine.Text + " at " + lilCustomer.Text;
appointment.Location = machineLocation;
appointment.Save();

// Show newly added appointment.
int oId = appointment.Oid;
appointment = null;
appointment = (OlAppointment)poom.GetItemFromOid(oId);
appointment.Display();

The appointment is created with a suggested start and end time during the morning (9 a.m. to 11 a.m.) of the service item required date. The machine description and customer name is used to form the subject, and the machine location is used for appointment location. After the appointment is saved, it is also viewed. This code uses the CFCOM component and the POOM wrapper provided by Odyssey Software. CFCOM is a product that enables .NET CF applications to access COM components, and the POOM wrapper is an example that interfaces with the standard POOM component.

Now, let's have a look at how the service items are synchronized. This synchronization uses a Web service that implements the synchronization logic that is called from the client with the following code:

WebServices.Services servicesWebService = new WebServices.Services();

// Set URL of Web Service.
servicesWebService.Url = Common.Values.RemoteWebServiceURL;

using (ServiceHandler serviceHandler = new ServiceHandler())
{
    DataSet ds = serviceHandler.GetReportedServices();

    // Transfer reported services to server, and get new services back.
    servicesWebService.Credentials =
        new NetworkCredential(remoteLogin, remotePassword);
    DataSet dsReturned = servicesWebService.Sync(
        Common.Values.EmployeeID, ds);

    // Since call to server went OK, assume services where transferred,
    // and can therefore be deleted from the local database
    serviceHandler.DeleteReportedServices();

    // Insert new services (and details) into database.
    serviceHandler.AddNewServices(dsReturned);
}

The Web service is instantiated and the URL is set. The reported (completed) service items are retrieved using the serviceHandler object's GetReportedServices method and sent to the Web service method (Sync) when the credentials are set. When the call to the Web service completes successfully, the reported (completed) service items are removed from the local database (DeleteReportedServices). Finally, the returned (new) service items are added to the local database (AddNewServices).

Here's the serviceHandler.GetReportedServices method:

DataSet ds = new DataSet();
da.SelectCommand.CommandText = "SELECT * FROM Services WHERE Status=" +
    ((int)Common.ServiceStatus.Reported).ToString();
da.Fill(ds, "Services");
da.SelectCommand.CommandText = "SELECT D.* FROM ServiceDetails D" +
    " INNER JOIN Services S ON D.ServiceID=S.ServiceID WHERE" +
    " S.Status=" + ((int)Common.ServiceStatus.Reported).ToString();
da.Fill(ds, "ServiceDetails");
da.SelectCommand.CommandText = defaultSQL;
ds.Tables["Services"].ChildRelations.Add("Services2Details",
    ds.Tables["Services"].Columns["ServiceID"],
    ds.Tables["ServiceDetails"].Columns["ServiceID"], true);
return ds;

Note that the relation between the Services and ServiceDetails tables are added to the DataSet, and the code for the DeleteReportedServices method is as follows:

SqlCeCommand cmd = cn.CreateCommand();
cmd.CommandText = "DELETE FROM ServiceDetails WHERE ServiceDetailID" +
    " IN (SELECT D.ServiceDetailID FROM ServiceDetails D" +
    " INNER JOIN Services S ON D.ServiceID=S.ServiceID WHERE S.Status=" 
    + ((int)Common.ServiceStatus.Reported).ToString() + ")";
cmd.ExecuteNonQuery();
cmd.CommandText = "DELETE FROM Services WHERE Status=" +
    ((int)Common.ServiceStatus.Reported).ToString();
cmd.ExecuteNonQuery();

The two tables are emptied of reported service items, and following is the AddNewServices implementation (dsNew is a DataSet parameter):

DataSet ds = this.GetEmpty();
foreach (DataRow dr in dsNew.Tables["Services"].Rows)
    ds.Tables["Service"].Rows.Add(dr.ItemArray);
this.Save(ds);
ds = this.GetEmptyDetail();
foreach (DataRow dr in dsNew.Tables["ServiceDetails"].Rows)
    ds.Tables["ServiceDetail"].Rows.Add(dr.ItemArray);
this.SaveDetail(ds);

Note that the DataRow ItemArray property is used to add row data because the DataRow can belong to only one DataTable.

The code for the server Web service method looks like this:

[WebMethod]
public DataSet Sync(string employeeID, DataSet dsClient)
{
    SqlConnection cn;
    SqlDataAdapter da;
    SqlDataAdapter daDetail;
    SqlCommandBuilder cb;
    SqlCommandBuilder cbDetail;
    DataSet dsServer;
    DataRow[] selectedRows;
    DataRow drServer;
    DataSet dsReturn;

    // Set up database connection.
    cn = new SqlConnection("data source=(local);initial" +
        " catalog=NorthwindX;integrated security=SSPI;");
    cn.Open();
    da = new SqlDataAdapter("SELECT * FROM Services", cn);
    cb = new SqlCommandBuilder(da);
    da.InsertCommand = cb.GetInsertCommand();
    da.UpdateCommand = cb.GetUpdateCommand();
    da.DeleteCommand = cb.GetDeleteCommand();
    dsServer = new DataSet();
    da.Fill(dsServer, "Services");
    daDetail = new SqlDataAdapter("SELECT * FROM ServiceDetails", cn);
    cbDetail = new SqlCommandBuilder(daDetail);
    daDetail.InsertCommand = cbDetail.GetInsertCommand();
    daDetail.UpdateCommand = cbDetail.GetUpdateCommand();
    daDetail.DeleteCommand = cbDetail.GetDeleteCommand();
    daDetail.Fill(dsServer, "ServiceDetails");
    dsServer.Tables["Services"].ChildRelations.Add("Services2Details",
        dsServer.Tables["Services"].Columns["ServiceID"],
        dsServer.Tables["ServiceDetails"].Columns["ServiceID"], true);

    // Update Services.
    foreach (DataRow drClient in dsClient.Tables["Services"].Rows)
    {
        selectedRows = dsServer.Tables["Services"].Select("ServiceID='" 
            + drClient["ServiceID"].ToString() + "'");
        drServer = selectedRows[0];
        drServer["DeliveredDate"] = drClient["DeliveredDate"];
        drServer["Status"] = drClient["Status"];
        drServer["CustomerCopy"] = drClient["CustomerCopy"];
        drServer["ContactName"] = drClient["ContactName"];
        if (dsClient.Tables["Services"].Columns.Contains("Signature"))
            drServer["Signature"] = drClient["Signature"];

        // Update ServiceDetails.
        foreach (DataRow dr in 
        drClient.GetChildRows("Services2Details"))
        {
            selectedRows = dsServer.Tables["ServiceDetails"].Select(
                "ServiceDetailID='" + 
                dr["ServiceDetailID"].ToString() + "'");
            drServer = selectedRows[0];
            drServer["DeliveredQuantity"] = dr["DeliveredQuantity"];
        }
    }

    // Update server database.
    da.Update(dsServer, "Services");
    daDetail.Update(dsServer, "ServiceDetails");

    // Use EmployeeID and status to select services to return.
    da = new SqlDataAdapter("SELECT * FROM Services WHERE EmployeeID='" 
        + employeeID + "' AND Status=0", cn);
    dsReturn = new DataSet();
    da.Fill(dsReturn, "Services");
    if (!dsClient.Tables["Services"].Columns.Contains("Signature"))
        dsReturn.Tables["Services"].Columns.Remove("Signature");
    da.SelectCommand.CommandText = "SELECT D.* FROM ServiceDetails D" +
        " INNER JOIN Services S ON D.ServiceID=S.ServiceID WHERE" +
        " S.EmployeeID='" + employeeID + "' AND S.Status=0";
    da.Fill(dsReturn, "ServiceDetails");

    // Update status flags (to avoid duplicate transfer).
    SqlCommand cmd = cn.CreateCommand();
    cmd.CommandText = "UPDATE Services SET Status=1 WHERE EmployeeID='" 
        + employeeID + "' AND Status=0";
    cmd.ExecuteNonQuery();

    return dsReturn;
}

First, the database connection and data adapters for the two tables are set up, and the reported service items (included in the dsClient DataSet) are used to update both the Services and ServiceDetails tables in the server database. Then, the new service items (with status set to zero — that is, "Open") are filled into a DataSet that is returned to the client when the status in the server database is updated to prevent duplicate transfer.

Reusable Code

Most of the code in the sample application is reusable in part, but the functionality related to synchronization, located in the SyncHandler, can be reused with great benefit because this is functionality that is probably needed in most enterprise applications. The server Web service implementation for synchronization of service items is an obvious complement to the SyncHandler.

Other interesting code segments for reuse include the implementation of a standard Edit menu by using the EditMenuHandler, the sorting of ListView items using the ListViewItemComparer, and the implementation of input panel functionality in most forms.

Coding Standards

In any enterprise development effort, it is a clear recommendation to decide on a common set of coding standards (or development guidelines). Following is a suggested set of topics to include in such a standard:

  • Code organization and style — The size of modules, layout of modules, space, nesting, legibility, declarations always at the beginning, one statement per row, and so on.
  • Code documentation — Use of inline code comments and the documentation of classes, methods, and parameters.
  • Naming standards — The naming of namespaces, classes, interfaces, enumerations, methods, properties, events, variables, and so on.
  • Error and exception handling — The standard way to handle errors and also report errors.
  • Sample code — Preferably a cross-section implementation covering all the tiers of the design (user interface, business logic, data access, and so on).

In the startup of the project, all developers should be involved in the decision on which coding standards to use. This will assure that the code produced will be fairly independent of the individual developer and therefore will ease maintenance of the application.

Conclusion

The vision for mobile solutions is to put business at the fingertips of customers, partners, and employees. In one short sentence: Mobile solutions add "anywhere capabilities" to enterprise core processes and systems.

The key word is availability. If a product is not available, your customer cannot buy it. Even worse, if your competitor's product is available, and not yours, you lose revenue as well as market share. From a business intelligence point of view, if vital data for decision making is not available when it needs to be, the risk of making wrong decisions is obvious. Mobile solutions are about making information and functionality available anywhere and at anytime.

What we know now about online business clearly shows that the most competitive product does not necessarily win. The winning combination is the product, superb online service, ready availability of products, and services that are integrated with the product. In the mobile marketplace, companies will find new ways to add a competitive edge to their offerings by making both products and service available to their customers from anywhere and thereby building an ever-closer relationship with the customer.

This white paper is intended to provide information vital to understanding and developing enterprise mobile solutions.