You are on page 1of 322

MCT USE ONLY.

STUDENT USE PROHIBITED

OFFICIAL

MICROSOFT

LEARNING

PRODUCT

6464A
Visual Studio 2008: ADO.NET 3.5

Be sure to access the extended learning content on your Course Companion CD enclosed on the back cover of the book.

ii

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Information in this document, including URL and other Internet Web site references, is subject to change without notice. Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places, and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, e-mail address, logo, person, place or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation. Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property. The names of manufacturers, products, or URLs are provided for informational purposes only and Microsoft makes no representations and warranties, either expressed, implied, or statutory, regarding these manufacturers or the use of the products with any Microsoft technologies. The inclusion of a manufacturer or product does not imply endorsement of Microsoft of the manufacturer or product. Links may be provided to third party sites. Such sites are not under the control of Microsoft and Microsoft is not responsible for the contents of any linked site or any link contained in a linked site, or any changes or updates to such sites. Microsoft is not responsible for webcasting or any other form of transmission received from any linked site. Microsoft is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement of Microsoft of the site or the products contained therein. 2008 Microsoft Corporation. All rights reserved. Microsoft, Access, Internet Explorer, MSDN, PowerPoint, SQL Server, Visual Basic, Visual C#, Visual Studio, Windows and Windows Vista are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. All other trademarks are property of their respective owners.

Product Number: 6464A Released: 06/2008

MICROSOFT LICENSE TERMS OFFICIAL MICROSOFT LEARNING PRODUCTS - TRAINER EDITION Pre-Release and Final Release Versions
These license terms are an agreement between Microsoft Corporation and you. Please read them. They apply to the Licensed Content named above, which includes the media on which you received it, if any. The terms also apply to any Microsoft updates, supplements, Internet-based services, and support services

for this Licensed Content, unless other terms accompany those items. If so, those terms apply. By using the Licensed Content, you accept these terms. If you do not accept them, do not use the Licensed Content. If you comply with these license terms, you have the rights below.

1. DEFINITIONS. a. Academic Materials means the printed or electronic documentation such as manuals,
workbooks, white papers, press releases, datasheets, and FAQs which may be included in the Licensed Content. location, an IT Academy location, or such other entity as Microsoft may designate from time to time. conducted at or through Authorized Learning Centers by a Trainer providing training to Students solely on Official Microsoft Learning Products (formerly known as Microsoft Official Curriculum or MOC) and Microsoft Dynamics Learning Products (formerly know as Microsoft Business Solutions Courseware). Each Authorized Training Session will provide training on the subject matter of one (1) Course. Center during an Authorized Training Session, each of which provides training on a particular Microsoft technology subject matter.

b. Authorized Learning Center(s) means a Microsoft Certified Partner for Learning Solutions

c. Authorized Training Session(s) means those training sessions authorized by Microsoft and

d. Course means one of the courses using Licensed Content offered by an Authorized Learning

e. Device(s) means a single computer, device, workstation, terminal, or other digital electronic or
analog device.

f.

Licensed Content means the materials accompanying these license terms. The Licensed Content may include, but is not limited to, the following elements: (i) Trainer Content, (ii) Student Content, (iii) classroom setup guide, and (iv) Software. There are different and separate components of the Licensed Content for each Course. Software means the Virtual Machines and Virtual Hard Disks, or other software applications that may be included with the Licensed Content.

g.

h. Student(s) means a student duly enrolled for an Authorized Training Session at your location.

i.

Student Content means the learning materials accompanying these license terms that are for use by Students and Trainers during an Authorized Training Session. Student Content may include labs, simulations, and courseware files for a Course. Trainer(s) means a) a person who is duly certified by Microsoft as a Microsoft Certified Trainer and b) such other individual as authorized in writing by Microsoft and has been engaged by an Authorized Learning Center to teach or instruct an Authorized Training Session to Students on its behalf. Trainers and Students, as applicable, solely during an Authorized Training Session. Trainer Content may include Virtual Machines, Virtual Hard Disks, Microsoft PowerPoint files, instructor notes, and demonstration guides and script files for a Course. Virtual Hard Disks means Microsoft Software that is comprised of virtualized hard disks (such as a base virtual hard disk or differencing disks) for a Virtual Machine that can be loaded onto a single computer or other device in order to allow end-users to run multiple operating systems concurrently. For the purposes of these license terms, Virtual Hard Disks will be considered Trainer Content. Microsoft Virtual PC or Microsoft Virtual Server software that consists of a virtualized hardware environment, one or more Virtual Hard Disks, and a configuration file setting the parameters of the virtualized hardware environment (e.g., RAM). For the purposes of these license terms, Virtual Hard Disks will be considered Trainer Content. you means the Authorized Learning Center or Trainer, as applicable, that has agreed to these license terms.

j.

k. Trainer Content means the materials accompanying these license terms that are for use by

l.

m. Virtual Machine means a virtualized computing experience, created and accessed using

n.

2. OVERVIEW.
Licensed Content. The Licensed Content includes Software, Academic Materials (online and electronic), Trainer Content, Student Content, classroom setup guide, and associated media. License Model. The Licensed Content is licensed on a per copy per Authorized Learning Center location or per Trainer basis.

3. INSTALLATION AND USE RIGHTS. a. Authorized Learning Centers and Trainers: For each Authorized Training Session, you
may: i. either install individual copies of the relevant Licensed Content on classroom Devices only for use by Students enrolled in and the Trainer delivering the Authorized Training Session, provided that the number of copies in use does not exceed the number of Students enrolled in and the Trainer delivering the Authorized Training Session, OR

ii. install one copy of the relevant Licensed Content on a network server only for access by classroom Devices and only for use by Students enrolled in and the Trainer delivering the Authorized Training Session, provided that the number of Devices accessing the Licensed Content on such server does not exceed the number of Students enrolled in and the Trainer delivering the Authorized Training Session. iii. and allow the Students enrolled in and the Trainer delivering the Authorized Training Session to use the Licensed Content that you install in accordance with (ii) or (ii) above during such Authorized Training Session in accordance with these license terms.

i.

Separation of Components. The components of the Licensed Content are licensed as a single unit. You may not separate the components and install them on different Devices.

ii. Third Party Programs. The Licensed Content may contain third party programs. These license terms will apply to the use of those third party programs, unless other terms accompany those programs.

b. Trainers:
i. Trainers may Use the Licensed Content that you install or that is installed by an Authorized Learning Center on a classroom Device to deliver an Authorized Training Session.

ii. Trainers may also Use a copy of the Licensed Content as follows:

A. Licensed Device. The licensed Device is the Device on which you Use the Licensed Content.
You may install and Use one copy of the Licensed Content on the licensed Device solely for your own personal training Use and for preparation of an Authorized Training Session. personal training Use and for preparation of an Authorized Training Session.

B. Portable Device. You may install another copy on a portable device solely for your own 4. PRE-RELEASE VERSIONS. If this is a pre-release (beta) version, in addition to the other provisions
in this agreement, these terms also apply:

a. Pre-Release Licensed Content. This Licensed Content is a pre-release version. It may not

contain the same information and/or work the way a final version of the Licensed Content will. We may change it for the final, commercial version. We also may not release a commercial version. You will clearly and conspicuously inform any Students who participate in each Authorized Training Session of the foregoing; and, that you or Microsoft are under no obligation to provide them with any further content, including but not limited to the final released version of the Licensed Content for the Course. Microsoft, without charge, the right to use, share and commercialize your feedback in any way and for any purpose. You also give to third parties, without charge, any patent rights needed for their products, technologies and services to use or interface with any specific parts of a Microsoft software, Licensed Content, or service that includes the feedback. You will not give feedback that is subject to a license that requires Microsoft to license its software or documentation to third parties because we include your feedback in them. These rights survive this agreement.

b. Feedback. If you agree to give feedback about the Licensed Content to Microsoft, you give to

c. Confidential Information. The Licensed Content, including any viewer, user interface, features

and documentation that may be included with the Licensed Content, is confidential and proprietary to Microsoft and its suppliers. i. Use. For five years after installation of the Licensed Content or its commercial release, whichever is first, you may not disclose confidential information to third parties. You may disclose confidential information only to your employees and consultants who need to know the information. You must have written agreements with them that protect the confidential information at least as much as this agreement. Survival. Your duty to protect confidential information survives this agreement.

ii.

iii. Exclusions. You may disclose confidential information in response to a judicial or governmental order. You must first give written notice to Microsoft to allow it to seek a

protective order or otherwise protect the information. Confidential information does not include information that d. becomes publicly known through no wrongful act; you received from a third party who did not breach confidentiality obligations to Microsoft or its suppliers; or you developed independently.

Term. The term of this agreement for pre-release versions is (i) the date which Microsoft informs you is the end date for using the beta version, or (ii) the commercial release of the final release version of the Licensed Content, whichever is first (beta term). Use. You will cease using all copies of the beta version upon expiration or termination of the beta term, and will destroy all copies of same in the possession or under your control and/or in the possession or under the control of any Trainers who have received copies of the pre-released version. Copies. Microsoft will inform Authorized Learning Centers if they may make copies of the beta version (in either print and/or CD version) and distribute such copies to Students and/or Trainers. If Microsoft allows such distribution, you will follow any additional terms that Microsoft provides to you for such copies and distribution.

e.

f.

5. ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS.


a. Authorized Learning Centers and Trainers: i. Software.

ii. Virtual Hard Disks. The Licensed Content may contain versions of Microsoft XP, Microsoft Windows Vista, Windows Server 2003, Windows Server 2008, and Windows 2000 Advanced Server and/or other Microsoft products which are provided in Virtual Hard Disks. A. If the Virtual Hard Disks and the labs are launched through the Microsoft Learning Lab Launcher, then these terms apply: Time-Sensitive Software. If the Software is not reset, it will stop running based upon the time indicated on the install of the Virtual Machines (between 30 and 500 days after you install it). You will not receive notice before it stops running. You may not be able to access data used or information saved with the Virtual Machines when it stops running and may be forced to reset these Virtual Machines to their original state. You must remove the Software from the Devices at the end of each Authorized Training Session and reinstall and launch it prior to the beginning of the next Authorized Training Session. B. If the Virtual Hard Disks require a product key to launch, then these terms apply: Microsoft will deactivate the operating system associated with each Virtual Hard Disk. Before installing any Virtual Hard Disks on classroom Devices for use during an Authorized Training Session, you will obtain from Microsoft a product key for the operating system software for the Virtual Hard Disks and will activate such Software with Microsoft using such product key. C. These terms apply to all Virtual Machines and Virtual Hard Disks:

You may only use the Virtual Machines and Virtual Hard Disks if you comply with the terms and conditions of this agreement and the following security requirements: o o You may not install Virtual Machines and Virtual Hard Disks on portable Devices or Devices that are accessible to other networks. You must remove Virtual Machines and Virtual Hard Disks from all classroom Devices at the end of each Authorized Training Session, except those held at Microsoft Certified Partners for Learning Solutions locations. You must remove the differencing drive portions of the Virtual Hard Disks from all classroom Devices at the end of each Authorized Training Session at Microsoft Certified Partners for Learning Solutions locations. You will ensure that the Virtual Machines and Virtual Hard Disks are not copied or downloaded from Devices on which you installed them. You will strictly comply with all Microsoft instructions relating to installation, use, activation and deactivation, and security of Virtual Machines and Virtual Hard Disks. You may not modify the Virtual Machines and Virtual Hard Disks or any contents thereof. You may not reproduce or redistribute the Virtual Machines or Virtual Hard Disks.

o o o o

ii. Classroom Setup Guide. You will assure any Licensed Content installed for use during an
Authorized Training Session will be done in accordance with the classroom set-up guide for the Course. iii. Media Elements and Templates. You may allow Trainers and Students to use images, clip art, animations, sounds, music, shapes, video clips and templates provided with the Licensed Content solely in an Authorized Training Session. If Trainers have their own copy of the Licensed Content, they may use Media Elements for their personal training use. iv. iv Evaluation Software. Any Software that is included in the Student Content designated as Evaluation Software may be used by Students solely for their personal training outside of the Authorized Training Session.

b. Trainers Only:
i. Use of PowerPoint Slide Deck Templates. The Trainer Content may include Microsoft PowerPoint slide decks. Trainers may use, copy and modify the PowerPoint slide decks only for providing an Authorized Training Session. If you elect to exercise the foregoing, you will agree or ensure Trainer agrees: (a) that modification of the slide decks will not constitute creation of obscene or scandalous works, as defined by federal law at the time the work is created; and (b) to comply with all other terms and conditions of this agreement.

ii. Use of Instructional Components in Trainer Content. For each Authorized Training Session, Trainers may customize and reproduce, in accordance with the MCT Agreement, those portions of the Licensed Content that are logically associated with instruction of the Authorized Training Session. If you elect to exercise the foregoing rights, you agree or ensure the Trainer agrees: (a) that any of these customizations or reproductions will only be used for providing an Authorized Training Session and (b) to comply with all other terms and conditions of this agreement.

iii. Academic Materials. If the Licensed Content contains Academic Materials, you may copy and use the Academic Materials. You may not make any modifications to the Academic Materials and you may not print any book (either electronic or print version) in its entirety. If you reproduce any Academic Materials, you agree that:

The use of the Academic Materials will be only for your personal reference or training use You will not republish or post the Academic Materials on any network computer or broadcast in any media; You will include the Academic Materials original copyright notice, or a copyright notice to Microsofts benefit in the format provided below: Form of Notice: 2008 Reprinted for personal reference use only with permission by Microsoft Corporation. All rights reserved. Microsoft, Windows, and Windows Server are either registered trademarks or trademarks of Microsoft Corporation in the US and/or other countries. Other product and company names mentioned herein may be the trademarks of their respective owners.

6. INTERNET-BASED SERVICES. Microsoft may provide Internet-based services with the Licensed

Content. It may change or cancel them at any time. You may not use these services in any way that could harm them or impair anyone elses use of them. You may not use the services to try to gain unauthorized access to any service, data, account or network by any means.

7. SCOPE OF LICENSE. The Licensed Content is licensed, not sold. This agreement only gives you some

rights to use the Licensed Content. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the Licensed Content only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the Licensed Content that only allow you to use it in certain ways. You may not install more copies of the Licensed Content on classroom Devices than the number of Students and the Trainer in the Authorized Training Session; allow more classroom Devices to access the server than the number of Students enrolled in and the Trainer delivering the Authorized Training Session if the Licensed Content is installed on a network server; copy or reproduce the Licensed Content to any server or location for further reproduction or distribution; disclose the results of any benchmark tests of the Licensed Content to any third party without Microsofts prior written approval; work around any technical limitations in the Licensed Content; reverse engineer, decompile or disassemble the Licensed Content, except and only to the extent that applicable law expressly permits, despite this limitation; make more copies of the Licensed Content than specified in this agreement or allowed by applicable law, despite this limitation; publish the Licensed Content for others to copy;

transfer the Licensed Content, in whole or in part, to a third party; access or use any Licensed Content for which you (i) are not providing a Course and/or (ii) have not been authorized by Microsoft to access and use; rent, lease or lend the Licensed Content; or use the Licensed Content for commercial hosting services or general business purposes. Rights to access the server software that may be included with the Licensed Content, including the Virtual Hard Disks does not give you any right to implement Microsoft patents or other Microsoft intellectual property in software or devices that may access the server.

8. EXPORT RESTRICTIONS. The Licensed Content is subject to United States export laws and

regulations. You must comply with all domestic and international export laws and regulations that apply to the Licensed Content. These laws include restrictions on destinations, end users and end use. For additional information, see www.microsoft.com/exporting. Content marked as NFR or Not for Resale.

9. NOT FOR RESALE SOFTWARE/LICENSED CONTENT. You may not sell software or Licensed 10. ACADEMIC EDITION. You must be a Qualified Educational User to use Licensed Content marked as
Academic Edition or AE. If you do not know whether you are a Qualified Educational User, visit www.microsoft.com/education or contact the Microsoft affiliate serving your country. fail to comply with the terms and conditions of these license terms. In the event your status as an Authorized Learning Center or Trainer a) expires, b) is voluntarily terminated by you, and/or c) is terminated by Microsoft, this agreement shall automatically terminate. Upon any termination of this agreement, you must destroy all copies of the Licensed Content and all of its component parts.

11. TERMINATION. Without prejudice to any other rights, Microsoft may terminate this agreement if you

12. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates, Internet-

based services and support services that you use, are the entire agreement for the Licensed Content and support services.

13. APPLICABLE LAW. a. United States. If you acquired the Licensed Content in the United States, Washington state law
governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort.

b. Outside the United States. If you acquired the Licensed Content in any other country, the laws
of that country apply.

14. LEGAL EFFECT. This agreement describes certain legal rights. You may have other rights under the

laws of your country. You may also have rights with respect to the party from whom you acquired the Licensed Content. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.

15. DISCLAIMER OF WARRANTY. The Licensed Content is licensed as-is. You bear the risk of
using it. Microsoft gives no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this agreement cannot change. To the extent permitted under your local laws, Microsoft excludes the implied warranties of merchantability, fitness for a particular purpose and non-infringement.

16. LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. YOU CAN RECOVER FROM
MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. This limitation applies to anything related to the Licensed Content, software, services, content (including code) on third party Internet sites, or third party programs; and claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.

It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages. Please note: As this Licensed Content is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French. Remarque : Ce le contenu sous licence tant distribu au Qubec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en franais. EXONRATION DE GARANTIE. Le contenu sous licence vis par une licence est offert tel quel . Toute utilisation de ce contenu sous licence est votre seule risque et pril. Microsoft naccorde aucune autre garantie expresse. Vous pouvez bnficier de droits additionnels en vertu du droit local sur la protection dues consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualit marchande, dadquation un usage particulier et dabsence de contrefaon sont exclues. LIMITATION DES DOMMAGES-INTRTS ET EXCLUSION DE RESPONSABILIT POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement hauteur de 5,00 $ US. Vous ne pouvez prtendre aucune indemnisation pour les autres dommages, y compris les dommages spciaux, indirects ou accessoires et pertes de bnfices. Cette limitation concerne: tout ce qui est reli au le contenu sous licence , aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et les rclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilit stricte, de ngligence ou dune autre faute dans la limite autorise par la loi en vigueur.

Elle sapplique galement, mme si Microsoft connaissait ou devrait connatre lventualit dun tel dommage. Si votre pays nautorise pas lexclusion ou la limitation de responsabilit pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou lexclusion ci-dessus ne sappliquera pas votre gard. EFFET JURIDIQUE. Le prsent contrat dcrit certains droits juridiques. Vous pourriez avoir dautres droits prvus par les lois de votre pays. Le prsent contrat ne modifie pas les droits que vous confrent les lois de votre pays si celles-ci ne le permettent pas.

Visual Studio 2008: ADO.NET 3.5

iii

MCT USE ONLY. STUDENT USE PROHIBITED

Contents
Module 1: Getting Started with ADO.NET 3.5
Lesson 1: Introduction to ADO.NET 3.5 Lesson 2: Connecting to a Database and Retrieving Data 1-3 1-7

Lesson 3: Best Practices for Managing Connections and Performing Queries 1-15 Lab: Connecting to a Database and Retrieving Data 1-22

Module 2: Modifying Data by Using ADO.NET Commands


Lesson 1: Inserting, Updating, and Deleting Data Lesson 2: Managing Data Integrity and Concurrency Lab: Modifying Data by Using ADO.NET Commands 2-3 2-8 2-14

Module 3: Querying and Maintaining Data by Using DataSets


Lesson 1: Creating and Using a DataSet to Retrieve Data Lesson 2: Updating a Database by Using a DataSet Lesson 3: Using a DataSet in an Occasionally Connected Environment Lab: Using a DataSet to Retrieve and Modify Data 3-3 3-10 3-16 3-19

Module 4: Querying and Maintaining Data by Using LINQ


Lesson 1: Querying In-Memory Data by Using LINQ Query Expressions Lesson 2: Retrieving Data by Using LINQ to SQL Lesson 3: Modifying Data by Using LINQ to SQL Lab: Querying and Maintaining Data by Using LINQ to SQL 4-3 4-9 4-17 4-22

iv

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module 5: Implementing an Entity Data Model by Using the ADO.NET Entity Framework
Lesson 1: Creating an Entity Data Model by Using the ADO.NET Entity Framework Lesson 2: Querying and Modifying Data by Using the ADO.NET Entity Framework Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework 5-3 5-9 5-17

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services


Lesson 1: Understanding Microsoft Synchronization Services Lesson 2: Downloading Data by Using Synchronization Services Lesson 3: Uploading Data by Using Synchronization Services Lab: Building Occasionally Connected Solutions by Using Synchronization Services Course Evaluation 6-3 6-8 6-13 6-18 6-34

Lab Answer Keys


L1 - L110

About This Course

MCT USE ONLY. STUDENT USE PROHIBITED

About This Course


This section provides a brief description of the course, audience, suggested prerequisites, and course objectives.

Course Description
This two-day instructor-led course describes the key features of application development with Microsoft database development technologies, including Microsoft Visual Studio 2008 development system and Microsoft ADO.NET 3.5. It explains how to develop an application that can insert, delete, and update database records in both a connected and occasionally connected scenario.

Audience
This course is intended for application developers. You should know how to build Windows Forms applications and how to use the common features of the base class library. You should have a basic understanding of Relational Database Management System databases and Transactional Structured Query Language. You do not have to understand concepts such as advanced UI threading and asynchronous programming. You also do not require experience building Visual Studio add-ins or custom designers.

Student Prerequisites
In addition to your professional experience, students who attend this training should have technical knowledge equivalent to the following: Intermediate experience of application development by using previous versions of Microsoft Visual Studio. (Level 200)

Course Objectives
After completing this course, you will be able to: Use ADO.NET commands to insert, delete, and modify database records. Use datasets to access tables in an occasionally connected application. Use Language-Integrated Query (LINQ) to insert, delete, and modify database records. Use the Entity Framework for ADO.NET and Entity SQL to develop code that insert, delete, and modify entities in a conceptual model.

ii

About This Course

MCT USE ONLY. STUDENT USE PROHIBITED

Use Synchronization Services to insert, delete, and modify records in an occasionally connected application.

Course Outline
This section provides an outline of the course: Module 1, "Getting Started with ADO.NET 3.5." This module introduces ADO.NET and describes how to connect to a database and how to use ADO.NET commands to retrieve data. It shows how to use simple commands and commands with parameters. Module 2, "Modifying Data by Using ADO.NET Commands." This module describes how to use ADO.NET commands to insert, delete, and modify database records. It shows how to perform commands asynchronously and under a transaction. Module 3, "Querying and Maintaining Data by Using DataSets." This module describes how to access and manipulate data by using a DataSet. It shows how to create a typed DataSet and how to use a DataSet in an occasionally connected scenario. Module 4, "Querying and Maintaining Data by Using LINQ." This module describes the capabilities of LINQ and how to use LINQ to query and modify data. Module 5, "Implementing an Entity Data Model by Using the ADO.NET Entity Framework." This module describes the conceptual and logical models of data and how to map between the two. It explains how to use Entity SQL to access data through the entity model. Module 6, "Building Occasionally Connected Solutions by Using Synchronization Services." This module describes how to use Synchronization Services to synchronize a local database cache on an occasionally connected application with a database server.

Course Materials
The following materials are included with your kit: Course Handbook. The Course Handbook contains the material covered in class. It is meant to be used in conjunction with the Course Companion CD. Course Companion CD. The Course Companion CD contains the full course content, including expanded content for each topic page, full lab exercises and

About This Course

iii

MCT USE ONLY. STUDENT USE PROHIBITED

answer keys, topical and categorized resources, and Web links. It is meant to be used both inside and outside the class.
Note: To access the full course content, insert the Course Companion CD into the CDROM drive, and then in the root directory of the CD, double-click StartCD.exe.

Course evaluation. At the end of the course, you will have the opportunity to complete an online evaluation to provide feedback on the course, training facility, and instructor.

To provide additional comments or feedback on the course, send an e-mail message to support@mscourseware.com. To inquire about the Microsoft Certification Program, send an e-mail message to mcphelp@microsoft.com.

Virtual Machine Environment


This section provides the information for setting up the classroom environment to support the business scenario of the course.

Virtual Machine Configuration


In this course, you will use Microsoft Virtual Server 2005 R2 SP1 to perform the labs.

Important: At the end of each lab, you must close the virtual machine and must not save any changes. To close a virtual machine without saving the changes, perform the following steps: 1. On the host computer, click Start, point to All Programs, point to Microsoft Virtual Server, and then click Virtual Server Administration Website. 2. Under Navigation, click Master Status. For each virtual machine that is running, right-click the virtual machine name, click Turn off Virtual Machine and Discard Undo Disks, and then click OK.

The following table shows the role of each virtual machine used in this course.
Virtual machine 6464A-XX (where XX represents the module number Role Application development computer

iv

About This Course

MCT USE ONLY. STUDENT USE PROHIBITED

Software Configuration
The following software is installed on each virtual machine: Windows Vista Enterprise Microsoft Visual Studio 2008 Microsoft SQL Server 2005 Express Edition

Course Files
There are files associated with the labs in this course. The lab files are located in the folder E:\Labfiles on the student computers.

Classroom Setup
Each classroom computer will have the same virtual machine configured in the same way. The virtual machines do not need to be connected to a network.

Course Hardware Level


To ensure a satisfactory student experience, Microsoft Learning requires a minimum equipment configuration for trainer and student computers in all Microsoft Certified Partner for Learning Solutions (CPLS) classrooms in which Official Microsoft Learning Product courseware is taught. This course requires that you have a computer that meets or exceeds hardware level 5, which specifies a 2.4-gigahertz (GHz) (minimum) Pentium 4 or equivalent CPU, at least 2 gigabytes (GB) of RAM, 16 megabytes (MB) of video RAM, and a 7200 RPM 40-GB hard disk.

Getting Started with ADO.NET 3.5

1-1

MCT USE ONLY. STUDENT USE PROHIBITED

Module 1
Getting Started with ADO.NET 3.5
Contents:
Lesson 1: Introduction to ADO.NET 3.5 Lesson 2: Connecting to a Database and Retrieving Data 1-3 1-7

Lesson 3: Best Practices for Managing Connections and Performing Queries 1-15 Lab: Connecting to a Database and Retrieving Data 1-22

1-2

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Overview

ADO.NET is a collection of Microsoft .NET Framework classes that provide data access services for relational, XML, and application data. These classes abstract the data access through strongly typed data provider classes or through generic interfaces and classes. ADO.NET also provides data binding classes for Microsoft ASP.NET, Windows Forms applications, and Windows Presentation Foundation (WPF) applications. Microsoft Visual Studio 2008 development system provides designers for creating data access controls. This module describes how to use ADO.NET to connect to a database and read data from that database. The module also describes how to handle connection exceptions.

Getting Started with ADO.NET 3.5

1-3

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 1

Introduction to ADO.NET 3.5

ADO.NET is a collection of classes that connect to a database, perform actions on the database, and retrieve data from the database. A collection of such classes is named a data provider and is used to access data from a specific data source. In addition to the fundamental classes for accessing data through a data source, the .NET Framework also provides language features and class libraries that use ADO.NET to further abstract data access.

1-4

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

What Is ADO.NET 3.5?

Key Points
ADO.NET is a collection of classes that enables you to access data in a data source. A data provider is a collection of ADO.NET classes that enable you to access data from a specific data source. ADO.NET provides classes that access data through disconnected datasets and also supplies data binding to controls. Question: When you would use data through a data provider connection, and when would you use disconnected data?

Getting Started with ADO.NET 3.5

1-5

MCT USE ONLY. STUDENT USE PROHIBITED

.NET Framework Data Providers

Key Points
ADO.NET includes .NET Framework data providers that enable you to connect to a database, execute commands, and retrieve results. The .NET Framework data providers create a minimal layer between the data source and your code, which increases performance and does not sacrifice functionality.

1-6

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

ADO.NET 3.5 Technologies and Techniques

Key Points
ADO.NET 3.5 is a collection of classes that is part of the .NET Framework library. In addition, Visual Studio 2008 provides tools that use ADO.NET classes in your code, and Visual C# and Visual Basic have language features for embedding data access in code. In addition, Visual Studio 2008 designers generate ADO.NET code for you.

Getting Started with ADO.NET 3.5

1-7

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 2

Connecting to a Database and Retrieving Data

This lesson shows how to create a connection to a data source, issue a command, and then retrieve the data by using typed classes for the SQL Server data provider.

1-8

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Connecting to a Database

Key Points
To create a connection, you use one of the connection classes that implement IDbConnection and supply a connection string. To create the connection, you then call Open. Because connection objects hold limited resources, after you finish using a connection object, you must release those resources. To do this, you can call the Dispose method on the object to release it. You can also call the Close method or use the object in a Using statement (Visual Basic) or a using statement (Visual C#). Question: Why is the Using statement important, and what problems might you experience when you use it?

Getting Started with ADO.NET 3.5

1-9

MCT USE ONLY. STUDENT USE PROHIBITED

Handling Connection Exceptions

Key Points
Two types of exceptions can be generated when you open a connection: InvalidOperationException exception object is generated by the data provider on the client computer and SqlException exception object contains errors that are generated by the data source on the server. Question: Can you identify some of the error conditions that are returned through SqlException exception object?

1-10

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Executing a Query and Retrieving the Results

Key Points
To retrieve data from a database, you must create a command object, initialize it with information about the command, and then execute the command. If the command returns results, you obtain a resultset through a DbDataReader object (for the SQL Server data provider this is a SqlDataReader object). To populate the DbDataReader object with the next row, you call the Read method, and then you can call members to obtain the columns of this row. You must close the DbDataReader object after you finish using it. Question: Why do you think it is important that you close the DbDataReader object after you finish using it?

Getting Started with ADO.NET 3.5

1-11

MCT USE ONLY. STUDENT USE PROHIBITED

Mapping SQL Server Data Types to .NET Framework Types

Key Points
Data sources have their own data types, and when you execute a command, the results that are returned use those data types. To make data useful for your code, it must be converted into .NET Framework data types. The data provider classes derived from the DbDataReader and DbParameter classes perform these conversions for you. Question: Why do data sources have different data types?

1-12

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Handling Exceptions When Retrieving Data

Key Points
The SqlCommand command is not executed until the Read method is called the first time, so if there is an error in the command, you receive these only when the Read method is called. If you perform an asynchronous call, you must open the SQL Server connection specifically to support asynchronous calls; however, if you not do this, the exception occurs only when the first asynchronous call is attempted on a data reader object. You receive errors from the data source in a SqlException exception object, which has a collection of SqlError objects, one for each SQL Server error generated. Question: When you execute a command, at what point in your code may exceptions be thrown?

Getting Started with ADO.NET 3.5

1-13

MCT USE ONLY. STUDENT USE PROHIBITED

Disconnecting from a Database

Key Points
A connection object holds a connection to the data source. The data source connection is a limited resource; therefore, you should maintain this connection for as little time as necessary. To do this, you should ensure that after you finish using a connection, you call the Close method. Question: What is the difference between the Dispose and Close method? When would you use each one?

1-14

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Connecting to a Database and Retrieving Data

Getting Started with ADO.NET 3.5

1-15

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 3

Best Practices for Managing Connections and Performing Queries

ADO.NET provides additional features to improve how you connect to a database and access data in that database. You can: Store the connection string in a configuration file for better maintainability. Use connection pooling for more efficient use of connections. Use asynchronous calls to ensure responsiveness. Perform commands that use parameters and commands that return single values. Write generic data access code.

1-16

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Storing Connection Strings in a Configuration File

Key Points
The connection string determines which server and which database you connect to, so if you hard code this into your application, the database cannot be renamed, nor can you move the database to another computer. You can store the connection string in a separate file. Question: What are the advantages and disadvantages of using a configuration file?

Getting Started with ADO.NET 3.5

1-17

MCT USE ONLY. STUDENT USE PROHIBITED

Managing Database Connections

Key Points
Database connections are expensive resources to create. If your application uses many connections, it makes sense to reuse them. To cut down on the time taken to create connections, the SQL Server data provider uses a connection pool. When you create a connection, it is put into the pool, and when your code closes a connection, the connection is not closed; instead, the entry in the pool is marked as free so that it can be reused. The best way to use pooled connections is to open connections as late as possible and close them as early as possible. Question: What resources do you think are consumed by database connections?

1-18

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Executing Long-Running Queries Asynchronously

Key Points
Commands that are involved with an inter-process call may also involve a call to another computerthis takes time and it causes the thread to block until the command completes. This means that the calling thread cannot do any work, which is catastrophic if the calling thread is the main thread in a Windows Forms application because it prevents Windows messages from being processed. You can prevent this from happening by calling the command asynchronously; to do this, you create a connection that supports asynchronous calls. Question: What happens to your Windows Forms application if Windows messages are not handled? Question: Why would you use the SQL Server asynchronous methods instead of calling a delegate asynchronously?

Getting Started with ADO.NET 3.5

1-19

MCT USE ONLY. STUDENT USE PROHIBITED

Executing Single-Value Queries Efficiently

Key Points
It is important that you close various data provider objects, such as the connection object and the data reader object. If the command returns a single (or no) value, it is easy to forget to close objects like the data reader. The DbCommand class has methods that wrap the ExecuteReader method so that it hides the DbDataReader object and ensures that this object is closed before the wrapper method returns. Question: What examples of commands can you think of that only return a single value?

1-20

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Creating and Executing Parameterized Commands

Key Points
Parameterized commands are useful for two reasons. First, if you call a parameterized command several times, data sources can recognize these as being the same command and optimize its execution. Second, they help to prevent SQL injection attacks. Question: When are you likely to use parameterized commands?

Getting Started with ADO.NET 3.5

1-21

MCT USE ONLY. STUDENT USE PROHIBITED

Writing Provider-Independent Code in ADO.NET

Key Points
Each data provider must supply a DbProviderFactory class that you can use to create data provider objects for the data provider. You use references to the provider-independent abstract base classes and so that your code is generic even though the actual objects are specific to the data provider. Question: Under what circumstances would data provider agnostic data access code be used?

1-22

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Lab: Connecting to a Database and Retrieving Data

Exercise 1: Connecting to a Database


Scenario
You are a developer for the Medical Clinic Management System for Contoso, Ltd. The Contoso Clinic Management System is a healthcare system for hospitals and clinics that run specialist practices. The clinic must organize a set of consultants and equipment to service patient needs. Patients are referred to the clinic from their Family Practitioner or General Practitioner. The system supports both the management of appointments and the management of patient information. In this exercise, you will develop the code to connect to a database. The main tasks for this exercise are as follows: 1. 2. 3. Start the 6464A-LON-DEV-01 virtual machine and log on as Student. Open and review the project. Add a connection string to the configuration file.

Getting Started with ADO.NET 3.5

1-23

MCT USE ONLY. STUDENT USE PROHIBITED

4. 5. 6.

Add a data access class to the project. Implement the GetConnection method. Build and run the project.

Task 1: Start the 6464A-LON-DEV-01 virtual machine and log on as Student


1. 2. Open the Virtual Server Remote Control Client and double-click 6464A-LONDEV-04. Log on to 6464A-LON-DEV-04 as Student using the password Pa$$w0rd.

Task 2: Open and review the project


1. 2. Click Start, point to All Programs, point to Microsoft Visual Studio 2008, and then click Microsoft Visual Studio 2008. In Microsoft Visual Studio, open the ContosoMedical project from the E:\Labfiles\Starter\VB\ContosoMedical folder (if you are using Microsoft Visual Basic development system) or E:\Labfiles\Starter\CS\ContosoMedical folder (if you are using Microsoft Visual C# development tool). In Solution Explorer, open all the projects and examine their contents. The ClinicAdminClient project is a Windows Forms project with a single form that enables you to retrieve doctor names from the database. The ContosoMedicalDatabases project contains scripts for creating the database. These are here for your information only; the database is already installed on the computer. The ContosoMedicalUtilities project is a library project that contains the code to access the database.

3.

4.

In Solution Explorer, under the ClinicAdminClient project, double-click ClinicAdminForm.vb (Visual Basic) or ClinicAdminForm.cs (Visual C#) to open the form in the forms designer. Review the form: The Get Count button gets a count of how many doctors are in the database.

5.

1-24

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

The Show Doctors button gets either all doctors or the doctors that have a particular specialty. The specialtyTextBox enables the user to request information for doctors that have a particular specialty. The doctorsListBox shows the list of doctors retrieved when the user clicks Show Doctors.

Task 3: Add a connection string to the configuration file


1. In Solution Explorer, under the ClinicAdminClient project, open the project Properties. On the Settings tab, add a (Connection string) setting with the values in the following table (the values are single lines).
Value ContosoMedicalDBConnectionString Data Source=.\SQLEXPRESS; Initial Catalog=ContosoMedicalDB; Integrated Security=true

Column Name Value

2.

Save the configuration values.

Note: Saving the values adds an app.config file to the project with the connection string you just added; however, the wizard gives the value a name that enables it to be used with the My.Settings (Visual Basic) or Properties.Settings (Visual C#) class. You will not use these classes, so to make the code easier to read, you should rename the value name.

3.

Open the app.config file in the editor. Check that the designer has added a <connectionStrings> element and, below that, there is an <add> element with the values that you entered in step 5 of Task 2. Change the name attribute to ContosoMedicalDBConnectionString. Save the changes.

4. 5.

Task 4: Add a data access class to the project


1. In Solution Explorer, under the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#) to open the file in the editor.

Getting Started with ADO.NET 3.5

1-25

MCT USE ONLY. STUDENT USE PROHIBITED

Note: The project file is empty (Visual Basic) or has an empty namespace named ContosoMedicalUtilities (Visual C#). You will add the skeleton code for this class from an existing file.

2.

Copy the code from Ex1_Task4.txt (in the E:\Labfiles\Starter\VB for Visual Basic or E:\Labfiles\Starter\CS for Visual C#) into the ContosoMedicalDAC source file.

Task 5: Implement the GetConnection method


1. 2. 3. In the ContosoMedicalUtilities project, add a reference for the System.Configuration assembly. In the ContosoMedicalDAC source file, add a statement so that you can use System.Configuration classes without a fully qualified name. In the GetConnection method, add code that gets the connection string from the configuration file: Use the ConnectionStrings collection on the ConfigurationManager class to access the ContosoMedicalDBConnectionString value. Use this connection string to initialize a SqlConnection object and return this object from the function.

Task 6: Build and run the project


1. Build the project and run it.

Note: The ContosoMedicalDC.GetAllDoctors method that you copied in Task 4 has been implemented to call GetConnection so that you can test your code. The method does nothing else.

2.

Click Show Doctors and verify that no exceptions are thrown.


Results: After this exercise, you should have created a project that compiles correctly and can call GetConnection without throwing an exception.

1-26

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 2: Executing a Simple Query


Scenario
In this exercise, you will add code to query the database for the number of doctors in the database. The doctor information is held in the Doctors table, so to get the number of doctors, the code should query for the number of rows in this table. The main tasks for this exercise are as follows: 1. 2. 3. Implement the GetNumberOfDoctors method. Implement the handler for the Get Count button. Build and run the project.

Task 1: Implement the GetNumberOfDoctors method


1. In Solution Explorer, open the Data Access Component file and scroll down to the GetNumberOfDoctors method. This method has only enough code so that it compiled in the last exercise. Add code to give result a value. The result value will be the return value from the following query:

2.

select count(*) from Doctors

Perform the following steps: a. b. c. Call the GetConnection method to get a connection. Create a command to execute the query. Execute the command by using the ExecuteScalar method.

d. Close the connection.

Task 2: Implement the handler for the Get Count button


1. In Solution Explorer, under the ClinicAdminClient project, double-click ClinicAdminForm.vb (Visual Basic) or ClinicAdminForm.cs (Visual C#) to open the form in the forms designer. Double-click the Get Count button to open the file in code view. The cursor is placed in the getDoctorCount_Click handler method.

2.

Getting Started with ADO.NET 3.5

1-27

MCT USE ONLY. STUDENT USE PROHIBITED

3.

This method already has a Try (Visual Basic) or try (Visual C#) block for the data access code. Within this block, add code to create an instance of the Data Access Component, call GetNumberOfDoctors, and show the returned result in a message box.

Task 3: Build and run the project


1. 2. Build and run the project. Verify that when you click the Get Count button, you get a message box and no exceptions occur.
Results: After this exercise, the Get Count button should show a dialog box with the number of doctors in the database.

Exercise 3: Executing a Query That Returns a Result Set


Scenario
In this exercise, you will implement code to query the database and return a rowset with all the doctors in the database. The main tasks for this exercise are as follows: 1. 2. 3. Implement the GetAllDoctors method. Implement the ShowAllDoctors method. Build and run the project.

Task 1: Implement the GetAllDoctors method


1. In Solution Explorer, open the source file for the Data Access Component and scroll to the GetAllDoctors method. The implementation in the method was provided so that you could test the results in Exercise 1, and because you do not need this code now, delete it. Implement the GetAllDoctors method to return a SqlDataReader object that is the result of the following query:

2.

select DoctorID, FirstName, LastName, Specialty from Doctors

1-28

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Perform the following steps: a. b. c. Call the GetConnection method to get a connection object. Call the ExecuteReader method so that the reader object closes the connection object (CommandBehavior.CloseConnection). Return the reader object from the method.

Task 2: Implement the ShowAllDoctors method


1. 2. Open the ClinicAdminClient form in the code editor and scroll down to the ShowAllDoctors method. This method already has a Try (Visual Basic) or try (Visual C#) block for the data access code. In this block, add code to create a Data Access Component and call GetAllDoctors. Iterate through all the results in the SqlDataReader object that is returned from the GetAllDoctors function and add each result to the list box as strings in the following format:

3.

[DoctorID]\tDr. FirstName LastName, Specialty

Note: For Visual C#, you use \t for the tab character. For Visual Basic, you use the Chr(9) function to insert the tab character into the string.

Task 3: Build and run the project.


1. 2. Build and run the project. Verify that when you click the Show Doctors button: No exceptions are thrown. On each line of the list box, there is the description of each doctor.

Results: After this exercise, you should have an application that can show all the doctors in the database in the list box.

Getting Started with ADO.NET 3.5

1-29

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 4: Executing a Query That Requires Parameters


Scenario
In this exercise, you will write code to execute a stored procedure in the database. The stored procedure will return all the doctors that have the specialty provided through a parameter. The main tasks for this exercise are as follows: 1. 2 3. 4. 5. Review the stored procedure. Review the Doctor class. Implement the GetDoctorsForSpecialty method. Implement the ShowDoctorsForSpecialty method. Build and run the project.

Task 1: Review the stored procedure


1. In Solution Explorer, open ContosoMedicalDatabases, open the Create Scripts node, and then double-click ContosoMedicalDB.dbo.uspGetDoctorsForSpecialty to open the stored procedure in the editor. Review the procedure: The procedure has one in parameter: @specialty. The procedure has one out parameter: @doctorCount. The procedure has a return value that is the number of doctors who have the provided specialty. The procedure performs a query for all the doctors who have the provided specialty.

2.

Task 2: Review the Doctor class


In Solution Explorer, under the ContosoMedicalUtilities project, open the Doctor.vb (Visual Basic) or Doctor.cs (Visual C#) and examine the code.

1-30

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Task 3: Implement the GetDoctorsForSpecialty method


1. In the code file for the data access component, scroll to the GetDoctorsForSpecialty method. Copy and paste the contents of the Ex4_Task2.txt file (E:\Labfiles\Starter\VB for Visual Basic or E:\Labfiles\Starter\CS for Visual C#) for the implementation of this method. Review the code you have just copied. This code: Obtains a connection from the GetConnection method. Creates a command to call the uspGetDoctorsForSpecialty stored procedure. Initializes the @specialty parameter with the specialty requested. Initializes the out parameter @doctorCount and return value parameter. Executes the command and uses the rowset to initialize a generic List of Doctor objects. Initializes the ByRef (out) parameters with return parameter from the command. Closes the connection.

2.

Task 4: Implement the ShowDoctorsForSpecialty method


1. In the code file for the ClinicAdminClient form, scroll down to the ShowDoctorsForSpecialty method and paste the contents of Ex4_Task3.txt (from E:\Labfiles\Starter\VB for Visual Basic or E:\Labfiles\Starter\CS for Visual C#). Review the code you have just copied. This code: Creates the data access component. Obtains a generic List of Doctor objects, the number of specialties, and the number of doctors with the requested specialty, by calling the GetDoctorsForSpecialty method. Iterates through the generic List and adds information about each doctor to the list box. Displays a message box with the specialty count and number of doctors who have the requested specialty.

2.

Getting Started with ADO.NET 3.5

1-31

MCT USE ONLY. STUDENT USE PROHIBITED

Task 5: Build and run the project


1. 2. Build and run the application. Verify that there are no exceptions and that the application works as expected: Click Show Doctors to fill the list box. Choose a specialty from this list and type this text into the Specialty text box. Click Show Doctors again and verify that the list box has a description of each doctor who has the specialty that you chose.

Results: After this exercise, the application should list the doctors who have a specialty that you provide.

1-32

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Review and Takeaways

Review Questions
1. Why was it important to make GetConnection a Private function? This method creates a connection object and returns it. A class invariant is that every method that calls the GetConnection function must close the connection. Every method in this class obeys this rule. If this function was made Public, you cannot guarantee that callers will close the connection. 2. In GetNumberOfDoctors, why was the connection closed in the Finally clause? The connection must be closed in this method, regardless of how the method completes. The Finally clause has code that is executed whenever code execution leaves the Try block, regardless of how that happens. So if the Try block has a Return, a GoTo, or even if an exception is thrown, the Finally block is still called.

Getting Started with ADO.NET 3.5

1-33

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Why was the SqlDataReader object created with the CloseConnection behavior in GetAllDoctors? The connection must be open when you access the SqlDataReader object, so you must close the connection after you finish using this object. The GetAllDoctors method returns the reader object, so this means that you cannot close the connection in this method. Instead, the CloseConnection behavior means that the SqlDataReader object closes the connection when the reader object is closed, which will happen in the method that calls the GetAllDoctors method.

Common Issues Related to Accessing Databases by Using ADO.NET


The following table lists some of the common problems that may occur when you use ADO.NET to access databases. For reasons why these errors occur, you must refer to relevant lessons in the module.
Issue Connection errors Troubleshooting tip Check that the connection string is correct. You might have a spelling mistake. Consider using the DbConnectionStringBuilder for your data provider. Check to see if you are closing connections and data readers after you finish using them. Consider using Max Pool Size. Check the command strings you are using, they may have spelling mistakes. Test query strings by using a tool such as sqlcmd. If a query has parameters, consider using a stored procedure.

Application memory usage problems

Problems retrieving data

Best Practices for Accessing Databases by Using ADO.NET


Supplement or modify the following best practices for your own work situations: Always open connections as late as possible and close them as early as possible. Design your code to use this principle. Use the Using construct or Finally clause to help you. Use the CloseConnection behavior if your function returns a DbDataReader. Always close a DbDataReader as soon as possible; the Using construct and Finally clause help with this.

1-34

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Consider writing your code so that it is data providerindependent by using DbProviderFactory and related classes. This means that if you choose to change your data source, the changes required in you code will be minimal.

Modifying Data by Using ADO.NET Commands

2-1

MCT USE ONLY. STUDENT USE PROHIBITED

Module 2
Modifying Data by Using ADO.NET Commands
Contents:
Lesson 1: Inserting, Updating, and Deleting Data Lesson 2: Managing Data Integrity and Concurrency Lab: Modifying Data by Using ADO.NET Commands 2-3 2-8 2-14

2-2

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Overview

Many applications perform operations to query and update data in a database. Often an application must perform several such operations as a single unit of work, so that either all the operations complete or none complete. This unit of work is called a transaction. ADO.NET provides command classes and transaction classes that enable you to perform these tasks. This module will introduce the commands to modify the database and the classes used to perform transactions.

Modifying Data by Using ADO.NET Commands

2-3

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 1

Inserting, Updating, and Deleting Data

This lesson describes the classes in ADO.NET that enable you to change the data in a database and how to handle errors that might be returned from the database.

2-4

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Creating and Executing Commands to Modify Data

Key Points
A command to modify data does not return a rowset; the only data that is returned is the number of rows affected by the command. To execute the operation, you create an ADO.NET command object, initialize the object with the command, and then execute it by invoking the ExecuteNonQuery method. Question: Why would you invoke the ExecuteNonQuery method instead of invoking the ExecuteReader or ExecuteScalar method?

Modifying Data by Using ADO.NET Commands

2-5

MCT USE ONLY. STUDENT USE PROHIBITED

Handling Exceptions When Modifying Data

Key Points
Your command might perform an action on the database that is invalid. The server returns an error as a SqlException exception that you can catch in your code. The Errors collection contains details about the errors. Question: When is an InvalidOperationException exception object thrown?

2-6

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Executing Long-Running Modifications Asynchronously

Key Points
If a command is likely to take a long time to perform, you should not execute the command on the main thread of a graphical application because this blocks all the processing of Windows messages. Such commands should be performed on a separate thread as an asynchronous command. Question: What visible effects are you likely to see if the main thread of a graphical application is blocked by the performance of a lengthy operation?

Modifying Data by Using ADO.NET Commands

2-7

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Inserting, Updating, and Deleting Data

2-8

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 2

Managing Data Integrity and Concurrency

Transactions are an important part of data access because they ensure data integrity. However, by their nature, transactions restrict access to data, so Microsoft SQL Server 2005 has settings that enable you to relax these restrictions according to the type of access operation that you want to perform. This lesson will explain how to create and use transactions effectively.

Modifying Data by Using ADO.NET Commands

2-9

MCT USE ONLY. STUDENT USE PROHIBITED

Overview of Transactions

Key Points
The Atomicity, Consistency, Isolation, Durability (ACID) properties are the classic description of the properties that all transactions should have: atomic, consistent, isolated, and durable. Question: What would happen if transactions are not used when transferring money from one bank account to another bank account and an error occurs before the second account is credited?

2-10

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Transactions and Concurrency

Key Points
In a multi-user system, more than one user may try to update a row. The concurrency model determines whether multiple users have concurrent access to the same row. Question: Can you identify tables that do not need concurrent access? Question: Can you identify tables that should always allow concurrent access?

Modifying Data by Using ADO.NET Commands

2-11

MCT USE ONLY. STUDENT USE PROHIBITED

SQL Server 2005 Isolation Levels

Key Points
Transactions are isolated items of work. However, complete isolation can affect the performance of your application if it runs more than one transaction at the same time on the same table. The isolation level allows you to relax isolation and enables you to improve concurrency. Question: Which of these isolation levels, which level gives the most concurrent access, and which level gives the most isolation?

2-12

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Best Practices for Implementing Transactions

Key Points
Depending on the isolation level used, a transaction locks data at some point, which consumes server resources that are deemed to be expensive. To use transactions efficiently, you should keep the transaction as short as possible. You can also choose an isolation level to improve concurrency. Question: Why should you keep the lifetime of a transaction as short as possible?

Modifying Data by Using ADO.NET Commands

2-13

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Managing Data Integrity and Concurrency

2-14

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Lab: Modifying Data by Using ADO.NET Commands

Exercise 1: Inserting, Updating, and Deleting Data in a Database


Scenario
You are a developer for the Medical Clinic Management System for Contoso, Ltd. The Contoso Clinic Management System is a healthcare system for hospitals and clinics that run specialist practices. The clinics must organize a set of consultants and equipment to service patient needs. The system supports both the management of appointments and the management of patient information. In this lab, you will develop the code to manage patient data in the database. You will write code to access patient data, insert new patient, update, and delete existing patient records. The main tasks for this exercise are as follows: 1. Start the 6464A-LON-DEV-02 virtual machine and log on as Student.

Modifying Data by Using ADO.NET Commands

2-15

MCT USE ONLY. STUDENT USE PROHIBITED

2. 3. 4. 5.

Access patient data. Insert a patient record. Update a patient record. Delete a patient record.

Task 1: Start the 6464A-LON-DEV-02 virtual machine and log on as Student


1. 2. Open the Virtual Server Remote Control Client and double-click 6464A-LONDEV-02. Log on to 6464A-LON-DEV-02 as Student using the password Pa$$w0rd.

Task 2: Access patient data


1. Open the ContosoMedical project: 2. 3. 4. 5. If you are using Microsoft Visual Basic development system, go to E:\Labfiles\Starter\VB\ContosoMedical. If you are using Microsoft Visual C# development tool, go to E:\Labfiles\Starter\CS\ContosoMedical.

In Solution Explorer, open the ContosoMedicalDatabases node, and then open the ContosoMedicalDB.dbo.Patients.SQL script. Familiarize yourself with the schema of the table created by this script. All the data in the Patients table is added and modified by using stored procedures. Familiarize yourself with the stored procedures in this project. Open the ClinicAdminClient form, click the Patients tab and familiarize yourself with the following controls on this form: There are buttons to retrieve a patient and to create a new patient. There are controls to provide information like the first name, last name, gender, and date of birth. There are buttons to insert, update, and delete database items according to the data in the controls. There is a picture box and a button to enable you to upload a picture.

2-16

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

6.

Implement the code for the Click event of the Get Patient button. This code retrieves the information for a patient by using the Patient ID and uses this data to update the controls on the form. To implement this method, paste the contents of the Ex1_Task2_getPatient_Click.txt file into the Click eventhandler method of the Get Patient button. The text file is located in one of the following folders. E:\Labfiles\Starter\VB (Visual Basic). E:\Labfiles\Starter\CS (Visual C#).

7.

In Microsoft Visual Studio 2008, in the ContosoMedicalUtilities project, open Patient.vb (Visual Basic) or Patient.cs (Visual C#). Note the following features in the Patient class: There are five properties that only provide get and set access to fields: PatientID, FirstName, LastName, Gender and DateOfBirth. There is a constructor that does nothing more than initializes the fields in the class.

8.

In the ContosoMedicalUtilities project, open ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#). This file contains data access code. The file contains all the code that you implemented in the last module, and also has four methods that you will implement in this lab.

9.

Implement the GetPatient method. The code for this method is in the Ex1_Task2_GetPatient.txt file. This code performs the following steps: a. b. c. It opens a database connection. It creates a command to execute the uspGetPatient stored procedure. The stored procedure has an in parameter, so the code initializes the parameter on the command object.

d. It calls the ExecuteReader to obtain a SqlDataReader object for the command. e. It reads the first and only row in the SqlDataReader object and uses the data to initialize the Patient object that is returned from the function.

10. Build and run the application. When the application starts: a. b. Click the Patients tab. In the Patient ID box, type 1

Modifying Data by Using ADO.NET Commands

2-17

MCT USE ONLY. STUDENT USE PROHIBITED

c.

Click Get Patient.

11. Verify that the following values are returned.


Control First name Last name Gender DoB Value Isabella Young The Female radio button is selected 31 December 1964

12. Close the application.

Task 3: Insert a patient record


1. 2. In the ContosoMedicalUtilities project node, open Patient.vb (Visual Basic) or Patient.cs (Visual C#) file and familiarize yourself with this class. In the ClinicAdminClient project, use the contents of the Ex1_Task3_insertPatient_Click.txt file to implement the Insert button Click handler. This code carries out these steps: a. b. It creates a new Patient object from the values in the controls on the form. It creates an instance of the data access component class and calls the InsertPatient method to write the data to the database and obtain the PatientID for the new patient.

Write the PatientID value into the Patient ID text box. 3. Open the Data Access Component source file and locate the starter implementation for the InsertPatient method. Paste the contents of the Ex1_Task3_InsertPatient.txt file as the implementation of this method. The code performs these steps: a. b. It opens a database connection. It creates a command to call the uspInsertPatient stored procedure.

2-18

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

4.

Add the following code to add the four input parameters of the command object that invokes the uspInsertPatient stored procedure:
Implement with patient.FirstName patient.LastName patient.Gender patient.DateOfBirth

Parameter @firstName @lastName @gender @dateOfBirth

5. 6. 7. 8. 9.

Add code to add an output parameter named @patientID to the command for the stored procedure. Write code to get the PatientID from the @patientID parameter. Build the project and confirm that there are no compiler errors. Run the project, and on the Patients tab, insert a new patient. Make a note of the returned Patient ID because you will use it in the following tasks. Close the application.

Task 4: Update a patient record


1. In the ClinicAdminClient project, use the contents of the Ex1_Task4_updatePatient_Click.txt file to implement the Update button Click handler. The code performs these steps: a. b. It creates a new Patient object from the values in the controls on the form. It creates an instance of the data access component class and calls the UpdatePatient method to write the data to the database and obtain the PatientID for the new patient. It writes the PatientID value into the Patient ID text box.

c. 2.

In the Data Access Component source file, the starter implementation for the UpdatePatient method is provided in the Ex1_Task4_UpdatePatient.txt file. This code performs these steps: a. b. It opens a database connection. It creates a command to call the uspUpdatePatient stored procedure.

Modifying Data by Using ADO.NET Commands

2-19

MCT USE ONLY. STUDENT USE PROHIBITED

c.

It initializes the parameters listed in the following table.


Implement with patient.PatientID patient.FirstName patient.LastName patient.Gender patient.DateOfBirth

Parameter @patientID @firstName @lastName @gender @dateOfBirth

d. It executes the command. 3. 4. Build the project and confirm that there are no compiler errors. Run the application and, on the Patients tab, retrieve the patient that you added in the last task. Use the number you obtained in the last task in the Patient ID control. Alter the patient data, and then click Update. Verify that the patient data is updated in the database.

5. 6.

Task 5: Delete a patient record


1. In the ClinicAdminClient project, use the contents of the Ex1_Task5_deletePatient_Click.txt file to implement the Delete button Click handler. The code performs these steps: a. b. 2. It creates a data access component and calls the DeletePatient method. If the patient is deleted from the database, it clears the controls on the form.

Use the contents of the Ex1_Task5_DeletePatient.txt file to implement the DeletePatient method in the Data Access Component. The code performs these steps: a. b. c. It opens a database connection. It creates a command to call the uspUpdatePatient stored procedure. It initializes the @patientID parameter of the uspUpdatePatient stored procedure with patient.PatientID.

2-20

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

d. It executes the command. e. If the patient is deleted from the database, it calls the uspArchivePatient stored procedure to add information about the deleted data to the database.

3. 4.

Build the project and confirm that there are no compiler errors. Run the application and, on the Patients tab, delete the patient that you added in the last task. Use the number you obtained in the last task in the Patient ID control. Verify that the patient is deleted in the database.
Results: After this exercise, you should have written code that retrieves, inserts, changes, and deletes patient data in the database.

5.

Exercise 2: Implementing Transactional Updates


Scenario
The DeletePatient method that you implemented in the last exercise deletes patient information from the Patients table and archives information about this patient in the ArchivedPatients table. This is an operation that should be performed under a transaction, because if it is not possible to archive the data in the ArchivedPatients table, the data should not be removed from the Patients table. In this exercise, you will change the DeletePatient method to use a transaction and test this code by using a special value for the patient name that will cause uspArchivePatient to fail. The main tasks for this exercise are as follows: 1. 2. 3. 4. Examine the ArchivedPatients table. Add transactional behavior to the DeletePatient method. Verify that the transaction commits if all of the operations succeed. Verify that the transaction rolls back if an error occurs.

Task 1: Examine the ArchivedPatients table


1. In the ContosoMedicalDatabases project, open the ContosoMedicalDB.dbo.ArchivedPatients.SQL script. Familiarize yourself with the ArchivedPatients table.

Modifying Data by Using ADO.NET Commands

2-21

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Open the ContosoMedicalDB.dbo.uspArchivePatient.SQL script and familiarize yourself with the uspArchivePatient stored procedure. This procedure checks whether the @fullName parameter is the value of Dummy Patient and, if it is, it raises an error.

Task 2: Add transactional behavior to the DeletePatient method


1. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#). Add transaction support to the command objects in the DeletePatient method: a. Declare a transaction reference at the top of the method.

[Visual Basic] Dim transaction As SqlTransaction = Nothing

[Visual C#] SqlTransaction transaction = null;

b. c.

After the connection opens, initialize the transaction object by calling BeginTransaction on the connection object. Use this transaction object to initialize the command object. Provide the transaction object as an additional parameter to the constructor of this SqlCommand object.

[Visual Basic] Dim command As New SqlCommand( _ "uspDeletePatient", connection, transaction)

[Visual C#] SqlCommand command = new SqlCommand( "uspDeletePatient", connection, transaction);

d. Do the same thing for the archiveCommand command object. 2. After the archiveCommand executes, commit the transaction if the command is successful and rollback the transaction if the command failed.

2-22

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Add an exception handler to roll back the transaction if any exceptions are thrown in the code.

Task 3: Verify that the transaction commits if all of the operations succeed
1. 2. 3. 4. Build the solution and confirm that there are no compiler errors. Run the application and on the Patients tab, add a new patient. Delete the patient that you just added. Test to see if the patient data was deleted by trying to retrieve the patient. Confirm that when you click Get Patient, a dialog box indicates that the patient ID is not recognized, which confirms that the record has been deleted successfully.

Task 4: Verify that the transaction rolls back if an error occurs


1. 2. Run the application again. On the Patients tab, add a new patient. Use the following values and make sure that you use the exact spelling and capitalization as given here (ignore the other controls). Make a note of the Patient ID.
Value Dummy Patient

Control First name Last name

3. 4.

Delete the patient that you just inserted. Verify that the Cannot archive Dummy Patient dialog box appears. Confirm that the patient data was not deleted by retrieving the data again from the database by clicking Get Patient.
Results: After this exercise, you should have implemented transactional semantics for the Delete button, so that either items are deleted and archived as one operation or do not happen at all.

Modifying Data by Using ADO.NET Commands

2-23

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 3: Executing Commands Asynchronously


Scenario
Operations that involve passing large amounts of data over the network take time, so such operations must not be performed on the user interface thread. In this exercise, you will perform a data operation that will take a long time: inserting and accessing bitmap images into the database. To prevent the operation affecting the user interface, you will implement the code to read and write bitmaps as asynchronous operations. The main tasks for this exercise are as follows: 1. 2. 3. 4. 5. Add the Asynchronous Processing flag to the connection string. Implement code to asynchronously upload a photograph for a patient. Verify that the application uploads photographs successfully. Implement code to asynchronously get a photograph for a patient. Verify that the application retrieves photographs successfully.

Task 1: Add the Asynchronous Processing flag to the connection string


1. 2. In the ClinicAdminClient project, open the App.config file in the code editor. Add the following code to the end of the connectionString value, and make sure there is a semicolon between the end of the existing string and the beginning of the new string.

Asynchronous Processing=true

3.

Save this file.

Task 2: Implement code to asynchronously upload a photograph for a patient


1. Open the ClinicAdminForm form in the Designer window, and then doubleclick the Upload New Photo button to open the uploadNewPhoto_Click method in the code editor.

2-24

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Paste the contents of the Ex3_Task2_uploadNewPhoto.txt file as the implementation of this method. The text file is located in one of the following folders. E:\Labfiles\Starter\VB\Ex3 (Visual Basic). E:\Labfiles\Starter\CS\Ex3 (Visual C#).

The uploadNewPhoto_Click method calls BeginSavePhoto on the Data Access Component (which you will implement later in this task). The BeginSavePhoto method is provided with a callback to the SavePhotoCallback method. 3. The SavePhotoCallback method is provided in the Ex3_Task2_SavePhotoCallback.txt file. Paste the contents of this method after the uploadNewPhoto_Click method. This method retrieves the result of the command and then calls the SavePhotoUI on the user interface thread by using the SavePhotoUIDelegate delegate. Use the contents of the Ex3_Task2_BeginSavePhoto.txt file to implement the BeginSavePhoto method in the Data Access Component. This method calls the uspSavePatientPhoto stored procedure asynchronously.

4.

Task 3: Verify that the application uploads photographs successfully


1. 2. 3. 4. 5. Build the solution and confirm that there are no compiler errors. Run the application. On the Patients tab, open the first patient; to do this, type 1 in the Patient ID control, and then click Get Patient. Click Upload New Photo, and in the Open File dialog box, select female.jpg in the E:\Labfiles\Starter folder. In the Open File dialog box, click OK to see the photograph, which will appear immediately on the form, and three seconds later you will see the Photo saved successfully dialog box, which indicates that the operation to write the data into the database completed.

Task 4: Implement code to asynchronously get a photograph for a patient


1. Open the code for the ClinicAdminForm form and locate the Click handler for the Get Patient button.

Modifying Data by Using ADO.NET Commands

2-25

MCT USE ONLY. STUDENT USE PROHIBITED

2.

After the method has initialized the form controls with the results from calling the GetPatient method on the Data Access Component, add the following line to read the photograph from the database, and use this code to initialize the photograph control on the form.

[Visual Basic] GetPhoto(Int32.Parse(patientID))

[Visual C#] GetPhoto(int.Parse(patientID));

3.

Paste the contents of the Ex3_Task4_GetPhoto.txt file after the getPatient_Click method. This file has the GetPhoto method and supporting methods. GetPhoto calls BeginGetPhoto on the Data Access Component. Implement this code with the contents of the Ex3_Task4_BeginGetPhoto.txt file. Review the code that you have just pasted: GetPhoto calls BeginGetPhoto on the Data Access Component by passing a delegate to GetPhotoCallback. BeginGetPhoto executes uspGetPatientPhoto asynchronously. When the stored procedure completes, the GetPhotoCallback method is called and harvests the results of the call. This method uses the data to update the user interface, which it has to do on the user interface thread, so it calls BeginInvoke by passing a delegate to GetPhotoUI. The GetPhotoUI method accesses the SqlDataReader object created as a result of the command, reads the binary data, and uses the data to update the photograph control.

4. 5.

Task 5: Verify that the application retrieves photographs successfully


1. 2. 3. Build the solution and confirm that there are no compiler errors. Run the application and click the Patients tab. Load the first patient; to do this, in the Patient ID text box, type 1 and then click Get Patient.

2-26

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

4.

The controls are updated immediately and show the values for the first patient. After three seconds the photograph appears.

Results: After this exercise, you should have implemented asynchronous reads and writes of data to the database. You should also have handled all user interface updates on the user interface thread.

Modifying Data by Using ADO.NET Commands

2-27

MCT USE ONLY. STUDENT USE PROHIBITED

Module Review and Takeaways

Review Questions
1. In the lab, why did you use BeginInvoke in the callback method? The callback method is called on the thread that executes the command asynchronously. This is not the user interface thread. The user interface can only be changed by the user interface thread; you do this by calling BeginInvoke by passing a delegate to the method that updates the user interface. 2. Why would you relax the isolation level of a transaction? If you use the most isolated level, rows used by the transaction are locked until the transaction completes. This has the effect of serializing operations so that they perform one after each other and, for a multi-user system, this affects the overall performance of the system. If you relax the isolation level, you can increase concurrency and prevent the blocking of users.

2-28

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Why make transactions isolated at all? If your application writes data to rows in the database, you must restrict some concurrency to make sure that the data that one user reads truly reflects the data in the row. You determine the concurrency model that is best for your application only by careful analysis of the application.

Best Practices
Supplement or modify the following best practices for your own work situations: Use transactions to make two or more operations atomic. Use the transaction isolation level to control concurrency. Keep the transaction time as short as possible. Integrate transaction rollback as part of your error handling.

Querying and Maintaining Data by Using DataSets

3-1

MCT USE ONLY. STUDENT USE PROHIBITED

Module 3
Querying and Maintaining Data by Using DataSets
Contents:
Lesson 1: Creating and Using a DataSet to Retrieve Data Lesson 2: Updating a Database by Using a DataSet Lesson 3: Using a DataSet in an Occasionally Connected Environment Lab: Using a DataSet to Retrieve and Modify Data 3-3 3-10 3-16 3-19

3-2

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Overview

ADO.NET provides extensive support for creating disconnected applications, if the application is not directly connected to a server for a source of data or for a middletier service. Mobile users who work with notebook computers are the primary users of disconnected applications. The primary class in disconnected applications is the DataSet class. A DataSet is an in-memory cache of tables, typically populated from a database. This module describes how to create a DataSet object, fill it with data, work with the data while disconnected from the database, and then reconnect to the database when you are ready to save the DataSet data.

Querying and Maintaining Data by Using DataSets

3-3

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 1

Creating and Using a DataSet to Retrieve Data

ADO.NET is a collection of classes that connect to a database, perform actions on the database, and retrieve data from the database. A collection of such classes is known as a data provider and is used to access data from a specific data source. In addition to the fundamental classes for accessing data through a data source, the Microsoft .NET Framework also provides language features and class libraries that use ADO.NET to further abstract data access.

3-4

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Overview of DataSets

Key Points
A DataSet object is an in-memory cache of data that is typically retrieved from a database. A DataSet can contain any number of DataTable objects. Each DataTable contains a collection of columns that define the schema of the table and a collection of rows that contain the data for the table. You can define relations and constraints between the DataTable objects in a DataSet to represent the corresponding relationships between tables in the database. Question: What tables and relations might you define for DataSet objects in your own applications?

Querying and Maintaining Data by Using DataSets

3-5

MCT USE ONLY. STUDENT USE PROHIBITED

Untyped and Typed DataSets

Key Points
The System.Data.DataSet class is an untyped DataSet class. To access tables and columns in an untyped DataSet, you must specify the index or string literal name of the table or column. If you specify an invalid index or string literal name, a runtime exception occurs. A typed DataSet is a class that you generate by using Microsoft Visual Studio wizards, and contains nested properties and classes that provide type-safe access to the tables and columns. If you specify an invalid table name or column name, you obtain a compile time error instead of a run time exception.

3-6

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Creating an Untyped DataSet

Key Points
ADO.NET 3.5 is a collection of classes that is part of the .NET Framework library. In addition, Visual Studio has designers that generate ADO.NET code for you.

Querying and Maintaining Data by Using DataSets

3-7

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Defining a Typed DataSet Class

3-8

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Retrieving Data into a DataSet

Key Points
When you create a typed DataSet class, Visual Studio generates TableAdapter classes that provide Fill methods to fill each table in the DataSet. If you are using an untyped DataSet, you can fill the DataSet by using a DataAdapter class, such as SqlDataAdapter. To specify the SQL query that will retrieve data from the database, you must set the SelectCommand property on the DataAdapter object. You can then invoke the Fill method on the DataAdapter object, which executes the SQL query and fills a table in the DataSet.

Querying and Maintaining Data by Using DataSets

3-9

MCT USE ONLY. STUDENT USE PROHIBITED

Accessing Data in a DataSet

Key Points
To access rows in a typed DataSet table, you use the Rows property to get a collection of rows and then access columns in each row by using type-safe properties. Alternatively, you can create a DataTableReader object on a typed or untyped DataSet table and then access columns by index or column name. To find a specific row in a typed DataSet table, you invoke the FindByXxx method on the table. The precise name of the method is generated by Visual Studio according to the name of the primary key column in the DataSet table. To select all the rows in a typed or untyped DataSet table that match a specified filter expression, you invoke the Select method on the table. The method returns an array of untyped DataRow objects that match the specified filter expression.

3-10

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 2

Updating a Database by Using a DataSet

This lesson shows how to modify data in a DataSet, validate the modifications, and then save the modified data back to the database. The lesson also describes how to resolve optimistic concurrency conflicts, which can occur if two or more users or processes attempt to make conflicting changes to data in the database.

Querying and Maintaining Data by Using DataSets

3-11

MCT USE ONLY. STUDENT USE PROHIBITED

Modifying Data in a DataSet

Key Points
To add a row to a typed DataSet table, you invoke the AddXxxRow method on the table. Another way to add a row to a typed or untyped DataSet table is to invoke the Add or InsertAt method on the DataTable Rows property. To permanently remove a row from a typed DataSet table, you invoke the RemoveXxxRow method on the table. Another way to permanently remove a row from a typed or untyped DataSet table is to invoke the Remove or RemoveAt method on the DataTable Rows property. To mark a row to be deleted from a typed or untyped DataSet table, you invoke the Delete method on a DataRow object. You can access the original value of data in a DataRow by specifying the DataRowVersion.Original enumeration value when you access a column.

3-12

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Validating Modified Data in a DataSet

Key Points
If you attempt to save a DataSet that contains erroneous rows, a run-time exception occurs. To avoid the exception, you should first determine whether the DataSet contains any erroneous data and then reject the erroneous rows before you save the DataSet.

Querying and Maintaining Data by Using DataSets

3-13

MCT USE ONLY. STUDENT USE PROHIBITED

Saving Modified Data to a Database

Key Points
When you create a typed DataSet class, the associated TableAdapter classes provide Update methods to save each table in the DataSet to the database. If you are using an untyped DataSet, you can fill the DataSet by using a DataAdapter class, such as SqlDataAdapter. To specify the SQL statement that you want to insert, update, or delete a row in the database, you must set the InsertCommand, UpdateCommand, and DeleteCommand properties on the DataAdapter object. You can then invoke the Update method on the DataAdapter object to execute the appropriate SQL statements to save the table modifications to the database.

3-14

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Resolving Optimistic Concurrency Conflicts

Key Points
Optimistic concurrency conflicts occur when you save a DataSet to the database, but the rows in the database have already been modified. ADO.NET DataSets enable you to detect optimistic concurrency conflicts and to handle them in one of the following ways: Force the current row to be saved and to overwrite the existing data in the database. Skip the current row and continue saving subsequent rows. Skip all the subsequent rows.

Question: When might you use each optimistic concurrency strategy in your own applications?

Querying and Maintaining Data by Using DataSets

3-15

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Updating a Database by Using a DataSet

3-16

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 3

Using a DataSet in an Occasionally Connected Environment

The ADO.NET DataSet class is designed to be used in occasionally connected environments if an application has intermittent access to the database. This lesson describes how you can store DataSet data locally in XML format while the database is unavailable and then repopulate the DataSet from XML data later.

Querying and Maintaining Data by Using DataSets

3-17

MCT USE ONLY. STUDENT USE PROHIBITED

Using a DataSet as a Cache in an Occasionally Connected Environment

Key Points
You can serialize the data in a DataSet object to an XML document. This is useful if you want to preserve the data between application invocations. The next time the application starts, you can repopulate the DataSet object from the XML document. The ability to serialize a DataSet as XML is also useful in distributed applications if you want to transmit a DataSet over a network to a remote client. To serialize a DataSet object as XML data, you invoke the WriteXml method on the DataSet object. To fill a DataSet object by using XML data, you invoke the ReadXml method on the DataSet object.

3-18

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Serializing and Deserializing a DataSet as XML

Key Points
When you serialize and deserialize XML data for a DataSet object, you specify the DiffGram format to preserve information about the data modifications in the DataSet.

Querying and Maintaining Data by Using DataSets

3-19

MCT USE ONLY. STUDENT USE PROHIBITED

Lab: Using a DataSet to Retrieve and Modify Data

Exercise 1: Creating a Typed DataSet


Scenario
You are a developer for the Medical Clinic Management System for Contoso, Ltd. The Contoso Clinic Management System is a healthcare system for hospitals and clinics that run specialist practices. The clinic must organize a set of consultants and equipment to service patient needs. In this exercise, you will create a typed DataSet to represent the following tables in the Contoso Medical database.
Table Doctors Description Contains information about all the doctors who are employed by the Contoso Medical Clinic. Contains information about all the patients registered at the Contoso Medical Clinic.

Patients

3-20

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Table Appointments

Description Contains appointment information. The Appointments table has foreign keys named DoctorID and PatientID, which identify the doctor and the patient for the appointment. The table also has a column named AppointmentDateTime that identifies the date and time of the appointment, and it has a column named Notes that contains notes entered by the doctor after the appointment takes place.

You will also define relations and constraints between the Doctors and Appointments tables and between the Patients and Appointments tables. You will use the typed DataSet in a Windows Forms application named AppointmentViewer, which enables a doctor to view appointments and to modify notes for an appointment.
Note: The database server name for this lab is .\SQLEXPRESS and the database name is ContosoMedicalDB.

The main tasks for this exercise are as follows: 1. 2. 3. 4. 5. Start the 6464A-LON-DEV-03 virtual machine and log on as Student. Create a typed DataSet. Add tables to the typed DataSet. Add relations and constraints to the typed DataSet. Review the typed DataSet class definition.

Task 1: Start the 6464A-LON-DEV-03 virtual machine and log on as Student


1. 2. Open the Virtual Server Remote Control Client and double-click 6464A-LONDEV-03. Log on to 6464A-LON-DEV-03 as Student using the password Pa$$w0rd.

Task 2: Create a typed DataSet


1. Open Microsoft Visual Studio 2008.

Querying and Maintaining Data by Using DataSets

3-21

MCT USE ONLY. STUDENT USE PROHIBITED

2.

If you are using Visual Basic, open the solution E:\Labfiles\Starter\VB\ContosoMedical\ContosoMedical.sln. If you are using Visual C#, open the solution E:\Labfiles\Starter\CS\ContosoMedical\ContosoMedical.sln. In the AppointmentViewer project, add a new DataSet named ContosoMedicalDataSet.xsd.

3.

Task 3: Add tables to the typed DataSet


1. Add a table named Doctors to the ContosoMedicalDataSet.xsd DataSet, that contains the ID and the full name of the doctor. Specify the following SQL statement to query the doctor details, but do not generate commands to insert, update, or delete doctors.

select DoctorID, FullName=FirstName + ' ' + LastName from Doctors

Verify that the DataSet designer displays a table named Doctors and an associated table adapter named DoctorsTableAdapter. 2. Add a table named Patients to the ContosoMedicalDataSet.xsd DataSet, that contains the ID, full name, gender, and date of birth of the patient. Specify the following SQL statement to query the patient details, but do not generate commands to insert, update, or delete patients.

select PatientID, FullName=FirstName + ' ' + LastName, Gender, DateOfBirth from Patients

Verify that the DataSet designer now displays a table named Patients and an associated table adapter named PatientsTableAdapter. 3. Add a table named Appointments to the ContosoMedicalDataSet.xsd DataSet, that contains all the appointment details.

3-22

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

When prompted, specify that you want Visual Studio to create new stored procedures to select, insert, update, and delete appointments. Provide the following SQL statement for the SELECT stored procedure.
select * from Appointments

Specify the following names for the stored procedures: Select: uspGetAppointments Insert: uspInsertAppointment Update: uspUpdateAppointment Delete: uspDeleteAppointment

Preview the SQL script that Visual Studio will use to generate the stored procedures. Verify that the uspUpdateAppointment and uspDeleteAppointment stored procedures perform optimistic concurrency tests that prevent the row from being updated or deleted if it has already been modified in the database. After you complete these steps, verify that the DataSet designer now displays a table named Appointments with an associated table adapter named AppointmentsTableAdapter. 4. Save ContosoMedicalDataSet.xsd.

Task 4: Add relations and constraints to the typed DataSet


1. Add a relation and foreign key constraint between the Doctors and Appointments tables in the ContosoMedicalDataSet.xsd DataSet, which represents the relationship between the DoctorID primary key in the Doctors database table and the DoctorID foreign key in the Appointments database table. Add a relation and foreign key constraint between the Patients and Appointments tables in the ContosoMedicalDataSet.xsd DataSet, which represents the relationship between the PatientID primary key in the Patients database table and the PatientID foreign key in the Appointments database table. Save ContosoMedicalDataSet.xsd.

2.

3.

Querying and Maintaining Data by Using DataSets

3-23

MCT USE ONLY. STUDENT USE PROHIBITED

Task 5: Review the typed DataSet class definition


1. In the AppointmentViewer project, open ContosoMedicalDataSet.Designer.vb (Visual Basic) or ContosoMedicalDataSet.Designer.cs (Visual C#) in the editor. Verify that the source file defines a ContosoMedicalDataSet class that contains the following strongly typed data table classes: 3. DoctorsDataTable PatientsDataTable AppointmentsDataTable

2.

Verify that the source file defines a namespace named AppointmentViewer.ContosoMedicalDataSetTableAdapters that contains the following strongly typed table adapter classes: DoctorsTableAdapter PatientsTableAdapter AppointmentsTableAdapter

Note: In Visual Basic, the source code specifies the namespace name as ContosoMedicalDataSetTableAdapters. This namespace is implicitly nested in the root namespace for the project, AppointmentViewer.

Results: After this exercise, you should have created a typed DataSet that contains tables named Doctors, Patients, and Appointments. You should also have defined relations and constraints between the Doctors and Appointments tables and between the Patients and Appointments tables.

Exercise 2: Retrieving Data into a DataSet


In this exercise, you will add code to the main form in the ApplicationViewer application to create a DataSet instance and to populate it from either the database or a local XML file. You will also add code to display a list of all the doctors in a DataGridView control and to display a list of appointments for a particular doctor and date in another DataGridView control.

3-24

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

The main tasks for this exercise are as follows: 1. 2. 3. 4. 5. Review the main form in the AppointmentViewer application. Create a typed DataSet instance. Populate the DataSet instance. Display all the doctors. Display appointments for a particular doctor and date.

Task 1: Review the main form in the AppointmentViewer application


1. 2. Open MainForm.vb (Visual Basic) or MainForm.cs (Visual C#) in the form designer. Review the following features in the form: The upper DataGridView control, doctorsGridView, will display all the doctors in the DataSet Doctors table. The lower DataGridView control, appointmentsGridView, will display the appointments for the currently selected doctor and date.

Task 2: Create a typed DataSet instance


1. 2. View the code for MainForm.vb (Visual Basic) or MainForm.cs (Visual C#). Locate the comment TODO: Import the namespace that contains the TableAdapter classes, and add code to import the AppointmentViewer.ContosoMedicalDataSetTableAdapters namespace. Locate the comment TODO: Create a typed DataSet instance, and add code to create a ContosoMedicalDataSet instance named _dataset.

3.

Task 3: Populate the DataSet instance


1. In the MainForm class, locate the InitDataSetFromLocalFile method. If a local XML file exists, the application invokes this method during initialization to fill the DataSet by using the data in the XML file. The XML file stores the DataSet data in DiffGram format. 2. Where indicated by the comment TODO: Fill the DataSet from a local XML file, add code to fill _dataset from the XML file specified by _xmlFileName.

Querying and Maintaining Data by Using DataSets

3-25

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Locate the InitDataSetFromDatabase method. If the local XML file does not exist, the application invokes this method during initialization to fill the DataSet from the database.

4.

Where indicated by the comments in the InitDataSetFromDatabase method, add code to fill the Doctors, Patients, and Appointments tables in the DataSet by using a DoctorsTableAdapter, PatientsTableAdapter, and AppointmentsTableAdapter respectively.

Task 4: Display all the doctors


1. 2. In the MainForm class, locate the MainForm_Load method. Where indicated by the comment TODO: Display all doctors, add code to iterate through all the rows in the DataSet Doctors table, and add each doctor to the doctorsGridView control.

Tip: To add a row to the grid view, invoke the doctorsGridView.Rows.Add method. To display the DoctorID and FullName properties for the doctor, pass two parameters into the method.

3.

Build and run the application. Verify that the Appointment Viewer window displays a list of doctors in the upper DataGridView control.

4.

Close the Appointment Viewer window and return to Visual Studio.

Task 5: Display appointments for a particular doctor and date


1. In the MainForm class, locate the DisplayAppointments method. The application invokes this method when the user changes the currently selected doctor or date on the form. 2. Review the code at the start of the method, which performs the following tasks: a. b. c. Clears the contents of the appointmentsGridView control. Gets the doctor ID and the appointment data specified by the user. Creates a filer expression to select appointments for the specified doctor and date.

3-26

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Where indicated by the comment TODO: Select rows from the DataSet Appointments table, add code to select rows from the DataSet Appointments table by using the filter filter expression. Where indicated by the comment TODO: Display each appointment in appointmentsGridView, add code to display each appointment as follows: a. b. c. Iterate through the appointment rows that you obtained in step 3. Get the AppointmentID, PatientID, and AppointmentDateTime columns for the appointment row. Get the row in the Patients table that corresponds to the appointment.

4.

d. Add an item to the appointmentsGridView control, to display the appointment ID, patient ID, appointment time (as a short time), patient name, patient gender, and patient date of birth (as a short date.)
Note: The appointment ID and patient ID columns are not visible in the appointmentsGridView control. These columns are included to identify the appointment and patient for other code in the application, which you will write shortly.

5.

Build and run the application. Verify that the Appointment Viewer window displays a list of doctors in the upper DataGridView control.

6.

Select the following details in the Appointment Viewer window: Doctor: Ian Jenkins Date: Monday, June 02, 2008

Verify that the application displays the following appointments for the selected doctor and date:
11:00 11:30 12:00 11:30 AM, AM, PM, AM, Isabella Young, Justin Harris, Jenna Parker, Heidi Chandra, F, M, F, F, 12/31/1964 2/1/1966 12/5/1974 1/19/1985

Select the following details in the Appointment Viewer window: Doctor: Ian Jenkins Date: Tuesday, June 03, 2008

Querying and Maintaining Data by Using DataSets

3-27

MCT USE ONLY. STUDENT USE PROHIBITED

Verify that the application displays the following appointments for the selected doctor and date:
11:00 AM, Olivia Torres, 11:30 AM, Gabriel Chow, 12:00 PM, Fernando King, F, 9/27/1974 M, 12/3/1991 M, 1/2/1980

Select the following details in the Appointment Viewer window: Doctor: Chloe Young Date: Tuesday, June 03, 2008

Verify that the application displays the following appointments for the selected doctor and date:
11:00 AM, Derrick Alonso, M, 6/7/1984 2:00 PM, Meghan Gutierrez, F, 9/8/1978

7.

Close the Appointment Viewer window and return to Visual Studio.


Results: After this exercise, you should have created a DataSet instance, populated it from a database or from a local XML file, and displayed the data in a form.

Exercise 3: Modifying Data in a DataSet


In this exercise, you will enable the user to edit appointment notes. The Appointments table in the database contains a Notes column to hold this value persistently, and the Appointments table in the DataSet contains a similar column to hold this value temporarily in memory. When the user double-clicks an appointment in the AppointmentViewer application, the application will display the appointment notes in a new window. The user can modify the notes for an appointment, if appropriate, and then close the window. When the user closes the window, the application will store the updated appointment notes in the DataSet. The main tasks for this exercise are as follows: 1. 2. 3. Review the form to edit appointment notes in the AppointmentViewer application. Modify appointment notes in the DataSet. Build and test the application.

3-28

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Task 1: Review the form to edit appointment notes in the AppointmentViewer application
1. 2. 3. 4. Open EditNotesForm.vb (Visual Basic) or EditNotesForm.cs in the form designer. Verify that the form contains a text box named notesTextBox that enables the user to view and edit the notes for a particular appointment. View the code for the EditNotesForm class. Verify that the EditNotesForm class has a property named Notes that gets and sets the text value in the notesTextBox control.

Task 2: Modify appointment notes in the DataSet


1. 2. View the code for MainForm.vb (Visual Basic) or MainForm.cs (Visual C#). Locate the appointmentsGridView_DoubleClick method. The application invokes this method when the user double-clicks an appointment in the appointmentsGridView control. 3. Where indicated by the comment TODO: Lookup the appointment row in the DataSet Appointments table, add code to get the row in the Appointments table for the specified appointmentID value. Where indicated by the comment TODO: Set the Notes property on the form, add code to set the Notes property on the EditNotesForm instance to display the notes for the current appointment in the DataSet. Where indicated by the comment TODO: Store the appointment notes in the appointment row, add code to retrieve the Notes value from the form and assign it to the Notes property for the appointment in the DataSet.

4.

5.

Task 3: Build and test the application


1. 2. Build and run the application. Select the following details in the Appointment Viewer window: 3. Doctor: Ian Jenkins Date: Monday, June 02, 2008

In the lower DataGridView control, double-click the first appointment.

Querying and Maintaining Data by Using DataSets

3-29

MCT USE ONLY. STUDENT USE PROHIBITED

Verify that the Appointment Notes window displays No notes. 4. 5. Type new notes into the text box, and then click OK to return to the Appointment Viewer window. In the Appointment Viewer window, in the lower DataGridView control, double-click the first appointment again. Verify that the Appointment Notes window displays the notes that you entered in the previous step. 6. Close the Appointment Notes window and the Appointment Viewer window, and then return to Visual Studio.
Results: After this exercise, you should have modified the appointment notes in the Appointments table in the DataSet.

Exercise 4: Saving a DataSet and Resolving Conflicts


In this exercise, you will add code to enable the user to save DataSet changes to a local XML file or to the database. You will also add code to detect and resolve conflicts that might occur when saving the DataSet to the database. Such conflicts arise if two users attempt to edit and save appointment notes for the same appointment. When this happens, you will reject the changes made by the second user for that appointment, and then continue saving the remainder of the changes for the second user. The main tasks for this exercise are as follows: 1. 2. 3. 4. 5. Pass the DataSet instance into a form to enable the user to save the DataSet. Save the DataSet to a local XML file. Save the DataSet to the database. Verify that the application saves DataSet data. Verify that the application detects and resolves optimistic concurrency conflicts.

3-30

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Task 1: Pass the DataSet instance into a form to enable the user to save the DataSet
1. 2. Open CloseApplicationForm.vb (Visual Basic) or CloseApplicationForm.cs (Visual C#) in the form designer. Verify that the form contains four buttons. You will implement the following functionality for the buttons in the form:
Button Save Locally Description of functionality Save the entire DataSet to a local XML file as a DiffGram, which retains information about the modifications made by the user. Save the Appointments table in the DataSet to the database. Discard all the modifications made to the DataSet since it was downloaded from the database. Cancel the close-form operation.

Save to Database

Discard Changes

Cancel

3. 4.

View the code for the CloseApplicationForm class. Locate the comment TODO: Import the namespace that contains the TableAdapter classes, and add code to import the AppointmentViewer.ContosoMedicalDataSetTableAdapters namespace. Locate the comment TODO: Declare a typed DataSet variable, and add code to declare a ContosoMedicalDataSet instance named _dataset. Locate the comment TODO: Retain a reference to the DataSet instance, and modify the constructor to receive a parameter to initialize the _dataset instance variable. Open the code for MainForm.vb (Visual Basic) or MainForm.cs (Visual C#). Locate the MainForm_FormClosing method. The application invokes this method when the user closes the main form in the application.

5. 6.

7. 8.

9.

Implement the MainForm_FormClosing method by adding the code in the Ex4_Task1.txt file, located in the folder E:\Labfiles\Starter\VB (Visual Basic) or E:\Labfiles\Starter\CS (Visual C#).

Querying and Maintaining Data by Using DataSets

3-31

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Save the DataSet to a local XML file


1. 2. View the code for CloseApplicationForm.vb (Visual Basic) or CloseApplicationForm.cs (Visual C#). Locate the saveLocally_Click method, and add code to save the entire DataSet as an XML file in DiffGram format. Specify _xmlFileName as the name of the XML file.

Task 3: Save the DataSet to the database


1. Locate the saveToDatabase_Click method, and add code to save the DataSet Appointments table to the database as follows: a. b. Create an AppointmentsTableAdapter object. Handle the RowUpdated event on the data adapter for the AppointmentsTableAdapter object. Specify Adapter_RowUpdated as the name of the event handler method. Invoke the Update method on the AppointmentsTableAdapter object to save the DataSet Appointments table to the database.

c. 2.

Implement the Adapter_RowUpdated event-handler method so that it detects and resolves optimistic concurrency conflicts, as follows: a. b. Test the RecordsAffected property of the SqlRowUpdatedEventArgs parameter. If RecordsAffected is zero, it indicates that the attempt to update a row in the DataSet Appointments table failed. In this case, display the appointment notes in a message box, and specify that the row should be skipped.

3.

Locate the discardChanges_Click method, and add code to discard changes to the DataSet Appointments table.

Task 4: Verify that the application saves DataSet data


1. 2. Build and run the application. Select the following details in the Appointment Viewer window: Doctor: Ian Jenkins Date: Monday, June 02, 2008

3-32

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

3. 4. 5. 6.

In the lower DataGridView control, double-click the first appointment. Type new notes into the text box, and then click OK to return to the Appointment Viewer window. Close the Appointment Viewer window. In the Save Changes? dialog box, click Save Locally. In Visual Studio, in Solution Explorer, expand the AppointmentViewer project, expand the bin folder, and then expand the Debug folder. Verify that the Debug folder contains a file named ContosoMedicalDataSet.xml, which contains the DataSet data that you just saved. In Visual Studio, run the application again. Select the following details in the Appointment Viewer window: Doctor: Ian Jenkins Date: Monday, June 02, 2008

7. 8.

9.

In the lower DataGridView control, double-click the first appointment. Verify that the Appointment Notes window displays the notes that you provided earlier. This confirms that the application has saved and restored the DataSet data to the local XML file successfully.

10. Close the Appointment Notes window, and then close the Appointment Viewer window. In the Save Changes? dialog box, click Save to Database.

Task 5: Verify that the application detects and resolves optimistic concurrency conflicts
1. 2. In Visual Studio, run the application again. Modify appointment notes in the Appointment Viewer window, as follows: Select the doctor Ian Jenkins. Select the date Monday, June 02, 2008. Edit the notes for the first appointment.

Do not close the Appointment Viewer window yet. 3. Switch back to Visual Studio and start another instance of the Appointment Viewer application.

Querying and Maintaining Data by Using DataSets

3-33

MCT USE ONLY. STUDENT USE PROHIBITED

4.

Modify appointment notes in the new Appointment Viewer window, as follows: Select the doctor Ian Jenkins. Select the date Monday, June 02, 2008. Edit the notes for all the appointments.

5.

Switch to the first Appointment Viewer window, and then close the window. In the Save Changes? dialog box, click Save to Database. Verify that the application closes without any errors, which indicates that the application saved the data to the database successfully.

6.

Close the other Appointment Viewer window. In the Save Changes? dialog box, click Save to Database. Verify that the application displays a message box indicating that the application detected an optimistic concurrency error for the first appointment, because it has already been updated in the database. Verify that no other error messages appear, which indicates that the application saved the other appointments successfully.

7. 8.

In Visual Studio, start another instance of the Appointment Viewer application. Verify that the application displays the correct appointment notes, as follows: Select the doctor Ian Jenkins. Select the date Monday, June 02, 2008. Verify that the first appointment contains the notes that you supplied in the first Appointment Viewer window. Verify that the other appointments contain the notes that you supplied in the second Appointment Viewer window.

9.

Close the Appointment Viewer window.

10. Close Visual Studio.


Results: After this exercise, you should have saved a DataSet to a local XML file or to the database. You should also have detected and resolved optimistic concurrency errors that might occur when a DataSet is saved to the database.

3-34

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Review and Takeaways

Review Questions
1. What are the benefits of using typed DataSets instead of untyped DataSets? A typed DataSet class contains properties that provide type-safe access to the tables in the DataSet. Each table is represented by a separated class that provides type-safe access to the columns in the table. Each table also has an associated TableAdapter class that contains pre-configured Fill and Update methods to populate and save the DataSet table. 2. How do you load data into a typed DataSet table from a database and save the data back to the database later? To load data into a typed DataSet table from a database, you create an instance of the appropriate TableAdapter class and invoke the Fill method. To save the data back to the database, you invoke the Update method on the TableAdapter instance.

Querying and Maintaining Data by Using DataSets

3-35

MCT USE ONLY. STUDENT USE PROHIBITED

3.

List four ways to access rows in a typed DataSet table. Iterate through the Rows collection in the table. Create a DataTableReader object and use it to get each row in the table. Get a particular row by its primary key value, by invoking the FindBy<PrimaryKey> method. Get all of the rows that match a particular filter expression, by invoking the Select method.

4.

What is the difference between deleting a row and removing a row in a DataSet table? When you delete a row, you mark the row for deletion the next time the DataSet is saved to the database; the row is not physically removed until that time. When you remove a row, the row is physically removed immediately.

5.

What is a DiffGram? A DiffGram is an XML format that you can specify when you serialize a DataSet instance to XML or when you populate a DataSet instance from XML. The DiffGram format preserves information about which rows have been added, modified, or deleted in the DataSet.

Common Issues Related to Accessing Databases with ADO.NET


The following table lists some of the common problems that occur when you query and maintain data by using DataSets.
Issue Optimistic concurrency conflicts Troubleshooting tip Handle the RowUpdated event on the DataAdapter object. Implement a consistent strategy for handling optimistic concurrency conflicts, such as always rejecting row modifications that cause optimistic concurrency conflicts. If you add rows to a DataTable that contains automatically-generated column values, such as auto-increment primary keys, the values are not assigned until you save the DataSet to the database. Do not attempt to use these values in your application until you save the DataSet.

Automatic key generation

3-36

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Issue Saving dependent tables

Troubleshooting tip If a DataSet contains related tables, you might need to save the added rows, modified rows, and deleted rows separately for each table in the DataSet to preserve referential integrity in the database. Invoke the GetChanges method on a DataTable to get the subset of rows that have been added, modified, or deleted.

Best Practices for Querying and Maintaining Data by Using DataSets


Supplement or modify the following best practices for your own work situations: Use typed DataSets where possible, because they provide better compile-time type safety and are easier to use than untyped DataSets. If you do not need to save DataSet modifications to the database, do not generate methods to insert, update, or delete rows in the DataSet. Define separate tables in the DataSet to match the tables in the database. Do not join multiple database tables into a single table in the DataSet, unless the schema is simple or you require read-only access to the data.

Querying and Maintaining Data by Using LINQ

4-1

MCT USE ONLY. STUDENT USE PROHIBITED

Module 4
Querying and Maintaining Data by Using LINQ
Contents:
Lesson 1: Querying In-Memory Data by Using LINQ Query Expressions Lesson 2: Retrieving Data by Using LINQ to SQL Lesson 3: Modifying Data by Using LINQ to SQL Lab: Querying and Maintaining Data by Using LINQ to SQL 4-3 4-9 4-17 4-22

4-2

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Overview

Language-Integrated Query (LINQ) is a new technology that was introduced in the Microsoft .NET Framework 3.5 and which enables you to query and maintain different types of data consistently. This module describes how to use LINQ to access data in a collection of objects, a database, a DataSet object, or an XML document by using a uniform set of keywords and application programming interface (API) calls.

Querying and Maintaining Data by Using LINQ

4-3

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 1

Querying In-Memory Data by Using LINQ Query Expressions

This lesson describes how to define LINQ queries to access in-memory data in a collection of objects or in a DataSet object. The lesson introduces the basic syntax of LINQ queries and summarizes the new language features in Microsoft Visual Basic development system and Microsoft Visual C# development tool that can be used to support and simplify LINQ queries.

4-4

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Introduction to LINQ

Key Points
LINQ enables you to access data consistently, regardless of the origins of the data. Instead of having to use specific and disparate programming models to access data from different data sources, you can define LINQ queries that treat the data consistently. The .NET Framework enables you to define LINQ queries to access data in a collection of objects, a DataSet object, a Microsoft SQL Server database, an entity in an Entity Data Model, or an XML document.
Additional Information: For more information about Entity Data Models, see Module 5, " Implementing an Entity Data Model by Using the ADO.NET Entity Framework," of this course.

Querying and Maintaining Data by Using LINQ

4-5

MCT USE ONLY. STUDENT USE PROHIBITED

Defining a LINQ Query

Key Points
LINQ introduces a set of keywords in Visual Basic and Visual C# that enable you to define queries on an enumerable data collection, such as a collection of objects. A LINQ query specifies the following information: The enumerable collection that you want to query A filter expression that specifies the items that you are interested in Conditions that specify whether the results should be ordered or grouped The type of object that you want to obtain from the query

4-6

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Executing a LINQ Query and Accessing the Result

Key Points
You can use a For Each loop (Visual Basic) or a foreach loop (Visual C#) to iterate over the enumerable result set returned by a LINQ query. LINQ uses a deferred execution model, so the execution of the LINQ query is deferred until the application iterates over the result set. This means that exceptions might occur during iteration, not in the query itself. If you want to obtain the results of the query immediately, invoke a method such as ToList on the query object.

Querying and Maintaining Data by Using LINQ

4-7

MCT USE ONLY. STUDENT USE PROHIBITED

Querying Data in a DataSet by Using LINQ

Key Points
LINQ to DataSet enables you to execute LINQ queries against a DataTable in a DataSet object. You can obtain the results as a collection of DataRow objects or as a collection of objects of an anonymous type. Question: If you do not use LINQ, how do you access the data in a DataSet object?

4-8

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Defining and Executing LINQ Queries

Querying and Maintaining Data by Using LINQ

4-9

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 2

Retrieving Data by Using LINQ to SQL

LINQ to SQL enables you to access and modify data in a SQL Server database by using LINQ queries. To use LINQ to SQL, you define entity classes that map to tables in the database. You can then perform data operations by using the entity classes and object-oriented programming techniques instead of using ADO.NET data access classes such as SqlConnection, SqlCommand and SqlDataReader.

4-10

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Defining Entity Classes

Key Points
You define an entity class by following these steps: 1. 2. Define a class and map it to a database table by using the Table attribute. Define properties and map them to database columns by using Column attributes.

The Table and Column attributes are defined in the System.Data.Linq.Mapping namespace and are located in the System.Data.Linq assembly. Question: Why might the name of the entity class and its properties differ from the name of the database table and its columns?

Querying and Maintaining Data by Using LINQ

4-11

MCT USE ONLY. STUDENT USE PROHIBITED

Retrieving Data by Using an Entity Class

Key Points
To retrieve data by using an entity class, you create a DataContext object and invoke the GetTable generic method. The GetTable method returns a generic Table object containing entity objects from the database. The DataContext class and the Table generic class are defined in the System.Data.Linq namespace, and are located in the System.Data.Linq assembly.

4-12

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Joining Entity Classes by Defining Associations

Key Points
LINQ to SQL enables you to define associations between entity classes, to represent the relationships between tables in the database. You can then define LINQ queries that perform joins between associated entity classes. Question: What many-to-one relationships might you want to model as entity class associations in your own applications?

Querying and Maintaining Data by Using LINQ

4-13

MCT USE ONLY. STUDENT USE PROHIBITED

Navigating Associations

Key Points
When you define associations between entity classes, you can define and execute LINQ to SQL queries to navigate the association in either direction, as follows: From a parent entity to its collection of child entities. From a child entity to its parent entity.

4-14

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Defining Entity Classes Programmatically

Querying and Maintaining Data by Using LINQ

4-15

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Defining Entity Classes by Using the Object Relational Designer

4-16

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Fine-Tuning Queries

Key Points
You can fine-tune a LINQ query by using a DataLoadOptions object, as follows: Create a DataLoadOptions object. If you want to load rows from an associated table, invoke the LoadWith method on the DataLoadOptions object. If you want to filter the objects that are retrieved for a particular relationship, invoke the AssociateWith method on the DataLoadOptions object. Assign the DataLoadOptions object to the LoadOptions property of a DataContext object.

Querying and Maintaining Data by Using LINQ

4-17

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 3

Modifying Data by Using LINQ to SQL

LINQ to SQL enables you to insert, update, and delete objects in a table in a DataContext object. The changes are held in memory until you invoke the SubmitChanges method on the DataContext object to submit the changes to the database. When you save changes to the database, optimistic concurrency errors can occur if other users have made conflicting changes to the data in the database. The LINQ to SQL API enables you to catch these errors and either reject the changes or force them through to the database.

4-18

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Inserting, Updating, and Deleting Entity Objects

Key Points
LINQ to SQL enables you to insert, update, and delete entity objects in a DataContext table. The modifications are not saved to the database until you invoke the SubmitChanges method on the DataContext object, as described in the following topic.

Querying and Maintaining Data by Using LINQ

4-19

MCT USE ONLY. STUDENT USE PROHIBITED

Submitting Changes to the Database

Key Points
When you insert, update, or delete entities in a DataContext table object, the changes are made to the in-memory objects. To submit the changes to the database, you must invoke the SubmitChanges method on the DataContext object. If you perform multiple updates, enclose the updates in a TransactionScope.

4-20

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Handling Optimistic Concurrency Conflicts

Key Points
When you submit entity changes to the database, concurrency conflicts occur if other users have made conflicting changes to the data in the database. LINQ to SQL enables you to specify which entity columns to test for concurrency conflicts, whether to fail as soon as a concurrency conflict is detected or attempt to complete all updates, and how to resolve each conflict that is detected. Question: Why might you specify that an entity member should not be tested for optimistic concurrency conflicts? Question: Which strategy do you think you would use to resolve concurrency conflicts in your own applications?

Querying and Maintaining Data by Using LINQ

4-21

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Modifying Data by Using LINQ to SQL

4-22

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Lab: Querying and Maintaining Data by Using LINQ to SQL

Exercise 1: Defining Entity Classes


Scenario
You are a developer for the Medical Clinic Management System for Contoso, Ltd. The Contoso Clinic Management System is a healthcare system for hospitals and clinics that run specialist practices. In this lab, you will add LINQ to SQL support to a Windows Forms application named PrescriptionManager to enable the user to view and edit prescriptions for patients. In this exercise, you will use the Object Relational Designer in Microsoft Visual Studio 2008 development system to generate entity classes named Patient and Prescription to represent the following tables in the Contoso Medical database.
Database table Patients Description Contains information about all the patients registered at the

Querying and Maintaining Data by Using LINQ

4-23

MCT USE ONLY. STUDENT USE PROHIBITED

Database table

Description Contoso Medical Clinic.

Prescriptions

Contains the following information about prescriptions:

PrescriptionID. Primary key PatientID. Foreign key to a patient in the Patients table Description. Textual description of the prescription IssueDate. Date when the prescription was first issued RepeatCount. Number of times the prescription has been repeated.

You will define an association between the Patient and Prescription entity classes to represent the one-to-many relationship between patients and prescriptions. The main tasks for this exercise are as follows: 1. 2. 3. 4. Open the PrescriptionManager application. Generate LINQ to SQL entity classes. Define an association between entity classes. View the generated classes.

Task 1: Open the PrescriptionManager application


1. 2. Open Visual Studio 2008. If you are using Visual Basic, open the solution E:\Labfiles\Starter\VB\PrescriptionManager\PrescriptionManager.sln. If you are using Visual C#, open the solution E:\Labfiles\Starter\CS\PrescriptionManager\PrescriptionManager.sln.

Task 2: Generate LINQ to SQL entity classes


1. In the PrescriptionManager project, add a new LINQ to SQL project item named ContosoMedicalDataClasses.dbml. Verify that Visual Studio displays ContosoMedicalDataClasses.dbml in the Object Relational Designer window. 2. In Server Explorer, open a connection to the ContosoMedicalDB database on the local instance of Microsoft SQL Server 2005 Express Edition.

4-24

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Generate an entity class to represent the Patients database table by dragging the Patients table from Server Explorer to the Object Relational Designer surface. Verify that the Object Relational Designer displays a box named Patient. This is the entity class that corresponds to the Patients database table.

4. 5.

Delete the Photo property in the Patient entity class because the application does not need to access or view this information. Generate an entity class to represent the Prescriptions database table, by dragging the Prescriptions table from Server Explorer to the Object Relational Designer surface. Verify that the Object Relational Designer displays a box named Prescription. This is the entity class that corresponds to the Prescriptions database table.

Task 3: Define an association between entity classes


1. In the Object Relational Designer, define a one-to-many association between the Patient entity class and the Prescription entity class. The association must link the PatientID primary key in the Patient entity class to the PatientID foreign key in the Prescription entity class. Verify that the Object Relational Designer displays a one-to-many association between the Patient and Prescription entity classes. The association appears as an arrow from the Patient box to the Prescription box.

2.

Task 4: View the generated classes


1. 2. In Solution Explorer, open ContosoMedicalDataClasses.designer.vb (Visual Basic) or ContosoMedicalDataClasses.designer.cs (Visual C#). Locate the ContosoMedicalDataClassesDataContext class. This is a typed DataContext class that provides type-safe access to tables of Patient and Prescription entity objects. The following table describes some of the members in the ContosoMedicalDataClassesDataContext class.
Member Patients Prescriptions Description Gets a table of Patient entity objects Gets a table of Prescription entity objects

Querying and Maintaining Data by Using LINQ

4-25

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Locate the Patient class. This is an entity class that maps to the Patients table in the ContosoMedicalDB database. The following table describes some of the members in the Patient class.
Member _Prescriptions Description Instance variable that contains an EntitySet of Prescription entities for a patient Property mapped to the PatientID column Property mapped to the FirstName column Property mapped to the LastName column Property mapped to the Gender column Property mapped to the DateOfBirth column Property that gets or sets the prescriptions for the patient. This property is annotated with an Association attribute that describes the one-to-many association between the Patient and Prescription entity classes.

PatientID FirstName LastName Gender DateOfBirth Prescriptions

4.

Locate the Prescription class. This is an entity class that maps to the Prescriptions table in the ContosoMedicalDB database. The following table describes some of the members in the Prescription class.
Member _Patient Description Instance variable that contains an EntityRef that refers to the Patient entity for a prescription Property mapped to the PrescriptionID column Property mapped to the PatientID column Property mapped to the Description column Property mapped to the IssueDate column Property mapped to the RepeatCount column Property that gets or sets the patient for the prescription. This property is annotated with an Association attribute that describes the one-to-many association between the

PrescriptionID PatientID Description IssueDate RepeatCount Patient

4-26

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Member

Description Patient and Prescription entity classes.

Results: After this exercise, you should have generated entity classes for the Patients and Prescriptions tables in the ContosoMedicalDB database, and defined a one-tomany association between the entity classes.

Exercise 2: Retrieving Data by Using LINQ to SQL


In this exercise, you will use the Patient and Prescription entity classes to retrieve and display data from the database. You will enable the user to view prescriptions for a particular patient or for a particular period, as follows: When the PrescriptionManager application starts, you will use LINQ to SQL to get all of the patients from the database and display them in a DataGridView control. When the user clicks a patient record in the DataGridView control, you will execute a LINQ to SQL query to get the prescriptions for that patient. You will display the prescriptions in another DataGridView control. When the user requests prescriptions for a particular period, you will execute a LINQ to SQL query to get all of the prescriptions that were issued in that period. You will also use the association between the Prescription and Patient entity classes to retrieve the name of the patient associated with each prescription.

The main tasks for this exercise are as follows: 1. 2. 3. 4. Review the user interface in the application. Retrieve all of the patient records. Retrieve prescriptions for a particular patient. Retrieve prescriptions for a particular period.

Task 1: Review the user interface in the application


1. In Solution Explorer, in the PrescriptionManager project, open MainForm.vb (Visual Basic) or Mainform.cs (Visual C#) in the form designer.

Querying and Maintaining Data by Using LINQ

4-27

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Review the following features in the View by Patient tab in the form: The upper DataGridView control, patientsGridView, displays all of the patient records when the application starts. The lower DataGridView control, prescriptionsGridView, displays the prescriptions for a particular patient. The Repeat Prescriptions, Delete Prescriptions, and New Prescriptions buttons enable the user to modify prescription data. You will implement these features in the next exercise.

3.

Click the View by Date tab in the form, and review the following features: The date picker controls, fromDatePicker and toDatePicker, enable the user to specify a date range. When the user clicks Go, the application retrieves the prescriptions in the specified date range and displays them in the prescriptionsInPeriodGridView control.

Task 2: Retrieve all of the patient records


1. 2. In Solution Explorer, view the code for the MainForm form. In the Variables, initialization, and selection events code region, locate the TODO: Create typed DataContext object comment. Add code to create a new ContosoMedicalDataClassesDataContext object, and assign the new object to an instance variable named _db. In the View by Patient tab - display data code region, locate the DisplayPatients method. Where indicated by the TODO comment, add code to get and display all of the patient records from the database, as follows: a. b. Define a For Each loop (Visual Basic) or a foreach loop (Visual C#) to iterate over the entities in the _db.Patients table. On each iteration, create a string that contains the full name of the patient by concatenating the FirstName and LastName properties on the entity. Then add a row to the patientsGridView control, which contains the PatientID and full name of the patient.

3.

Note: To add a row to the patientsGridView control, invoke the patientsGridView.Rows.Add method.

4-28

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

4. 5. 6.

Build and run the application. Verify that the Prescription Manager window appears, and that the upper DataGridView control displays 18 patients. Close the Prescription Manager window.

Task 3: Retrieve prescriptions for a particular patient


1. In the MainForm source file, locate the DisplayPrescriptions method. The application invokes this method when the user highlights a patient on the form. The purpose of the method is to get all of the prescriptions for the highlighted patient and display them in the prescriptionsGridView control on the form. 2. Where indicated by the first TODO comment, add code to define a LINQ query to get the prescriptions for the highlighted patient. Use the following information to help you to define the LINQ query: Specify _db.Prescripitons as the data source for the query. Define a Where clause (Visual Basic) or a where clause (Visual C#) that compares the PatientID for prescriptions with the patientID local variable, so that the query only returns prescriptions for that patient.

3.

Where indicated by the second TODO comment, add code to display the prescriptions returned by the LINQ query, as follows: a. b. Define a For Each loop (Visual Basic) or a foreach loop (Visual C#) to iterate over the LINQ query that you defined in the previous step. On each iteration, add a row to the prescriptionsGridView control, which contains the PrescriptionID, Description, IssueDate, and RepeatCount properties for the prescription.

4. 5.

Build and run the application. Verify that the Prescription Manager window appears and that the upper DataGridView control displays 18 patient records. Also verify that the lower DataGridView control displays the prescriptions for the first patient. In the upper DataGridView control, highlight the second patient. Verify that the lower DataGridView control now displays the prescriptions for the second patient. Close the Prescription Manager window.

6.

7.

Querying and Maintaining Data by Using LINQ

4-29

MCT USE ONLY. STUDENT USE PROHIBITED

Task 4: Retrieve prescriptions for a particular period


1. In the MainForm source file, in the View by Date tab - display data code region, locate the go_Click method. The application invokes this method when the user clicks the Go button on the View by Date tab in the form, to get and display prescriptions in a particular period. Review the code that is already provided in the method. 2. Where indicated by the TODO comment, add the code provided in the Ex2_Task4.txt file that is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code performs the following tasks: a. b. Defines a LINQ query that gets the prescriptions in the specified date range, ordered by issue date. Iterates over the query results, and displays each prescription in the prescriptionsInPeriodGridView control. The code gets the name of the patient for each prescription by using the Patient.FirstName and Patient.LastName properties on the prescription entity.

3. 4. 5. 6. 7.

Build and run the application. In the Prescription Manager window, click the View by Date tab. View the prescriptions between January 1, 2008 and March 31, 2008. Verify that the application displays the prescriptions in the specified date range. View the prescriptions between April 1, 2008 and June 30, 2008. Verify that the application displays the prescriptions in the specified date range. Close the Prescription Manager window.
Results: After this exercise, you should have defined and executed LINQ to SQL queries to get information about patients and prescriptions from the ContosoMedicalDB database.

Exercise 3: Modifying Data by Using LINQ to SQL


In this exercise, you will enhance the PrescriptionManager application so that it enables the user to add, modify, and delete prescriptions. When the application submits the changes to the database, the application will check for optimistic concurrency conflicts. If such conflicts arise, the application will inform the user of

4-30

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

the conflict and will continue trying to submit the remaining changes to the database. The main tasks for this exercise are as follows: 1. 2. 3. 4. 5. 6. Get a specific Prescription entity. Update a Prescription entity. Delete a Prescription entity. Insert a Prescription entity. Save changes to the database. Test the application.

Task 1: Get a specific Prescription entity


1. 2. In the MainForm source file, in the View by Patient tab - modify data code region, locate the TODO: Define a GetPrescriptionEntity method comment. Add the code provided in the Ex3_Task1.txt file that is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code defines the GetPrescriptionEntity method, which performs the following tasks: a. b. Defines a LINQ query that gets the prescription that matches the specified prescription ID. Invokes the First method on the LINQ query to retrieve the first, and only, entity in the query result set.

You will use the GetPrescriptionEntity method in the following tasks to locate a Prescription entity that is to be updated or deleted.

Task 2: Update a Prescription entity


1. In the MainForm source file, locate the repeatPrescriptions_Click method. The application invokes this method when the user clicks Repeat Prescriptions on the form. The purpose of the method is to increment the

Querying and Maintaining Data by Using LINQ

4-31

MCT USE ONLY. STUDENT USE PROHIBITED

RepeatCount property for Prescription entities that are highlighted by the user. Review the code that has already been provided in the method. 2. Where indicated by the first TODO comment, add code to invoke the GetPrescriptionEntity method to get the Prescription entity for the prescriptionID. Where indicated by the second TODO comment, add code to increment the RepeatCount property on the Prescription entity.

3.

Note: At the end of the repeatPrescriptions_Click method, the application invokes the DoSave method. You will implement this method later in this exercise to submit the changes to the database.

4.

Build the application and verify that no errors or warnings occur.

Task 3: Delete a Prescription entity


1. In the MainForm source file, locate the deletePrescriptions_Click method. The application invokes this method when the user clicks Delete Prescriptions on the form. The purpose of the method is to mark a Prescription entity for deletion. Review the code that has already been provided in the method. 2. Where indicated by the first TODO comment, add code to invoke the GetPrescriptionEntity method to get the Prescription entity for the prescriptionID. Where indicated by the second TODO comment, add code to mark the Prescription entity for deletion from the _db.Prescriptions table.

3.

Task 4: Insert a Prescription entity


1. In the MainForm source file, locate the newPrescriptions_Click method. The application invokes this method when the user clicks New Prescriptions on the form. The purpose of the method is to enable the user to create new prescriptions for a patient. 2. Where indicated by the TODO comment, uncomment the code that creates and displays a NewPrescriptionsForm form.

4-32

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

3.

In Solution Explorer, open NewPrescriptionForm.vb (Visual Basic) or NewPrescriptionForm.cs (Visual Basic) in the form designer. The form enables the user to select a date and to create a series of prescriptions issued on that date. Each time the user clicks Add, the form creates another Prescription entity and adds it to the DataContext. When the user clicks Done, the application returns to the main form.

4. 5.

View the code for the NewPrescriptionForm form. In the NewPrescriptionForm source file, where indicated by the first TODO comment, add code to declare a ContosoMedicalDataClassesDataContext instance variable named _db. Where indicated by the second TODO comment, add the code provided in the Ex3_Task4_Constructor.txt file that is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

6.

The code defines a constructor that initializes the _patientID and _db instance variables. The form needs this information so that it can locate a particular Patient entity and then add Prescription entities to the DataContext. 7. Locate the add_Click method. The application invokes this method when the user clicks Add. Where indicated by the TODO comment, add the code provided in the Ex3_Task4_CreatePrescription.txt file that is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code creates and initializes a Prescription entity, marks it for insertion into the DataContext, and then displays the prescription description on the form.

Task 5: Save changes to the database


1. 2. Switch to the MainForm source file, and locate the Do Save method. Where indicated by the TODO: Submit changes to the database comment, add code to invoke the SubmitChanges method on the _db object. Pass ConflictMode.ContinueOnConflict into the method, so that the DataContext object attempts to complete all of the updates even if concurrency conflicts occur.

Querying and Maintaining Data by Using LINQ

4-33

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Where indicated by the TODO: Catch ChangeConflictException exceptions comment, add the code provided in the Ex3_Task5.txt file located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code performs the following tasks: a. b. Catches ChangeConflictException exceptions, which indicate that a concurrency conflict has occurred. Iterates over the collection of change conflicts and displays information about the object that caused a concurrency conflict; the members in conflict; and the current, original, and database values of each such member. Invokes the Resolve method to refresh the current values in memory with the latest values from the database.

c.

Task 6: Test the application


1. 2. 3. Build the application. Verify that no errors or warnings occur. Run the application. Update several prescriptions for the first patient, as follows: a. b. 4. In the lower DataGridView control, highlight several prescriptions, and then click Repeat Prescriptions. Verify that the application increases the RepeatCount for each highlighted prescription. Make a note of the prescriptions that you updated.

Delete several prescriptions for the first patient, as follows: a. b. In the lower DataGridView control, highlight several prescriptions, and then click Delete Prescriptions. Verify that the application deletes each of the prescriptions that you highlighted. Make a note of the prescriptions that you deleted.

5.

Add several new prescriptions for the first patient, as follows: a. b. Click New Prescriptions. In the New Prescriptions for PatientID 1 dialog box, in the Issue date control, select the current date.

4-34

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

c.

In the Description box, type a description for a new prescription, and then click Add.

d. Verify that the Added box displays the description that you just typed. This verifies that the application has created a new prescription. e. f. g. 6. 7. 8. Repeat the previous two steps several times to create several prescriptions. Click Done to return to the main form. Verify that the application displays the new prescriptions that you just added. Make a note of the new prescriptions.

Close the Prescription Manager window. In Visual Studio, on the Debug menu, click Start Without Debugging to start the application again. In the upper DataGridView control, click the first patient record. Verify that the lower DataGridView control shows the correct set of prescriptions for the patient, taking into account the prescriptions that you updated, deleted, and added earlier in this task. In the lower DataGridView control, highlight several prescriptions. Do not click any buttons to affect the prescriptions yet; you will do so later in this task.

9.

10. Switch back to Visual Studio. On the Debug menu, click Start Without Debugging to start another instance of the application. 11. In the upper DataGridView control, click the first patient. 12. In the lower DataGridView control highlight a subset of the prescriptions that you highlighted in step 9, and then click Repeat Prescriptions to update these prescriptions. 13. Repeat the previous step several times to update the RepeatCount property several times. 14. Close the second instance of the application, and return to the first instance of the application. 15. Click Repeat Prescriptions to update the highlighted prescriptions. Verify that the application detects and resolves optimistic concurrency conflicts as follows: For the prescriptions that you modified in the other instance of the application, the current instance of the application should display a message box, which indicates that an optimistic concurrency conflict has

Querying and Maintaining Data by Using LINQ

4-35

MCT USE ONLY. STUDENT USE PROHIBITED

occurred. The message box should indicate the current, original, and database values of the RepeatCount property and then update the value in the application with the value from the database. For the prescriptions that you did not modify in the other instance of the application, the current instance of the application should update the prescriptions successfully.

16. Close the Prescription Manager window. 17. Close Visual Studio.
Results: After this exercise, you should have implemented functionality to enable the user to insert, update, and delete entities by using LINQ to SQL, and to detect and resolve optimistic concurrency conflicts.

4-36

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Review and Takeaways

Review Questions
1. What are the benefits of using LINQ to SQL instead of using ADO.NET classes such as SqlConnection and SqlCommand? Using LINQ to SQL can be more productive for developers than using ADO.NET classes. Developers can define simple queries and delegate the complexities of database interactions to the LINQ to SQL provider. 2. What attributes do you use to designate a class as an entity class and to specify that a member maps to a database column? To specify that a class is an entity class, annotate the class with the Table attribute. To specify that a member maps to a database column, annotate the member with the Column attribute?

Querying and Maintaining Data by Using LINQ

4-37

MCT USE ONLY. STUDENT USE PROHIBITED

3.

How do you define an association between two entity classes? In the parent class, define an EntitySet instance variable and a property to get and set it. In the child class, optionally define an EntityRef instance variable and a property to get and set it. Annotate the properties in the parent and child classes with an Association attribute.

4.

How do you insert and delete entity objects into a DataContext? How do you submit the changes to the database? To insert an entity object into a DataContext, create an entity object and pass it as a parameter to the InsertOnSubmit method on the DataContext object. To delete an entity object from a DataContext, pass it as a parameter to the DeleteOnSubmit method on the DataContext object. To submit the changes to the database, invoke the SubmitChanges method on the DataContext object.

Common Issues Related to Accessing Databases with ADO.NET


The following table lists some of the common problems you may get when using LINQ to SQL.
Issue Optimistic concurrency conflicts Troubleshooting tip When you invoke the SubmitChanges method on the DataContext object, catch ChangeConflictException exceptions. For each entity object that causes a concurrency conflict, invoke the resolve method to specify if you want to force the current values through to the database, keep the current values in memory, or load the latest values from the database. If you add entity objects to a DataContext, any database-generated values are not assigned until you save the entity to the database. Do not attempt to use these values in your application until you save the changes. LINQ to SQL does not support cascaded delete operations. For example, if you delete a Patient entity, LINQ to SQL does not automatically delete all of the associated

Automatic key generation

Cascaded deletes

4-38

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Issue

Troubleshooting tip Patient entities. You must add code to perform the cascaded deletion manually.

Best Practices for Using LINQ to SQL


Supplement or modify the following best practices for your own work situations: Retain entity changes in memory for as short a time as possible. Submit the changes to the database as soon as possible to minimize the risk of concurrence conflicts with other users. Enclose updates in a transaction if appropriate, for example, to ensure all data is updated or no data updates.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-1

MCT USE ONLY. STUDENT USE PROHIBITED

Module 5
Implementing an Entity Data Model by Using the ADO.NET Entity Framework
Contents:
Lesson 1: Creating an Entity Data Model by Using the ADO.NET Entity Framework Lesson 2: Querying and Modifying Data by Using the ADO.NET Entity Framework Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework 5-3 5-9 5-17

5-2

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Overview

The ADO.NET Entity Framework enables you to create data access applications by programming against a conceptual application model instead of programming directly against a relational storage schema. The goal of the ADO.NET Entity Framework is to decrease the amount of code and maintenance that is required for data-oriented applications. This module describes how to create an Entity Data Model by using the ADO.NET Entity Framework and how to query and modify data by using the Entity Framework.
Note: The ADO.NET Entity Framework is a beta product at the time of writing, and some changes to the product might occur before its first full release.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-3

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 1

Creating an Entity Data Model by Using the ADO.NET Entity Framework

This lesson describes how to create an Entity Data Model (EDM) by using tools provided by the ADO.NET Entity Framework. An EDM contains a conceptual model that defines entity types that you use in your application and a storage model that describes how the data is stored in the database. The EDM also contains a mapping specification that connects the entity types in the conceptual model to the database metadata in the storage model.

5-4

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Overview of the ADO.NET Entity Framework

Key Points
The ADO.NET Entity Framework is a set of technologies that supports development of data-oriented software applications. The Entity Framework enables developers to work with data in the form of domain-specific objects and properties, such as customers and customer addresses, without having to consider the underlying database tables and columns where this data is stored. The ADO.NET Entity Framework reduces the amount of data access code in object-oriented data applications and services, and makes it faster to create object-oriented data applications and services from an existing database.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-5

MCT USE ONLY. STUDENT USE PROHIBITED

Entity Data Models

Key Points
An .edmx Entity Data Model file defines the following information: Conceptual model Storage model Mapping specification

5-6

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Defining an Entity Data Model

Key Points
The Entity Framework provides the tools that enable you to create and modify an EDM. The EMD can be created for a console, a Windows-based application or an ASP.NET application.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-7

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Creating an Entity Data Model

5-8

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Modifying an Entity Data Model

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-9

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 2

Querying and Modifying Data by Using the ADO.NET Entity Framework

The ADO.NET Entity Framework includes a component named Object Services that enables you to query and modify data in an Entity Data Model. This lesson describes the features provided by Object Services and introduces a number of techniques for using entities in your application.

5-10

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Overview of Object Services

Key Points
Object Services is a component of the Entity Framework that enables you to query, insert, update, and delete data, expressed as strongly typed objects that are instances of entity types. Object Services supports both Entity SQL and LINQ to Entities queries against types that are defined in an EDM. Object Services represents data from the data store as objects, and it propagates object changes back to the persisted data store. Object Services also provides facilities for tracking changes, binding objects to controls, and handling concurrency. Object Services is implemented by classes in the System.Data.Objects and System.Data.Objects.DataClasses namespaces.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-11

MCT USE ONLY. STUDENT USE PROHIBITED

Defining Object Queries

Key Points
The Entity Framework provides a generic class named ObjectQuery that enables you to execute queries against an EDM and return data as objects. The ObjectQuery class provides a set of query builder methods, such as Where and Include, that enable you to filter and shape the query results.

5-12

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Using LINQ to Entities in Object Queries

Key Points
LINQ to Entities enables you to define LINQ queries on the entities that are returned by an object query. In a typical scenario, an application defines an object query to retrieve data from the persistent data store into a collection of entities in memory, and then it uses LINQ to Entities to query the entities without requiring additional roundtrips to the database.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-13

MCT USE ONLY. STUDENT USE PROHIBITED

Using Entity SQL in Object Queries

Key Points
Entity SQL is an SQL-like language that is provided by the Entity Framework and enables you to query and manipulate rich graphs of objects that are based on the EDM.

5-14

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Modifying Entities

Key Points
The ObjectContext class provides methods that enable you to insert and delete entities in the cache of entities held in memory by the object context object. You can also locate existing entities and modify their property values in memory. To save entity changes to the persistent data store, you must invoke the SaveChanges method on the ObjectContext object and handle any concurrency errors that might occur.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-15

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Querying and Modifying Entities

5-16

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Binding Entities to Controls

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-17

MCT USE ONLY. STUDENT USE PROHIBITED

Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

Exercise 1: Creating an Entity Data Model


Scenario
You are a developer for the Medical Clinic Management System for Contoso, Ltd. The Contoso Clinic Management System is a healthcare system for hospitals and clinics that run specialist practices. In this exercise, you will define an Entity Data Model (EDM) to represent the Patients and Prescriptions tables in the ContosoMedicalDB database. In the other exercises in this lab, you will add code to the application to query and modify entities by using object queries and Entity SQL. The main tasks for this exercise are as follows: 1. 2. 3. Open the PrescriptionManager application. Generate an Entity Data Model. Define an association between the entities.

5-18

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

4.

Map the association between entities.

Task 1: Open the PrescriptionManager application


1. 2. Open Microsoft Visual Studio 2008. If you are using Visual Basic, open the solution E:\Labfiles\Starter\VB\PrescriptionManager\ PrescriptionManager.sln. If you are using Visual C#, open the solution E:\Labfiles\Starter\CS\PrescriptionManager \PrescriptionManager.sln.

Task 2: Generate an Entity Data Model


1. 2. In Solution Explorer, in the PrescriptionManager project, add a new ADO.NET EDM named ContosoMedicalModel.edmx. When the Entity Data Model Wizard dialog box appears, generate the EDM from the ContosoMedicalDB database on the local instance of SQL Server Express, and then add the Patients and Prescriptions tables to the EDM. Verify that Visual Studio displays the ContosoMedicalModel.edmx file in the EDM designer window and that the EDM contains boxes named Patients and Prescriptions. 3. 4. 5. In the designer, in the Patients entity, delete the Photo scalar property. The application does not require the photograph of the patient. In the Patients entity, set the Name and Entity Set Name properties to Patient, to indicate that the entity represents a single patient. In the Prescriptions entity, set the Name and Entity Set Name properties to Prescription, to indicate that the entity represents a single prescription.

Task 3: Define an association between the entities


1. 2. In the designer, right-click the upper section of the Patient box, point to Add, and then click Association. In the New Association dialog box, verify that the default options represent a one-to-many association between the Patient and Prescription entities, and then click OK.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-19

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Verify that the designer displays a one-to-many association between the Patient and Prescription entities. The association appears as a line between the Patient and Prescription boxes.

Task 4: Map the association between entities


1. 2. In the designer, right-click the PatientPrescription association, and then click Show in Mapping Details. In the Mapping Details - PatientPrescription window at the bottom of Visual Studio, expand the <Add a Table or View> list, and then click Prescriptions.

Note: When you map an association, you must select the table that contains the foreign keys for the association in the database. In this example, the Prescriptions database table contains foreign keys to the Patients database table, to identify the patient for each prescription.

3.

Verify that the Mapping Details - PatientPrescription window defines the following mapping information: For the Patient entity, the PatientID (Int32) entity property is mapped to the PatientID (int) column in the database table. For the Prescription entity, the PrescriptionID (Int32) entity property is mapped to the PrescriptionID (int) column in the database table.

4.

In the main designer window, in the Prescription entity box, delete the PatientID scalar property. The Prescription entity no longer needs the PatientID scalar property, because the Patient navigation property now defines the navigability from a Prescription entity to its associated Patient entity in memory.

5.

Build the solution, and verify that there are no compiler errors or warnings.
Results: After this exercise, you should have generated an EDM that represents the Patients and Prescriptions tables in the ContosoMedicalDB database, and defined a one-to-many association between the entities in the EDM.

5-20

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 2: Querying Entities in an Entity Data Model


In this exercise, you will add code to the application to query entities in the EDM, as follows: When the PrescriptionManager application starts, you will define an object query to get Patient entities for all of the patients in the database, and then bind the entities to a DataGridView control. When the user clicks a patient in the DataGridView control, you will define an object query to get the prescriptions for that patient. You will display the prescriptions in another DataGridView control.

The main tasks for this exercise are as follows: 1. 2. 3. Review the user interface in the application. Retrieve patients. Retrieve prescriptions.

Task 1: Review the user interface in the application


1. 2. In Solution Explorer, in the PrescriptionManager project, open MainForm.vb (Visual Basic) or Mainform.cs (Visual C#) in the form designer. Review the following features in the form: The upper DataGridView control, patientsGridView, will display all of the patients when the application starts. The lower DataGridView control, prescriptionsGridView, will display the prescriptions for a particular patient. The Repeat Prescriptions button will enable the user to modify selected prescriptions, by incrementing their RepeatCount property.

Note: For simplicity, the application does not enable the user to insert or delete prescriptions.

Task 2: Retrieve patients


1. Open the code file for the MainForm form.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-21

MCT USE ONLY. STUDENT USE PROHIBITED

2.

At the top of the source file, where indicated by the first TODO comment, import the EDM namespace that you generated in the first exercise. The namespace to import is as follows: Visual Basic: PrescriptionManager.ContosoMedicalDBModel Visual C#: ContosoMedicalDBModel

3. 4.

At the top of the source file, where indicated by the second TODO comment, import the System.Data.Objects namespace. In the MainForm class, locate the DisplayPatients method. The application invokes this method during startup, to display the patients in the patientsGridView control.

5.

Where indicated by the TODO comment, add the code provided in the Ex2_Task2.txt file located in the following folder: If you are using Visual Basic: E:\Labfiles\Starter\VB If you are using Visual C#: E:\Labfiles\Starter\CS

The code creates a ContosoMedicalDBEntities object and contains TODO comments that you will implement in the following steps. 6. 7. 8. 9. Where indicated by the TODO: Define an object query comment, define an ObjectQuery object to get all Patient entities from the database. Where indicated by the TODO: Bind the retrieved entities comment, bind the entities that are returned by the query to the patientsGridView control. Build and run the application. Verify that the Prescription Manager window appears and that the upper DataGridView control displays 18 patients.

10. Close the Prescription Manager window.

Task 3: Retrieve prescriptions


1. In the MainForm source file, locate the DisplayPrescriptions method. The application invokes this method when the user highlights a patient on the form. The purpose of the method is to get all of the prescriptions for the highlighted patient and display them in the prescriptionsGridView control on the form.

5-22

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Where indicated by the TODO comment, add the code that is provided in the Ex2_Task3.txt file, which is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code is complete and performs the following tasks: a. b. Creates a ContosoMedicalDBEntities object. Defines an object query to get Prescription entities for the highlighted patient. The Where method uses the syntax it.Patient.PatientID to get the Patient entity that is associated with the current prescription, and then it gets the PatientID property on the Patient entity. The Where method uses the PatientID property to retrieve prescriptions for a particular patient. Iterates over the Prescription entities that are returned by the object query, and displays the information in the prescriptionsGridView control.

c.

3. 4.

Build and run the application. Verify that the Prescription Manager window appears and that the upper DataGridView control displays 18 patients. Verify that the lower DataGridView control displays the prescriptions for the first patient. In the upper DataGridView, click the second patient. Verify that the lower DataGridView control displays the prescriptions for the second patient. Close the Prescription Manager window.
Results: After this exercise, you should have defined and executed object queries to get information about patients and prescriptions from the ContosoMedicalDB database.

5. 6.

Exercise 3: Modifying Entities in an Entity Data Model


In this exercise, you will enhance the PrescriptionManager application so that it enables the user to modify prescriptions. You will enable the user to select prescriptions for a patient and then increment the RepeatCount property on the prescriptions. The main tasks for this exercise are as follows: 1. Modify entities.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-23

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Test the application.

Task 1: Modify entities


1. In the MainForm source file, locate the repeatPrescriptions_Click method. The application invokes this method when the user clicks the Repeat Prescriptions button to repeat selected prescriptions. 2. Review the code that is already provided in the method. The code creates a string variable named prescriptionIDs that contains a list of all of the prescription IDs that the user highlighted. You will use this list of prescription IDs in an Entity SQL query later in this task. Where indicated by the TODO comment, add the code that is provided in the Ex3_Task1.txt file, which is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

3.

The code performs the following tasks: a. b. Creates a ContosoMedicalDBEntities object. Defines an Entity SQL string to get the highlighted Prescription entities. The WHERE and IN operators ensure that the query only retrieves the set of Prescription entities whose PrescriptionID is in the prescriptionIDs list.

4.

Where indicated by the TODO: Create an object query to get the requested prescriptions comment, define an ObjectQuery object to retrieve Prescription entities by using the Entity SQL string. Ensure that the query overwrites any local entity values with the latest values from the database. Where indicated by the TODO: For each Prescription entity, increase the RepeatCount comment, iterate over the Prescription entities that are returned by the object query. For each Prescription entity, increment the RepeatCount property. Where indicated by the TODO: Save the changes to the database comment, add code to save the object context changes to the database.

5.

6.

Task 2: Test the application


1. Build and run the application.

5-24

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

2.

In the Prescription Manager window, verify that the upper DataGridView control displays 18 patients. Verify that the lower DataGridView control displays the prescriptions for the first patient. Click some of the rows in the lower DataGridView control, and then click Repeat Prescriptions. Verify that the application shows the incremented repeat count for the prescriptions. Close the Prescription Manager window. In Visual Studio, on the Debug menu, click Run Without Debugging. In the Prescription Manager window, verify that the upper DataGridView control displays 18 patients. Verify that the lower DataGridView control displays the prescriptions for the first patient and that the repeat counts are the incremented values. Close the Prescription Manager window. Close Visual Studio.
Results: After this exercise, you should have modified entities and saved the changes back to the database.

3.

4. 5. 6.

7. 8.

Implementing an Entity Data Model by Using the ADO.NET Entity Framework

5-25

MCT USE ONLY. STUDENT USE PROHIBITED

Module Review and Takeaways

Review Questions
1. What information does an .edmx Entity Data Model file contain? The .edmx file defines the conceptual model, the logical model, and the mapping specification for the EDM. 2. How do you define an association between entities, and what information does the code generator add to the entity classes? In the EDM designer window, you right-click an entity, point to Add, and then click Association. You must verify the multiplicity at both ends of the association. When you define an association, the code generator adds a navigation property to each entity, to enable you to navigate the association programmatically. 3. What is an object context? An object context encapsulates the underlying connection to the database, so that you can execute object queries.

5-26

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

4.

When might you decide to use LINQ to Entities instead of executing a new object query? LINQ to Entities is useful when you have already executed an object query to retrieve a collection of entities and you want to obtain selective entities or properties from the result set in memory without performing another database roundtrip.

Common Issues Related to the ADO.NET Entity Framework


The following table lists some of the common issues that may arise when you use the ADO.NET Entity Framework.
Issue Optimistic concurrency conflicts Troubleshooting tip When you invoke the SaveChanges method on the ObjectContext object, catch OptimisticConcurrencyException exceptions. Invoke the Refresh method on the ObjectContext object to specify how you want to handle the conflict. When you map an association between two entities, you must delete the original scalar property that represented the foreign key. In its place, the code generator creates a navigation property that you can use to locate the associated entity.

Mapping associations

Best Practices for the ADO.NET Entity Framework


Supplement or modify the following best practices for your own work situations: Retain entity changes in memory for as short a time as possible. Submit the changes to the database as soon as possible, to minimize the risk of concurrent conflicts with other users. Make use of the advanced capabilities that are available in EDMs to abstract your code from the underlying database schema.

Building Occasionally Connected Solutions by Using Synchronization Services

6-1

MCT USE ONLY. STUDENT USE PROHIBITED

Module 6
Building Occasionally Connected Solutions by Using Synchronization Services
Contents:
Lesson 1: Understanding Microsoft Synchronization Services Lesson 2: Downloading Data by Using Synchronization Services Lesson 3: Uploading Data by Using Synchronization Services Lab: Building Occasionally Connected Solutions by Using Synchronization Services Course Evaluation 6-3 6-8 6-13 6-18 6-34

6-2

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Overview

Microsoft Synchronization Services is a separate library, in addition to the Microsoft .NET Framework, that enables you to write code for applications that have one or more clients that connect occasionally. For example, you would use this library when you develop an application to run on a laptop that is usually not connected to the network. In this module, you will learn about the architecture and the applications programming interface (API) of Synchronization Services and how to use the services to perform synchronization.

Building Occasionally Connected Solutions by Using Synchronization Services

6-3

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 1

Understanding Microsoft Synchronization Services

This lesson describes the architecture of Synchronization Services, the types of changes that can be tracked, and the architecture of the code that is used to provide occasionally connected applications.

6-4

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Overview of Synchronization Services

Key Points
Synchronization is the process where the data in one data source is used to update the data in another data source. Microsoft Synchronization Services provides ADO.NET classes to enable you to synchronize between data sources. The server side can be a data source for which there is an ADO.NET 2.0 data provider and the client side can be Microsoft SQL Server or Microsoft SQL Server Compact Edition 3.5 or later. Synchronization Services can handle multiple clients uploading and downloading data from a server simultaneously. The services ensure that only data that has changed since the last synchronization is exchanged, and it indicates conflicts. Question: How does the client find out that there have been changes in the server?

Building Occasionally Connected Solutions by Using Synchronization Services

6-5

MCT USE ONLY. STUDENT USE PROHIBITED

Synchronization Models Supported by Synchronization Services

Key Points
Synchronization Services supports four synchronization modes. You choose the mode that best suits your application. Question: What are the principal differences between snapshot and download-only?

6-6

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Common Application Architectures That Use Synchronization Services

Key Points
Synchronization Services supports two tier, n-tier, and service-based architecture. Question: When could these models be applied to your own applications?

Building Occasionally Connected Solutions by Using Synchronization Services

6-7

MCT USE ONLY. STUDENT USE PROHIBITED

Synchronization Services vs. SQL Server Merge Replication

Key Points
Synchronization Services is an easy-to-use development framework that enables you to create solutions that synchronize data in occasionally connected systems. SQL Server Merge Replication is a powerful replication solution that enables you to synchronize data between SQL Server databases. SQL Server Merge Replication supports more complex scenarios that Synchronization Services, but it is not as easy to configure programmatically.

6-8

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 2

Downloading Data by Using Synchronization Services

This lesson explains how to change the server database to support Synchronization Services and how a client application can retrieve data by using Synchronization Services.

Building Occasionally Connected Solutions by Using Synchronization Services

6-9

MCT USE ONLY. STUDENT USE PROHIBITED

Configuring a Server Database to Support Synchronization

Key Points
You must alter the server database so that Synchronization Services can track changes. You do not make any changes to the client database. Question: Why would you track user IDs? Question: What changes must be made on the database to support tracking deleting rows?

6-10

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Overview of the Synchronization Services API

Key Points
Synchronization Services provides classes to coordinate synchronization and to access data sources on the client and on the server. Question: Which of these objects do you call on a server in an n-tier application?

Building Occasionally Connected Solutions by Using Synchronization Services

6-11

MCT USE ONLY. STUDENT USE PROHIBITED

Downloading and Caching Data in a Client Database

Key Points
Synchronization applies the changes made on one database over a period of time to another database. At synchronization time, Synchronization Services generates anchor values and uses these values to determine which rows have changed. Question: Where do the values for anchor session variables come from?

6-12

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Downloading and Caching Data by Using Synchronization Services

Building Occasionally Connected Solutions by Using Synchronization Services

6-13

MCT USE ONLY. STUDENT USE PROHIBITED

Lesson 3

Uploading Data by Using Synchronization Services

This lesson describes how your applications can upload data to the server. This lesson also explains how your applications are informed about synchronization conflicts and how you can handle these conflicts.

6-14

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Uploading Modified Data from a Client Database

Key Points
When you use upload-only or bidirectional synchronization, there is a possibility that more than one client could attempt to change the same row. Question: Why can you not use transactions to solve the type of concurrency issue that occurs with synchronization?

Building Occasionally Connected Solutions by Using Synchronization Services

6-15

MCT USE ONLY. STUDENT USE PROHIBITED

Detecting and Resolving Conflicts

Key Points
The synchronization provider indicates conflicts by raising the ApplyChangeFailed event. You can resolve conflicts by changing the properties of the event argument. Question: How can you reduce the possibility of conflicts during synchronization?

6-16

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Handling Synchronization Events

Key Points
You can monitor the progress of the synchronization through events that are raised on the synchronization providers and the synchronization agent. Question: What is the significance of the fact that the events that are used to monitor progress are raised on the thread that called Synchronize?

Building Occasionally Connected Solutions by Using Synchronization Services

6-17

MCT USE ONLY. STUDENT USE PROHIBITED

Demonstration: Uploading Data by Using Synchronization Services

6-18

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

Exercise 1: Modifying a Database Schema to Support Synchronization


Scenario
You are a developer for the Medical Clinic Management System for Contoso, Ltd. The Contoso Clinic Management System is a healthcare system for hospitals and clinics that run specialist practices. In this lab, you will write an application that enables doctors to view and edit their appointments. This application runs on the doctors' computers that are only occasionally connected to the database. Doctors can change some items, like the notes for each appointment, and cache these changes locally. When doctors are connected to the database, they can download new appointments and upload changes they have made to the appointments on their computers. In this exercise, you will alter the database to enable Synchronization Services to synchronize the database with locally cached tables on a doctor's computer.

Building Occasionally Connected Solutions by Using Synchronization Services

6-19

MCT USE ONLY. STUDENT USE PROHIBITED

The main tasks for this exercise are as follows: 1. 2. 3. 4. Start the 6464A-LON-DEV-06 virtual machine and log on as Student. Add a local database cache. Examine the generated code. Examine the database.

Task 1: Start the 6464A-LON-DEV-06 virtual machine and log on as Student


1. 2. Open the Virtual Server Remote Control Client and double-click 6464A-LONDEV-06. Log on to 6464A-LON-DEV-06 as Student using the password Pa$$w0rd.

Task 2: Add a Local Database Cache


1. 2. Open Microsoft Visual Studio 2008. If you are using Microsoft Visual Basic development system, open the solution E:\Labfiles\Starter\VB\Appointments\Appointments.sln. If you are using Microsoft Visual C# development tool, open the solution E:\Labfiles\Starter\CS\Appointments\Appointments.sln. In the MobileAppointments project, add a new Local Database Cache item called client.sync When you add this item, the Configure Data Synchronization Wizard will run. 4. In the Configure Data Synchronization Wizard, perform these steps: a. b. 5. Add a new connection to ContosoMedicalDB on .\SQLEXPRESS. To the Cached tables control, add the Appointments table.

3.

When the Configure Data Synchronization Wizard completes, the Data Source Configuration Wizard allows you to add a dataset. a. Add the Appointments table with the following columns: AppointmentID PatientID AppointmentDateTime

6-20

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

b. 6.

Notes

Change the DataSet name to clientDataSet.

Confirm that the wizard performs these steps: a. b. Creates the SQL Server CE 3.5 database file, as the local cache, and adds it to the project. Adds a dataset that you can use to connect to the local cache.

Task 3: Examine the generated code


1. View the code generated by the wizard for Synchronization Services. The easiest way to do this is to use Class View to load the code for the clientClientSyncProvider class. The Local Database Cache Wizard has generated the following classes.
Description This is the local synchronization provider and holds the code to connect to the local cache. This is the synchronization agent that encapsulates the code to create the synchronization providers and to indicate which tables to synchronize. This class indicates the table that will be synchronized and the direction of the synchronization. This is the server synchronization adapter that indicates information about how to access the server database. This is the server synchronization provider.

2.

Class clientClientSyncProvider

clientSyncAgent

clientSyncAgent.AppointmentsSyncTable

AppointmentsSyncAdapter

clientServerSyncProvider

Building Occasionally Connected Solutions by Using Synchronization Services

6-21

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Scroll to the nested class clientSyncAgent.AppointmentsSyncTable. The wizard only generates code to perform download-only synchronization. Notice the following: The class does not explicitly declare the value for the SyncTable.SyncDirection property, so it uses the default value of DownloadOnly. The class calls the partial method OnInitialized in the constructor.

4.

In the MobileApplications project, open the code for the MainForm form. Add an implementation for the OnInitialized method of the clientSyncAgent.AppointmentsSyncTable. The code for this method is supplied in the Ex1_Task3_OnInitialized.txt file: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

5. 6.

Add a line to enable you to use members from the Microsoft.Synchronization.Data namespace. Save your code.

Task 4: Examine the database


1. 2. In Solution Explorer, expand the ContosoMedicalDatabases project, and then double-click lon-dev\SQLEXPRESS.ContosoMedicalDB.dbo. In Server Explorer, expand lon-dev\SQLEXPRESS.ContosoMedicalDB.dbo and view the tables in the database. Notice that there is a new table named Appointments_Tombstone. Examine the Appointments table and note that there are two new columns, as described in the following table.
Description A datetime column used to track when a row was last updated. This is a new column. A datetime column used to track when a row was inserted. This is a new column.

3.

Item LastEditDate

CreationDate

6-22

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

4.

Examine the triggers created for the Appointments table.


Description Adds an entry in the tombstone table for the deleted row, together with the appointment identifier and the current time. If the row has been deleted before, the tombstone entry is updated to show the current time. Initializes the CreationDate column with the current time. Initializes the LastEditDate column with the current time.

Trigger Appointments_DeletionTrigger

Appointments_InsertTrigger

Appointments_UpdateTrigger

5.

Examine the Appointments_Tombstone table, summarized in the following table.


Description This is the primary key of the row that was deleted. This is the time and date when the row was deleted.

Item AppointmentID DeletionDate

Results: After this exercise, you should have altered the database to enable synchronization and generated supporting classes to initiate synchronization.

Exercise 2: Downloading Data to a Client Computer


In this exercise, you will add the code to synchronize the locally cached database with the server database. You will only support download-only synchronization. The main tasks for this exercise are as follows: 1. 2. 3. 4. 5. Examine the user interface. Alter the SyncAdapter class. Add a new dataset. View the server test code. Compile and test download-only synchronization.

Building Occasionally Connected Solutions by Using Synchronization Services

6-23

MCT USE ONLY. STUDENT USE PROHIBITED

Task 1: Examine the user interface


1. 2. Open MainForm.vb (Visual Basic) or MainForm.cs (Visual C#) in the forms designer. Examine the controls on this form as summarized in the following table.
Description Use this text box to provide the identifier for the doctor. Click this button to synchronize between the server database and the local cache. Click this button to save data in the grid to the local cache. (Will be used in a later exercise.) View the data in the local cache.

Control doctorID synchronize

saveCache

appointmentsGrid

Task 2: Alter the SyncAdapter class


1. In the ContosoMedicalDatabases solution, run the CreateApointmentStoredProcedures.sql script in the Create Scripts folder. This script creates the stored procedures necessary for retrieving and updating appointments in the ContosoMedical database. Review the InitializeCommands on the AppointmentstSyncAdapter class that was generated by the Configure Data Synchronization wizard. The commands defined in this method are summarized in the following table.
Description This is called to insert a row in the server database. The command first sets the IDENTITY_INSERT T-SQL option so that a value can be provided for the identity row. The command then inserts a row into the table. All of the column values are provided through parameters. The command provides values for the date tracking columns, which is redundant because the insertion trigger will perform this action. Finally, the @sync_row_count session variable is initialized by the value of the number of rows inserted.

2.

Command InsertCommand

6-24

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Command DeleteCommand

Description The row that holds the specific AppointmentID value is deleted under one of two conditions: either this is a force write or the row was not edited since last synchronized. A force write means that the client has indicated that the client changes must be made regardless of any conflicts with the server data. The AppointmentID value, which identifies the appointment row to be deleted, is provided through a parameter. The @sync_row_count session variable is initialized by the value of the number of rows inserted. The row with the specified AppointmentID is updated. All the other columns are provided through parameters, including the date tracking columns, which is redundant because the update trigger will perform this action. The update is performed under one of two conditions: either this is a force write or the row was not edited since last synchronized. The @sync_row_count session variable is initialized by the value of the number of rows inserted. The query used to determine if there is a deletion conflict. This simply tests the tombstone table for a row with the specified AppointmentID value. The query used to identify updated rows that conflict with other changes. The query used to obtain the rows that were inserted since the last synchronization. The query used to obtain the rows that were deleted since the last synchronization. The query used to obtain the rows that were updated since the last

UpdateCommand

SelectConflictDeletedRowsCommand

SelectConflictUpdatedRowsCommand

SelectIncrementalInsertsCommand

SelectIncrementalDeletesCommand

SelectIncrementalUpdatesCommand

Building Occasionally Connected Solutions by Using Synchronization Services

6-25

MCT USE ONLY. STUDENT USE PROHIBITED

Command

Description synchronization.

3.

In Server Explorer, examine the uspGetAppointmentsForDoctor stored procedure. This procedure is used to get all of the appointments for a specific doctor. To enable you to use the results from the stored procedure, you will remove the local cache and the dataset that was generated for you. To do this: a. b. c. Remove the ContosoMedicalDB.sdf file from the project. Remove the ContosoMedicalDB.sdf file from the output build folder. Remove the clientDataSet.xsd file from the project.

4.

In the following tasks you will generate new versions of these files. 5. Provide an implementation of OnInitialized in the AppointmentsSyncAdapter class to provide the commands to invoke the uspGetAppointmentsForDoctor stored procedure. The code for this method is in the Ex2_Task2_OnInitialized.txt file.

Task 3: Add a new dataset


1. Recreate the cached database. Add an implementation for the Click handler of the Synchronize button to create an empty SQL Server CE 3.5 database and use Synchronization Services to fill this database. The implementation of this method can be found in the Ex2_Task3_synchronize_Click.txt file. Compile and run the application. Click Synchronize to generate the new database file. Close the application. Copy the generated file, ContosoMedicalDB.sdf, to the project folder and add it to the project. The Data Source Configuration Wizard starts to create a new dataset in the project. Add the dataset for Appointments table and name this dataset clientDataSet. Indicate that the dataset will use the following columns: AppointmentID AppointmentDateTime FullName Gender DateOfBirth

2. 3.

6-26

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

4.

Notes

Use the Appointments table on the clientDataSet dataset as the DataSource value of the appointmentsGrid control on the MainForm form. A table adapter and a binding source are generated.

5.

In the synchronize_Click method, update the data grid view by using the table adapter. Add the following line of code after the call to agent.Synchronize.

[Visual Basic] Me.appointmentsTableAdapter.Fill(Me.clientDataSet.Appointments)

[Visual C#] this.appointmentsTableAdapter.Fill(this.clientDataSet.Appointments);

Task 4: View the server test code


1. 2. In Solution Explorer, open the DesktopAppointments project, and then open the MainForm form in the forms designer. Familiarize yourself with the controls on this form as summarized in the following table.
Description This navigation control enables you to navigate through the Appointments table on the server. In particular, notice the following buttons:

Control navigator

The Delete button deletes the selected row in the dataset. The Save button saves all of the changes in the dataset to the
server database.

The Refresh button reads the dataset from the database. If


you have already made changes to the dataset they are discarded. appointmentsGrid This data grid shows values from the Appointments table. If you add a new row, you must provide values for DoctorID, PatientID and AppointmentDateTime.

Building Occasionally Connected Solutions by Using Synchronization Services

6-27

MCT USE ONLY. STUDENT USE PROHIBITED

Task 5: Compile and test download-only synchronization


1. 2. Compile and run the client application. Start the server application.

Note: Visual Studio only starts the process for the project that is marked as the startup project. To start processes created by other projects, you must start the process directly from the build output folder.

3.

Position the applications side by side and compare the contents. Verify that they are synchronized.

4.

In the Desktop Calendar add the following rows. On the navigator, click the Add New button, and then fill all of the cells except for the AppointmentID cell. When you have entered the values for all of the new rows, click the Save button on the navigator. To do this: a. Add the first new appointment with the information from the following table.
Value 1 5 06/03/2008 9:00 First new appointment

Column DoctorID PatientID AppointmentDateTime Notes

b.
Column

Add the second new appointment with the information from the following table.
Value 2 10 06/03/2008 10:00 Second new appointment

DoctorID PatientID AppointmentDateTime Notes

6-28

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

5.

Verify that the Mobile Calendar application reads its data from the local cache instead of the server database. Close the application, and then restart and verify that there are no new rows. On the Mobile Calendar form, click Synchronize. Verify that the Mobile Calendar now has the row you entered on Desktop Calendar. In the Desktop Calendar, make a change to the Notes field for the row that you just inserted for doctor 1. Click the Save button. In the Mobile Calendar, click Synchronize, and then confirm that the change has been copied to the cached database. In the Desktop Calendar, delete the new row. Click the Save button to save the results to the database. In the Mobile Calendar, click Synchronize, and then confirm that the previous row has been deleted. Close Mobile Calendar but keep Desktop Calendar running for the other exercises.
Results: After this exercise, you should have implemented an application that performs download-only synchronization with a SQL Server database. You should have shown that synchronization works for inserted, updated, and deleted rows.

6. 7.

8.

9.

Exercise 3: Uploading Data Changes to the Database


In this exercise, you will write the code to support bidirectional synchronization and to enable you to handle conflicts. The main tasks for this exercise are as follows: 1. 2. 3. Change the MobileAppointments class to use bidirectional synchronization. Add conflict handling. Build and run the application.

Task 1: Change the MobileAppointments class to use bidirectional synchronization


1. In the code for the MainForm form, alter the OnInitialized method of the nested class AppointmentsSyncTable so that the synchronization direction is bidirectional.

Building Occasionally Connected Solutions by Using Synchronization Services

6-29

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Provide a workaround for the InsertCommand method of the AppointmentsSyncAdapter class, which was generated by the wizard. The workaround code is in the Ex3_Task1_OnInitialized.txt file. In the Forms Designer, double-click the Save to Cache button on the MainForm form, and then add the following code to save the data in the data grid view control through the table adapter object.

3.

[Visual Basic] Me.Validate() Me.appointmentsBindingSource.EndEdit() Me.appointmentsTableAdapter.Update(Me.clientDataSet.Appointments)

[Visual C#] this.Validate(); this.appointmentsBindingSource.EndEdit(); this.appointmentsTableAdapter.Update(this.clientDataSet.Appointments);

4.

Compile and run the application. To do this: a. b. c. In Mobile Calendar, change the Notes cell of one of the appointments. Click Save to Cache to save the change to the local cache. Click Synchronize to synchronize the changes to the server.

d. In Desktop Calendar, click Refresh, and then verify that the Notes column of the appointment that you changed has changed to the value you used. e. Close the Mobile Calendar application.

Task 2: Add conflict handling


1. Open the Handle Conflict dialog in the forms designer and examine the following controls:
Description This text box displays the conflict that has occurred. It gives the type of conflict and the conflicting client and server rows. This radio button group enables you to determine if you will allow the default action to

Control The following conflict has occurred

How do you want to handle this?

6-30

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Control

Description occur or if you want to force another action.

2.

View the code for this form. There are two properties: The Action property returns an ApplyAction value based on the radio button selected. The ConflictType property displays information about the conflict in the text box on the form.

3.

On the MainForm form, open the Click handler for the Synchronize button and, immediately before the call to agent.Synchronize(), add code to handle the ApplyChangeFailed event on the remote synchronization provider with a method named remote_ApplyChangeFailed. The Ex3_Task2_ApplyChangeFailed.txt file has the implementation of remote_ApplyChangeFailed. This code creates an instance of the Handle Conflict dialog box and uses the results from this dialog box to determine how the ApplyChangeFailed event is handled.

Task 3: Build and run the application


1. Build and run the application, and test it as follows: a. b. c. 2. Add a new row to the server database by using Desktop Calendar. On the navigator, click the Save button to save the data in the server database. In Mobile Calendar, synchronize the databases.

Generate a conflict as follows: a. b. c. In Mobile Calendar, change the Notes cell for the new row, and then click Save to Cache to save this change in the cached database. In Desktop Calendar, change the Notes cell for the same row, and then click Save to save the change in the server database. In Mobile Calendar, click Synchronize.

Building Occasionally Connected Solutions by Using Synchronization Services

6-31

MCT USE ONLY. STUDENT USE PROHIBITED

The Handle Conflict dialog box appears and shows the details of the conflict. d. Select Continue with the current action, and then click OK to indicate that the server changes should be accepted. Confirm that the client cache is updated with the results from the server. 3. Repeat the previous test, but this time in the Handle Conflict dialog box, select Force this write. This time the client change is accepted. To confirm this, in Desktop Calendar, click Refresh to refresh the grid with values from the server database. 4. Generate a conflict by deleting a row in the server and updating the same row in the cached database, as follows: a. b. c. In Desktop Calendar, select the new row, and then click Delete. Click Save. In Mobile Calendar, change the Notes field for this row. Click Save to Cache. Synchronize. Confirm that a conflict is detected, to indicate that the mobile calendar updated a row that the desktop calendar deleted. d. In the Handle Conflict dialog box, select Force this write. e. f. 5. Confirm that the row remains in the local cache. In Desktop Calendar, click Refresh, and then confirm that the row has been re-inserted into the server database.

Close Desktop Calendar and close Mobile Calendar.


Results: After this exercise, you should have implemented the application so that it handles synchronization conflicts and you can specify whether changes in the client override changes in the server.

6-32

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Module Review and Takeaways

Review Questions
1. Why is it important that values for time tracking anchor values are generated by the server? For synchronization to work, it is vital that the time source used by all of the code that can change data is the same. If different time sources are used, even a difference in a few milliseconds can prevent Synchronization Services from working. A single time source prevents this problem. 2. What role do transactions play in Synchronization Services? Transactions can only be used within individual commands, for example to update the server. A transaction must not be used between the Synchronization Services commands.

Building Occasionally Connected Solutions by Using Synchronization Services

6-33

MCT USE ONLY. STUDENT USE PROHIBITED

3.

What role does the tombstone table play? The tombstone table has sufficient information about the rows that have been deleted for Synchronization Services to determine which rows have been deleted since the last synchronization. This table is not an archive of deleted data, all the tombstone table needs is to have the identity column of the table that it is associated with, tracking information (such as the time the row was deleted), and the identifier of the user who deleted the row.

Real-World Issues and Scenarios


The following real-world scenarios benefit from a solution that uses Synchronization Services: 1. 2. 3. Courier services Utility meter readers Survey taking

6-34

Visual Studio 2008: ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Course Evaluation

Your evaluation of this course will help Microsoft understand the quality of your learning experience. Please work with your training provider to access the course evaluation form. Microsoft will keep your answers to this survey private and confidential and will use your responses to improve your future learning experience. Your open and honest feedback is valuable and appreciated.

Lab: Connecting to a Database and Retrieving Data

L1-1

MCT USE ONLY. STUDENT USE PROHIBITED

Module 1: Getting Started with ADO.NET 3.5

Lab: Connecting to a Database and Retrieving Data


Exercise 1: Connecting to a Database
Logon information:
Virtual machine: 6464A-LON-DEV-01 User name: Student Password: Pa$$w0rd

Estimated time: 45 minutes

Task 1: Start the 6464A-LON-DEV-01 virtual machine and log on as Student


1. 2. Open the Virtual Server Remote Control Client and double-click 6464A-LONDEV-01. Log on to 6464A-LON-DEV-01 as Student using the password Pa$$w0rd.

Task 2: Open and review the project


1. 2. 3. Click Start, point to All Programs, click Microsoft Visual Studio 2008, and then click Microsoft Visual Studio 2008. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, go to E:\Labfiles\Starter\VB\ContosoMedical (if you are using Microsoft Visual Basic development system) or E:\Labfiles\Starter\CS\ContosoMedical (if you are using Microsoft Visual C# development tool), click ContosoMedical.sln, and then click Open.

L1-2

Module 1: Getting Started with ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

4.

In Solution Explorer, open the following projects and examine their contents. The ClinicAdminClient project is a Windows Forms project with a single form that enables the user to retrieve doctor names from the database. The ContosoMedicalDatabases project contains scripts for creating the database. These scripts are here for your information only; the database is already installed on the computer. The ContosoMedicalUtilities project is a library project that contains the code to access the database.

5.

In Solution Explorer, in the ClinicAdminClient project, double-click ClinicAdminForm.vb (Visual Basic) or ClinicAdminForm.cs (Visual C#) to open the form in the designer. Review the form: The Get Count button gets a count of how many doctors are in the database. The Show Doctors button gets either all doctors or the doctors that have a particular specialty. The specialtyTextBox enables the user to request information for doctors that have a particular specialty. The doctorsListBox shows the list of doctors retrieved when the user clicks Show Doctors.

6.

Task 3: Add a connection string to the application configuration file


1. 2. 3. 4. In Solution Explorer, right-click the ClinicAdminClient project, and then click Properties. Click the Settings tab to show the application settings grid. On the first line, click in the left-most box (under the Name column), and then type ContosoMedicalDBConnectionString The next box (under the Type column) is a drop-down list. Expand the dropdown list, and then click (Connection string).

Lab: Connecting to a Database and Retrieving Data

L1-3

MCT USE ONLY. STUDENT USE PROHIBITED

5.

In the right-most box (under the Value column), type the following connection string as a single line:
Data Source=.\SQLEXPRESS; Initial Catalog=ContosoMedicalDB; Integrated Security=true

6.

Close the ClinicAdminClient properties window. When you are asked if you want to save the changes to the settings, click Yes.

Note: Microsoft Visual Studio development system adds an app.config file to the project with the connection string you just added; however, it will give the setting a name so that it can be used with the My.Settings (Visual Basic) or Properties.Settings (Visual C#). You will not be using these classes in the application, so you will rename the setting as described in the steps.

7.

In Solution Explorer, double-click app.config to open the file in the editor. Verify that the designer has added a <connectionStrings> element and that it has an <add> child element containing the connection string that you entered in step 5:
[Visual Basic] ClinicAdminClient.My.MySettings.ContosoMedicalDBConnectionString

[Visual C#] ClinicAdminClient.Properties.Settings.ContosoMedicalDBConnectionStr ing

8. 9.

Change the name to ContosoMedicalDBConnectionString. On the File menu, click Save app.config to save the changes.

L1-4

Module 1: Getting Started with ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Task 4: Add a data access class to the project


1. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#) to open the file in the editor.

Note: This file will be empty (Visual Basic) or have an empty namespace named ContosoMedicalUtilities (Visual C#).

2.

Open Notepad, go to the folder E:\Labfiles\Starter\VB (Visual Basic) or E:\Labfiles\Starter\CS (Visual C#), and open the Ex1_Task4.txt file. Copy the entire contents of the file to the Clipboard. Keep Notepad open because you will open more text files during this exercise. In Visual Studio, in the ContosoMedicalDAC source file, click the first line (Visual Basic) or click the line between the braces (Visual C#). On the Edit menu, click Paste to paste the class code into the file.

3.

Task 5: Implement the GetConnection method


1. In Solution Explorer, right-click the ContosoMedicalUtilities project, and then click Add Reference. In the Add Reference dialog box, click the .NET tab. Scroll down the list of components, click System.Configuration, and then click OK. In the ContosoMedicalDAC source file, add the following statement to the top of the file:
[Visual Basic] Imports System.Configuration

2.

[Visual C#] using System.Configuration;

Lab: Connecting to a Database and Retrieving Data

L1-5

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Locate the GetConnection method, delete the statement that returns Nothing (Visual Basic) or null (Visual C#), and then add the following code to the method:
[Visual Basic] Dim connection As SqlConnection = Nothing Dim settings As ConnectionStringSettings = _ ConfigurationManager.ConnectionStrings( _ "ContosoMedicalDBConnectionString") If Not (settings Is Nothing) Dim ConnectionString As String = settings.ConnectionString connection = New SqlConnection(ConnectionString) End If Return connection

[Visual C#] SqlConnection connection = null; ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[ "ContosoMedicalDBConnectionString"]; if (settings != null) { string ConnectionString = settings.ConnectionString; connection = new SqlConnection(ConnectionString); } return connection;

4.

Save the ContosoMedicalDAC source file.

L1-6

Module 1: Getting Started with ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Task 6: Build and run the application


1. On the Build menu, click Rebuild Solution, and verify that no errors or warnings occur.

Note: The ContosoMedicalDC.GetAllDoctors method that you copied in Task 4 has been implemented to call GetConnection so that you can test your code.

2. 3.

On the Debug menu, click Start Without Debugging to start the application. In the Clinic Administration Client window, click Show Doctors. If you get an exception thrown, check that you typed the code correctly, in particular, check that the correct connection string is used in the configuration file. Close the application.

4.

Results: After this exercise, you should have created a project that will compile correctly and can connect to a database without throwing an exception.

Exercise 2: Executing a Simple Query


Task 1: Implement the GetNumberOfDoctors method
1. 2. In Solution Explorer, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#) to open the file in the editor. Locate the GetNumberOfDoctors method. The method currently contains the following minimal implementation.
[Visual Basic] Dim result as Integer = 0 Return result

[Visual C#] int result = 0; return result;

Lab: Connecting to a Database and Retrieving Data

L1-7

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Between these two lines of code, add the following code.


[Visual Basic] Dim connection As SqlConnection = Nothing Try connection = GetConnection() Dim sql As String = "select count(*) from Doctors" Dim command As New SqlCommand(sql, connection) connection.Open() result = CInt(command.ExecuteScalar()) Finally If Not (connection Is Nothing) connection.Close() End If End Try

[Visual C#] SqlConnection connection = null; try { connection = GetConnection(); string sql = "select count(*) from Doctors"; SqlCommand command = new SqlCommand(sql, connection); connection.Open(); result = (int)command.ExecuteScalar(); } finally { if (connection != null) { connection.Close(); } }

4.

Save the ContosoMedicalDAC source file.

L1-8

Module 1: Getting Started with ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Implement the handler for the Get Count button


1. In Solution Explorer, in the ClinicAdminClient project, double-click ClinicAdminForm.vb (Visual Basic) or ClinicAdminForm.cs (Visual C#) to open the form in the designer. Double-click the Get Count button to view the getDoctorCount_Click event handler method. In the getDoctorCount_Click method, in the Try block (Visual Basic) or the try block (Visual C#), add the following code.
[Visual Basic] Dim dac As New ContosoMedicalDAC() Dim count As Integer = dac.GetNumberOfDoctors() Dim message As String = _ String.Format("There are {0} doctors registered.", count) MessageBox.Show(message, "Doctor Count")

2. 3.

[Visual C#] ContosoMedicalDAC dac = new ContosoMedicalDAC(); int count = dac.GetNumberOfDoctors(); string message = String.Format( "There are {0} doctors registered.", count); MessageBox.Show(message, "Doctor Count");

4.

On the File menu, click Save ClinicAdminForm.vb (Visual Basic) or Save ClinicAdminForm.cs (Visual C#).

Lab: Connecting to a Database and Retrieving Data

L1-9

MCT USE ONLY. STUDENT USE PROHIBITED

Task 3: Build and run the project


1. 2. 3. On the Build menu, click Rebuild Solution, and verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. In the Client Administration Client window, click Get Count. Verify that the application displays a message box indicating the number of doctors in the database. Close the message box, and then close the Client Administration Client window.
Results: After this exercise, you should have executed a database query that retrieves a single value from the database.

4.

Exercise 3: Executing a Query that Returns a Result Set


Task 1: Implement the GetAllDoctors method
1. 2. In Solution Explorer, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#) to open the file in the editor. Locate the GetAllDoctors method. Delete the code in the body of the method, and then replace it with the following code.
[Visual Basic] Dim connection As SqlConnection = GetConnection() Dim sql As String = _ "select DoctorID, FirstName, LastName, Specialty from Doctors" Dim command As New SqlCommand(sql, connection) connection.Open() Dim reader As SqlDataReader = command.ExecuteReader( _ CommandBehavior.CloseConnection) Return reader

L1-10

Module 1: Getting Started with ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] SqlConnection connection = GetConnection(); string sql = "select DoctorID, FirstName, LastName, Specialty from Doctors"; SqlCommand command = new SqlCommand(sql, connection); connection.Open(); SqlDataReader reader = command.ExecuteReader( CommandBehavior.CloseConnection); return reader;

Note: In this code, the ExecuteReader method specifies the CommandBehaviors.CloseConnection parameter. This parameter value causes the data reader object to close the connection when you close the data reader object.

3.

On the File menu, click Save ContosoMedicalDAC.vb (Visual Basic) or Save ContosoMedicalDAC.cs (Visual C#).

Task 2: Implement the ShowAllDoctors method


1. In Solution Explorer, in the ClinicAdminClient project, right-click ClinicAdminForm.vb (Visual Basic) or ClinicAdminForm.cs (Visual C#) and then click View Code. Locate the ShowAllDoctors method. Inside the Try block (Visual Basic) or try block (Visual C#), add the following code.
[Visual Basic] Dim dac As New ContosoMedicalDAC() Using reader As SqlDataReader = dac.GetAllDoctors() While reader.Read() Dim doctorInfo As String = _ String.Format("[{0}]" & Chr(9) & "Dr. {1} {2} {3}", _ reader.GetInt32(0), _ reader.GetString(1), _ reader.GetString(2), _ reader.GetString(3)) doctorsListBox.Items.Add(doctorInfo) End While End Using

2.

Lab: Connecting to a Database and Retrieving Data

L1-11

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] ContosoMedicalDAC dac = new ContosoMedicalDAC(); using (SqlDataReader reader = dac.GetAllDoctors()) { while (reader.Read()) { string doctorInfo = string.Format("[{0}]\tDr. {1} {2}, {3}", reader.GetInt32(0), reader.GetString(1), reader.GetString(2), reader.GetString(3)); doctorsListBox.Items.Add(doctorInfo); } }

3.

On the File menu, click Save ClinicAdminForm.vb (Visual Basic) or Save ClinicAdminForm.cs (Visual C#).

Task 3: Build and run the project


1. 2. 3. 4. On the Build menu, click Rebuild Solution, and verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. In the Client Administration Client window, click Show Doctors. Verify that the application displays a list of doctors in the list box. Close Client Administration Client.
Results: After this exercise, you should have executed a database query that retrieves a result set from the database.

L1-12

Module 1: Getting Started with ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 4: Executing a Query that Requires Parameters


Task 1: Review the stored procedure
1. In Solution Explorer, in the ContosoMedicalDatabases project, expand the Create Scripts node, and then double-click ContosoMedicalDB.dbo.uspGetDoctorsForSpecialty to open the stored procedure in the editor. Review the stored procedure: The procedure has an input parameter named @specialty. The procedure has an output parameter named @doctorCount. The procedure returns an integer value indicating the number of doctors with the provided specialty. The procedure performs a query for all the doctors that have the provided specialty.

2.

Task 2: Review the Doctors class


In Solution Explorer, under the ContosoMedicalUtilities project, double-click Doctor.vb (Visual Basic) or Doctor.cs (Visual C#). Note the following: This is a very trivial class that gives property access to its fields. It has a constructor that simply uses the parameters to initialize the fields.

Lab: Connecting to a Database and Retrieving Data

L1-13

MCT USE ONLY. STUDENT USE PROHIBITED

Task 3: Implement the GetDoctorsForSpecialty method


1. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#) to open the file in the editor. Locate the GetDoctorsForSpecialty method. This method has a minimal implementation. You will copy the rest of the implementation from a file on disk. 3. In Notepad, go to the folder E:\Labfiles\Starter\VB (Visual Basic) or E:\Labfiles\Starter\CS (Visual C#), and then open the Ex4_Task2.txt file. Copy the entire contents of the file to the Clipboard. In Visual Studio, paste the code immediately before the Return doctors statement (Visual Basic) or return doctors; statement (Visual C#). Save the ContosoMedicalDAC source file.

2.

4. 5.

Task 4: Implement the ShowDoctorsForSpecialty method


1. In Solution Explorer, in the ClinicAdminClient project, right-click ClinicAdminForm.vb (Visual Basic) or ClinicAdminForm.cs (Visual C#) and then click View Code. Locate the ShowDoctorsForSpecialty method. In Notepad, open the Ex4_Task3.txt file from the same folder as in the previous task, and then copy the entire contents of the file to the Clipboard. In Visual Studio, paste the code into the body of the ShowDoctorsForSpecialty method. On the File menu, click Save ClinicAdminForm.vb (Visual Basic) or Save ClinicAdminForm.cs (Visual C#).

2. 3. 4. 5.

L1-14

Module 1: Getting Started with ADO.NET 3.5

MCT USE ONLY. STUDENT USE PROHIBITED

Task 5: Build and run the project


1. 2. 3. 4. On the Build menu, click Rebuild Solution. Verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. In the Clinic Administration Client window, click Show Doctors. From the list of doctors, make a note of one of the specialties. Type the specialty in the Specialty box, and then click Show Doctors. Verify that the application displays a list of doctors that have the provided specialty. Also verify that the application displays a message box indicating the number of doctors that have the specialty, plus the number of specialties registered in the database. 5. 6. Close the message box, and then close Clinic Administration Client. Close Visual Studio.
Results: After this exercise, you should have executed a stored procedure that requires parameters.

Lab: Modifying Data by Using ADO.NET Commands

L2-15

MCT USE ONLY. STUDENT USE PROHIBITED

Module 2: Modifying Data by Using ADO.NET Commands

Lab: Modifying Data by Using ADO.NET Commands


Exercise 1: Inserting, Updating, and Deleting Data in a Database
Logon information:
Virtual machine: 6464A-LON-DEV-02 User name: Student Password: Pa$$w0rd

Estimated time: 60 minutes

Task 1: Start the 6464A-LON-DEV-02 virtual machine and log on as Student


1. 2. Open the Virtual Server Remote Control Client and double-click 6464A-LONDEV-02. Log on to 6464A-LON-DEV-02 as Student using the password Pa$$w0rd.

L2-16

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Access patient data


1. 2. 3. Click Start, point to All Programs, click Microsoft Visual Studio 2008, and then click Microsoft Visual Studio 2008. In Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, go to E:\Labfiles\Starter\VB\ContosoMedical (if you are using Microsoft Visual Basic development system) or E:\Labfiles\Starter\CS\ContosoMedical (if you are using Microsoft Visual C# development tool), click ContosoMedical.sln, and then click Open. In Solution Explorer, in the ContosoMedicalDatabases project, expand the Create Scripts node. Double-click ContosoMedicalDB.dbo.Patients.SQL to open the script in the editor.

4. 5.

Note: Do not change this script or any of the other scripts.

6.

This script has already been run to create the Patients table in the ContosoMedicalDB database. Examine the schema of this table, which is summarized in the following table.
Column PatientID Description The primary key and also an IDENTITY column so the database creates a value automatically. The first name of the patient; it cannot be NULL. The last name of the patient; it cannot be NULL. The gender of the patient; it cannot be NULL. The date of birth of the patient; it cannot be NULL. A binary column that contains the photograph of the patient. This column can be NULL.

FirstName LastName Gender DateOfBirth Photo

Lab: Modifying Data by Using ADO.NET Commands

L2-17

MCT USE ONLY. STUDENT USE PROHIBITED

7.

You will use the following stored procedures to modify data in the Patients table. In Solution Explorer, double-click the appropriate SQL script file to open each of these scripts.
Stored Procedure uspArchivePatient Description Used when a patient record is deleted and will be explained in Exercise 2, Implementing Transactional Updates. The parameters are the full name and date of birth of a patient who you want to add to the ArchivedPatients table. Deletes a patient who has a specified PatientID in the Patients table. Gets all of the columns for the patient who has the specified PatientID in the Patients table. Gets the photo for the patient who has the specified PatientID in the Patients table. This stored procedure includes an artificial delay so that, in a later exercise, you can observe the effects of executing commands asynchronously in a later exercise. Inserts a patient record into the Patients table, which contains the specified given name, surname, gender, and date of birth. The stored procedure returns the PatientID of the new patient. Updates the photograph for the patient who has the specified PatientID in the Patients table. This stored procedure includes an artificial delay, so that in a later exercise you can observe the effects of executing commands asynchronously. Updates the first name, last name, gender, and date of birth columns for the patient who has the specified PatientID in the Patients table.

uspDeletePatient

uspGetPatient

uspGetPatientPhoto

uspInsertPatient

uspSavePatientPhoto

uspUpdatePatient

8. 9.

In Solution Explorer, in the ClinicAdminClient project, double-click the ClinicAdminForm form to open the form in the form designer. Notice that there are two tabs on the tabbed control, named Doctors and Patients. You will work with the Patients tab in this lab.

L2-18

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

10. Click the tabbed control to select it, and then click the Patients tab. Examine the controls on this tab: You type the ID of a patient in the Patient ID text box and click Get Patient to retrieve information for the specified patient. The information retrieved is the name, gender, and date of birth. If the database has a photograph for the patient, this is also retrieved after a three-second delay. When patient information is returned, the name, gender, and date of birth controls are enabled so that you can modify these values. If you click Update, the new values are written to the database. If you click Delete, the current patient record is deleted from the Patients table and an entry is added in the ArchivedPatients table. The New Patient button enables you to create a new patient. You must provide the name, gender, and date of birth for the new patient, and then click Insert to add the patient record to the database. The Upload New Photo button enables you to provide a new photograph for a patient. You must supply a value in the Patient ID text box.

11. Open the ContosoMedicalUtilities project. Open the Patient.vb (or Patient.cs) file. Look at the implementation of the Patient class. There are five properties that only provide get and set access to fields: PatientID, FirstName, LastName, Gender and DateOfBirth. There is a constructor that does nothing more than initializes the fields in the class.

12. Open ContosoMedicalDAC.vb (or ContosoMedicalDAC.cs) file. This file contains data access code. The file contains all the code that you implemented in the last module, and also has four methods that you will implement in this lab. 13. On the Patients form, double-click the Get Patient button to open the getPatient_Click method. 14. Open Notepad, go to the folder E:\Labfiles\Starter\VB (Visual Basic) or E:\Labfiles\Starter\CS (Visual C#), and open the Ex1_Task2_getPatient_Click.txt file. Copy the entire contents of the file to the Clipboard. Keep Notepad open because you will open more text files during this exercise. 15. In Visual Studio, paste the code that you copied before the End Sub (Visual Basic) or the closing brace (Visual C#) as the implementation for getPatient_Click.

Lab: Modifying Data by Using ADO.NET Commands

L2-19

MCT USE ONLY. STUDENT USE PROHIBITED

16. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#) to open the code for the Data Access Component. 17. Locate the GetPatient method. This method will query the database for the patient who has the supplied ID by using the uspGetPatient stored procedure. 18. In Notepad, open the Ex1_Task2_GetPatient.txt file. Copy the entire contents of the file to the Clipboard. 19. Paste the code into the GetPatient method, immediately above the Return patient (Visual Basic) or return patient; (Visual C#) statement. 20. On the Build menu, click Build Solution, and verify that no errors or warnings occur. 21. On the Debug menu, click Start Without Debugging to start the application. 22. In the Clinic Administration Client window, click the Patients tab. 23. In the Patient ID box, type 1 and then click Get Patient. Verify that the application displays the following values.
Control First name Last name Gender DoB Value Isabella Young The Female radio button is selected. Thursday, December 31, 1964

24. Close Clinic Administration Client.

L2-20

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

Task 3: Insert a patient record


1. 2. In Solution Explorer, in the ContosoMedicalUtilities project, double-click Patient.vb (Visual Basic) or Patient.cs (Visual C#). Examine the code. Note that: 3. 4. 5. 6. There is a field for each column in the Patient table, and a property for each field. The constructor initializes each field from parameters that are passed to it.

In Solution Explorer, in the ClinicAdminClient project, right-click the ClinicAdminForm form, and then click View Code. Locate the insertPatient_Click method. In Notepad, open the Ex1_Task3_insertPatient_Click.txt file. Copy the entire contents of the file to the Clipboard. In Visual Studio, paste the contents of the Clipboard into the insertPatient_Click method. Notice that this code uses PopulatePatientObject to populate a Patient object from controls on the form. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#). Locate the InsertPatient method, which will add a patient to the database by using the uspInsertPatient stored procedure. In Notepad, open the Ex1_Task3_InsertPatient.txt file, and then copy the entire contents of the file to the Clipboard.

7.

8. 9.

10. In Visual Studio, paste the code into the InsertPatient method, immediately above the Return result (Visual Basic) or the return result; (Visual C#) statement.

Lab: Modifying Data by Using ADO.NET Commands

L2-21

MCT USE ONLY. STUDENT USE PROHIBITED

11. The InsertPatient method is not fully implemented. First you must initialize the parameters that you want to pass to the stored procedure. Add the following code (shown in bold) to the method immediately after the statement that creates the command object.
[Visual Basic] Dim command As New SqlCommand("uspInsertPatient", connection) command.CommandType = CommandType.StoredProcedure ' Add parameters to command. command.Parameters.AddWithValue("@firstName", patient.FirstName) command.Parameters.AddWithValue("@lastName", patient.LastName) command.Parameters.AddWithValue("@gender", patient.Gender) command.Parameters.AddWithValue( _ "@dateOfBirth", patient.DateOfBirth)

[Visual C#] SqlCommand command = new SqlCommand( "uspInsertPatient", connection); command.CommandType = CommandType.StoredProcedure; // Add parameters to command. command.Parameters.AddWithValue("@firstName", patient.FirstName); command.Parameters.AddWithValue("@lastName", patient.LastName); command.Parameters.AddWithValue("@gender", patient.Gender); command.Parameters.AddWithValue( "@dateOfBirth", patient.DateOfBirth);

12. The stored procedure has an output parameter, named @patientID, which indicates the PatientID value that is generated by the database. Add the following code immediately after the code you added in step 11, to configure the parameter in the command object.
[Visual Basic] Dim patientIDParam As New SqlParameter("@patientID", SqlDbType.Int) patientIDParam.Direction = ParameterDirection.Output command.Parameters.Add(patientIDParam)

[Visual C#] SqlParameter patientIDParam = new SqlParameter( "@patientID", SqlDbType.Int); patientIDParam.Direction = ParameterDirection.Output; command.Parameters.Add(patientIDParam);

L2-22

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

13. Now add the following code, immediately after the code you typed in step 12. This code executes the command and accesses the output parameter from the stored procedure.
[Visual Basic] ' Execute the command. Dim rowsAffected As Integer = command.ExecuteNonQuery() If rowsAffected = 1 Then ' Get the patient ID generated by the database for ' the new patient. patient.PatientID = CInt(command.Parameters("@patientID").Value) result = True End If

[Visual C#] // Execute the command. int rowsAffected = command.ExecuteNonQuery(); if (rowsAffected == 1) { // Get the patient ID generated by the database for // the new patient. patient.PatientID = (int)command.Parameters["@patientID"].Value; result = true; }

14. On the Build menu, click Build Solution, and verify that no errors or warnings occur. 15. On the Debug menu, click Start Without Debugging to start the application. 16. In the Clinic Administration Client window, click the Patients tab. 17. Click New Patient. 18. Fill in the First name, Last name, Gender, and Dob controls with your details. 19. Click Insert. 20. Verify that an Information dialog box appears; this dialog box confirms that the patient has been inserted. 21. In the Information dialog box, click OK. 22. Make a note of the number in the Patient ID text box. 23. Close Clinic Administration Client. 24. To verify that the data has been stored in the database, run the application again. On the Debug menu, click Start Without Debugging.

Lab: Modifying Data by Using ADO.NET Commands

L2-23

MCT USE ONLY. STUDENT USE PROHIBITED

25. In the Clinic Administration Client window, click the Patients tab. 26. In the Patient ID box, type the number that you obtained in step 21. 27. Click Get Patient and verify that the application displays your details. 28. Close Clinic Administration Client.

Task 4: Update a patient record


1. 2. 3. 4. 5. In Solution Explorer, in the ClinicAdminClient project, right-click the ClinicAdminForm form, and then click View Code. Locate the updatePatient_Click method in the code editor. In Notepad, open the Ex1_Task4_updatePatient_Click.txt file, and copy the entire contents of the file to the Clipboard. In Visual Studio, paste the contents of the Clipboard into the updatePatient_Click method. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#). Locate the UpdatePatient method. This method will update a patient in the database by using the uspUpdatePatient stored procedure. In Notepad, open the Ex1_Task4_UpdatePatient.txt file, and copy the entire contents of the file to the Clipboard. In Visual Studio, paste the code into the UpdatePatient method immediately above the Return result (Visual Basic) or the return result; (Visual C#) statement. On the Build menu, click Build Solution, and verify that no errors or warnings occur.

6. 7. 8.

9.

10. On the Debug menu, click Start Without Debugging to start the application. 11. On the Clinic Administration Client window, click the Patients tab. 12. In the Patient ID box, type the number that you obtained in Task 3. 13. Click Get Patient and verify that the application displays your details. 14. Change some of your details; for example, change your given name to all uppercase, or add or remove 10 years from your date of birth. 15. Click Update.

L2-24

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

16. Verify that an Information dialog box appears; this dialog box confirms that the patient record has been updated. 17. In the Information dialog box, click OK. 18. Close Clinic Administration Client. 19. To verify that the changes were stored in the database, run the application again. On the Debug menu, click Start Without Debugging. 20. In the Clinic Administration Client window, click the Patients tab. 21. In the Patient ID box, type the number that you obtained in Task 3. 22. Click Get Patient and verify that the application displays your new details. 23. Close Clinic Administration Client.

Task 5: Delete a patient record


1. 2. 3. 4. 5. In Solution Explorer, in the ClinicAdminClient project, right-click the ClinicAdminForm form, and then click View Code. Locate the deletePatient_Click method in the code editor. In Notepad, open the Ex1_Task5_ deletePatient_Click.txt file, and copy the entire contents of the file to the Clipboard. In Visual Studio, paste the contents of the Clipboard into the deletePatient_Click method. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#). Locate the DeletePatient method. This method will delete a patient in the database by using the uspDeletePatient stored procedure. In Notepad, open the Ex1_Task5_DeletePatient.txt file, and copy the entire contents of the file to the Clipboard. In Visual Studio, paste the code into the DeletePatient method immediately above the Return result (Visual Basic) or the return result; (Visual C#) statement. On the Build menu, click Build Solution, and verify that no errors or warnings occur.

6. 7. 8.

9.

10. On the Debug menu, click Start Without Debugging to start the application.

Lab: Modifying Data by Using ADO.NET Commands

L2-25

MCT USE ONLY. STUDENT USE PROHIBITED

11. In Clinic Administration Client, click the Patients tab. 12. In the Patient ID box, type the number that you obtained in Task 3. 13. Click Get Patient and verify that your details are returned. 14. Click Delete. 15. Verify that an Information dialog box appears, confirming that the patient has been deleted. Close the Information dialog box. 16. In the Patient ID box, type the number that you obtained in Task 3. 17. Click Get Patient. 18. Verify that a Warning dialog box appears; this dialog box indicates that the patient ID is unrecognized. This confirms that the application successfully deleted your patient record from the database. Close the Warning dialog box. 19. Close Clinic Administration Client.
Results: After this exercise, you should have been able to view an existing patient record, insert a new patient record, change the details of an existing patient record, and delete a patient record.

Exercise 2: Implementing Transactional Updates


Task 1: Examine the ArchivedPatients table
1. 2. 3. In Solution Explorer, in the ContosoMedicalDatabases project, expand the Create Scripts node. Double-click ContosoMedicalDB.dbo.ArchivedPatients.SQL to open the script in the editor. Examine the schema of the ArchivedPatients table, in particular notice that: 4. There are two columns and no primary key. Both columns must have a value. The FullName column is the combination of the first name and last name.

In Solution Explorer, double-click ContosoMedicalDB.dbo.uspArchivePatient.SQL to open the script in the editor.

L2-26

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

5.

Notice that there are two parts to the stored procedure: A check is performed on the @fullName parameter. If the parameter value is Dummy Patient, the stored procedure raises an error and the stored procedure exits. If the @fullName parameter is not Dummy Patient, the stored procedure inserts a row into the ArchivedPatients table.

Task 2: Add transactional behavior to the DeletePatient method


1. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#). Locate the DeletePatient method. Immediately above the Try block, add the following code (shown in bold) to declare the reference.
[Visual Basic] Dim result As Boolean = False Dim connection As SqlConnection = Nothing Dim transaction As SqlTransaction = Nothing Try

2. 3.

[Visual C#] bool result = false; SqlConnection connection = null; SqlTransaction transaction = null; try {

4.

Add the following code (shown in bold) immediately after the connection is opened. This code creates a transaction from an opened connection.
[Visual Basic] ' Open a database connection. connection = GetConnection() connection.Open() transaction = connection.BeginTransaction()

Lab: Modifying Data by Using ADO.NET Commands

L2-27

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] // Open a database connection. connection = GetConnection(); connection.Open(); transaction = connection.BeginTransaction();

5.

Scroll to the code that creates the command to call uspDeletePatient and add the following code that is shown in bold (note the comma) to enlist the two commands into the transaction.
[Visual Basic] Dim command As New SqlCommand( _ "uspDeletePatient", connection, transaction)

[Visual C#] SqlCommand command = new SqlCommand( "uspDeletePatient", connection, transaction);

6.

Locate the code that creates the command to invoke the uspArchivePatient stored procedure, and then add the transaction to end of the parameter list for the SqlCommand constructor. Add the following code that is shown in bold (note the comma).
[Visual Basic] Dim archiveCommand As New SqlCommand( _ "uspArchivePatient", connection, transaction)

[Visual C#] SqlCommand archiveCommand = new SqlCommand( "uspArchivePatient", connection, transaction);

L2-28

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

7.

Add the following code (shown in bold) immediately after the command is executed. If the second command fails (uspArchivePatient), the results of the first command (uspDeletePatient) are rolled back.
[Visual Basic] ' Execute the command. rowsAffected = archiveCommand.ExecuteNonQuery() If rowsAffected = 1 Then ' Commit the transaction. result = True transaction.Commit() Else ' Rollback the transaction. transaction.Rollback() End If

[Visual C#] // Execute the command. rowsAffected = archiveCommand.ExecuteNonQuery(); if (rowsAffected == 1) { // Commit the transaction. result = true; transaction.Commit(); } else { // Rollback the transaction. transaction.Rollback(); }

Lab: Modifying Data by Using ADO.NET Commands

L2-29

MCT USE ONLY. STUDENT USE PROHIBITED

8.

Add the following code immediately before the Finally (or finally) clause. If any errors are generated by the database, they are returned as SqlExceptions. This code catches the exception, rolls back the transaction, and rethrows the exception.
[Visual Basic] Catch ex As SqlException ' Rollback the transaction and then rethrow the exception. transaction.Rollback() Throw Finally

[Visual C#] catch (SqlException) { // Rollback the transaction and then rethrow the exception. transaction.Rollback(); throw; } finally

Task 3: Verify that the transaction commits if all of the operations succeed
1. 2. 3. 4. 5. 6. 7. 8. 9. On the Build menu, click Build Solution, and verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. In the Clinic Administration Client window, click the Patients tab. Click New Patient. Fill in the First name, Last name, Gender, and Dob controls with your own details. Click Insert. Verify that an Information dialog box appears, confirming that the patient has been inserted. Close the Information dialog box. Make a note of the value in the Patient ID box. Click Delete to delete the patient that you just added.

L2-30

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

10. Verify that an Information dialog box appears; this dialog box confirms that the patient has been deleted. Close the Information dialog box. 11. In the Patient ID box, type the number you noted in step 8, and then click Get Patient. 12. Verify that a Warning dialog box appears, which indicates that the patient ID is unrecognized. This confirms that the application successfully deleted your patient record from the database, and that the transaction was committed. Close the Warning dialog box. 13. Close Clinic Administration Client.

Task 4: Verify that the transaction rolls back if an error occurs


1. 2. 3. 4. On the Debug menu, click Start Without Debugging to start the application. In the Clinic Administration Client window, click the Patients tab. Click New Patient. Fill in the controls with the following values; make sure that you use the exact spelling and capitalization as given here (ignore the other controls).
Control First name Last name Value Dummy Patient

5. 6. 7. 8. 9.

Click Insert. Verify that an Information dialog box appears; this dialog box confirms that the patient has been inserted. Make a note of the new patient ID. Close the Information dialog box. Click Delete. Verify that an error dialog box appears; this dialog box indicates that the application could not archive Dummy Patient. Close the error dialog box.

10. Close the application. 11. Start the application again. 12. In the Clinic Administration Client window, click the Patients tab.

Lab: Modifying Data by Using ADO.NET Commands

L2-31

MCT USE ONLY. STUDENT USE PROHIBITED

13. In the Patient ID text box, type the patient ID that you obtained in step 6. 14. Click Get Patient. 15. Confirm that the Dummy Patient is retrieved from the database indicating that the patient was not deleted in step 8.
Results: After this exercise you should have implemented transactional semantics for the Delete button so that either items are deleted and archived as one operation or do not happen at all.

Exercise 3: Executing Commands Asynchronously


Task 1: Add the Asynchronous Processing flag to the connection string
1. 2. In Solution Explorer, in the ClinicAdminClient project, double-click app.config (App.config). Locate the connectionString attribute for the ContosoMedicalDBConnectionString connection string. Append the following flag to the end of the string and ensure that there is a semicolon separating this string from the string before it.
Asynchronous Processing=true

The complete connection string looks like the following example (note that this is one line in the configuration file).
Data Source=.\SQLEXPRESS; Initial Catalog=ContosoMedicalDB; Integrated security=true; Persist Security Info=False; Asynchronous Processing=true

3.

On the File menu, click Save App.config.

L2-32

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Implement code to asynchronously upload a photograph for a patient


1. 2. 3. 4. In Solution Explorer, in the ClinicAdminClient project, double-click the ClinicAdminForm form. Double-click the Upload New Photo button to open the uploadNewPhoto_Click method in the code editor. In Notepad, open the Ex3_Task2_uploadNewPhoto_Click.txt file. Copy the entire contents of the file to the Clipboard. In Visual Studio, paste the code into the uploadNewPhoto_Click method. The new code in the uploadNewPhoto_Click method displays a File Open dialog box to enable the user to provide the name of the photo file. The method then reads the file into a stream. This stream is passed to the BeginSavePhoto method that is described in the following table.
Code BeginSavePhoto Description This method starts the asynchronous call. You pass the file stream for the photograph and a delegate to the SavePhotoCallback method. This method is invoked when the asynchronous call completes. The method is invoked on the thread that executes the command. This delegate is declared to call the SavePhotoUI method. This method is called to update the user interface on the user interface thread.

SavePhotoCallback

SavePhotoUIDelegate

SavePhotoUI

5. 6. 7.

In Notepad, open the Ex3_Task2_SavePhotoCallback.txt file, and then copy the entire contents of the file to the Clipboard. In Visual Studio, immediately after the end of the uploadNewPhoto_Click method, paste the code from the Clipboard. In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#).

Lab: Modifying Data by Using ADO.NET Commands

L2-33

MCT USE ONLY. STUDENT USE PROHIBITED

8. 9.

In Notepad, open the Ex3_Task2_BeginSavePhoto.txt file, and then copy the entire contents of the file to the Clipboard. In Visual Studio, after the end of the DeletePatient method, paste the code from the Clipboard.

Task 3: Verify that the application uploads photographs successfully


1. 2. 3. 4. 5. 6. 7. On the Build menu, click Build Solution, and verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. In the Clinic Administration Client window, click the Patients tab. In the Patient ID box, type 1 Click Upload New Photo. In the Open dialog box, go to E:\Labfiles\Starter, click female.jpg, and then click Open. Verify that the application displays the photo immediately. Then, three seconds later, verify that a dialog box appears, which indicates that the photo was saved successfully. Close the dialog box. Close the Clinic Administration Client window.

8.

Task 4: Implement code to asynchronously get a photograph for a patient


1. 2. In Solution Explorer, in the ClinicAdminClient project, right-click the ClinicAdminForm form, and then click View Code. Locate the getPatient_Click method in the code editor.

L2-34

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Locate the code that initializes the form controls from a Patient object. Add code to invoke the GetPhoto method to retrieve the photograph for the patient from the database. Add the following code that is shown in bold.
[Visual Basic] SetFormForExistingPatient() patientFirstNameTextBox.Text = patient.FirstName patientLastNameTextBox.Text = patient.LastName patientDOBPicker.Value = patient.DateOfBirth If patient.Gender = "M" Then maleRadioButton.Checked = True Else femaleRadioButton.Checked = True End If GetPhoto(Int32.Parse(patientID))

[Visual C#] SetFormForExistingPatient(); patientFirstNameTextBox.Text = patient.FirstName; patientLastNameTextBox.Text = patient.LastName; patientDOBPicker.Value = patient.DateOfBirth; if (patient.Gender == 'M') maleRadioButton.Checked = true; else femaleRadioButton.Checked = true; GetPhoto(int.Parse(patientID));

4.

Next, you need to insert the GetPhoto method and supporting methods. These methods can go anywhere in the ClinicAdminForm class; the best place is immediately after the getPatient_Click method. Add a new line immediately after the End Sub (Visual Basic) or the closing brace (Visual C#). In Notepad, open the Ex3_Task4_GetPhoto.txt file, and then copy the entire contents of the file to the Clipboard.

5.

Lab: Modifying Data by Using ADO.NET Commands

L2-35

MCT USE ONLY. STUDENT USE PROHIBITED

6.

In Visual Studio, paste the code from the Clipboard. The code you pasted is described in the following table.
Code GetPhoto Description This code calls BeginGetPhoto on the Data Access Component, which passes the patient ID and a delegate that is initialized with the address of GetPhotoCallback. This is the callback method that is called on the asynchronous thread when the operation completes. The method finishes the asynchronous call and accesses the returned data. It then updates the user interface with the results. Because the user interface can only be updated on the user interface thread, Control.BeginInvoke is called with a delegate to a method that updates the photograph control.

GetPhotoCallback

GetPhotoUIDelegate This is the delegate type that is used by the GetPhotoCallback method to update the user interface on the user interface thread. The GetPhotoCallback method initializes an instance of GetPhotoUIDelegate and passes the instance to BeginInvoke. GetPhotoUI This is the method that is called on the user interface thread to read binary information from the data reader and to use the information to initialize the photo control.

7.

In Solution Explorer, in the ContosoMedicalUtilities project, double-click ContosoMedicalDAC.vb (Visual Basic) or ContosoMedicalDAC.cs (Visual C#). Now you implement the BeginGetPhoto method. This method can go anywhere in the ContosoMedicalDAC class, so scroll down to the BeginSavePhoto method and click the first empty line after the End Function (Visual Basic) or closing brace (Visual C#).

8.

L2-36

Module 2: Modifying Data by Using ADO.NET Commands

MCT USE ONLY. STUDENT USE PROHIBITED

9.

In Notepad, open the Ex3_Task4_BeginGetPhoto.txt file and copy the entire contents of the file to the Clipboard.

10. In Visual Studio, paste the code from the Clipboard.

Note: The BeginExecuteReader is called by using the CloseConnection behavior because the connection must remain open while the command is executing. This means that the connection cannot be closed in BeginGetPhoto, so the responsibility of closing the connection is given to the data reader object.

Task 5: Verify that the application retrieves photographs successfully


1. 2. 3. 4. On the Build menu, click Build Solution, and verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. In the Clinic Administration Client window, click the Patients tab. In the Patient ID box, type 1 and then click Get Patient. Verify that the following values in the following table are returned.
Control First name Last name Gender DoB Value Isabella Young The Female radio button is selected. 31 December 1964

5. 6. 7.

After three seconds, a photograph appears in the photo control on the right side of the form. Close the Clinic Administration Client window. Close Visual Studio.
Results: After this exercise, you should have written code that uploads and downloads a photograph asynchronously.

Lab: Using a DataSet to Retrieve and Modify Data

L3-37

MCT USE ONLY. STUDENT USE PROHIBITED

Module 3: Querying and Maintaining Data by Using DataSets

Lab: Using a DataSet to Retrieve and Modify Data


Exercise 1: Creating a Typed DataSet
Logon information:
Virtual machine: 6464A-LON-DEV-03 User name: Student Password: Pa$$w0rd

Estimated time: 90 minutes

Task 1: Start the 6464A-LON-DEV-03 virtual machine and log on as Student


1. 2. Open the Virtual Server Remote Control Client and double-click 6464A-LONDEV-03. Log on to 6464A-LON-DEV-03 as Student using the password Pa$$w0rd.

Task 2: Create a typed DataSet


1. 2. 3. Click Start, point to All Programs, click Microsoft Visual Studio 2008, and then click Microsoft Visual Studio 2008. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, go to E:\Labfiles\Starter\VB\AppointmentViewer (if you are using Visual Basic) or E:\Labfiles\Starter\CS\AppointmentViewer (if you are using Visual C#), click AppointmentViewer.sln, and then click Open. In Solution Explorer, right-click the AppointmentViewer project, point to Add, and then click New Item.

4.

L3-38

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

5.

In the Add New Item - AppointmentViewer dialog box, create a new DataSet named ContosoMedicalDataSet.xsd as follows: a. b. c. In the Categories pane, click Data. In the Templates pane, click DataSet. In the Name box, type ContosoMedicalDataSet.xsd

d. Click Add. In Solution Explorer, verify that the AppointmentViewer project now contains an item named ContosoMedicalDataSet.xsd.

Task 3: Add tables to the typed DataSet


1. Add a table named Doctors to the ContosoMedicalDataSet.xsd DataSet, which contains the ID and the full name of the doctor, as follows: a. b. In Solution Explorer, double-click ContosoMedicalDataSet.xsd to view the DataSet in the designer. From the Toolbox, drag a TableAdapter onto the DataSet designer surface. Verify that the TableAdapter Configuration Wizard window appears. In the TableAdapter Confirmation Wizard dialog box, on the Choose Your Data Connection page, click New Connection.

c.

d. In the Choose Data Source dialog box, click Microsoft SQL Server, and then click Continue. e. In the Add Connection dialog box, in the Server name box, type .\SQLEXPRESS In the Select or enter a database name box, type ContosoMedicalDB and then click OK. On the Choose Your Data Connection page, click Next. On the Save the Connection String to the Application Configuration File page, click Next. On the Choose a Command Type page, verify that the Use SQL statements option is selected, and then click Next.

f. g. h.

Lab: Using a DataSet to Retrieve and Modify Data

L3-39

MCT USE ONLY. STUDENT USE PROHIBITED

i.

On the Enter a SQL Statement page, type the following in the text box, and then click Advanced Options.
select DoctorID, FullName=FirstName + ' ' + LastName from Doctors

j. 2. 3. 4.

In the Advanced Options dialog box, clear the Generate Insert, Update and Delete statements check box, and then click OK.

On the Enter a SQL Statement page, click Next. On the Choose Methods to Generate page, clear the Create methods to send updates to the database check box, and then click Next. On the Wizard Results page, click Finish. Verify that the DataSet designer displays a table named Doctors and an associated table adapter named DoctorsTableAdapter.

5.

Add a table named Patients to the ContosoMedicalDataSet.xsd DataSet, which contains the ID, full name, gender, and date of birth of the patient, as follows: a. From the Toolbox, drag a TableAdapter onto the DataSet designer surface. Verify that the TableAdapter Configuration Wizard window appears. On the Choose Your Data Connection page, click Next. On the Choose a Command Type page, verify that the Use SQL statements option is selected, and then click Next.

b. c.

d. On the Enter a SQL Statement page, type the following in the text box, and then click Advanced Options.
select PatientID, FullName=FirstName + ' ' + LastName, Gender, DateOfBirth from Patients

L3-40

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

e. f. g. h.

In the Advanced Options dialog box, clear the Generate Insert, Update and Delete statements check box, and then click OK. On the Enter a SQL Statement page, click Next. On the Choose Methods to Generate page, clear the Create methods to send updates to the database check box, and then click Next. On the Wizard Results page, click Finish.

Verify that the DataSet designer now displays a table named Patients, with an associated table adapter named PatientsTableAdapter. 6. Add a table named Appointments to the ContosoMedicalDataSet.xsd DataSet, containing all the appointment details, as follows: a. From the Toolbox, drag a TableAdapter onto the DataSet designer surface. Verify that the TableAdapter Configuration Wizard window appears. On the Choose Your Data Connection page, click Next. On the Choose a Command Type page, select the Create new stored procedures option, and then click Next. On the Enter a SQL Statement for the SELECT Stored Procedure page, type the following in the text box, and then click Advanced Options.
select * from Appointments

a. b. c.

e.

In the Advanced Options dialog box, ensure that all the check boxes are selected, and then click OK. These options enable the user to query and modify data in the Appointments table.

f. g.

On the Enter a SQL Statement for the SELECT Stored Procedure page, click Next. On the Create the Stored Procedures page, specify the following names for the stored procedures: Select: uspGetAppointments Insert: uspInsertAppointment Update: uspUpdateAppointment Delete: uspDeleteAppointment

Lab: Using a DataSet to Retrieve and Modify Data

L3-41

MCT USE ONLY. STUDENT USE PROHIBITED

h.

Click Preview SQL Script to view the stored procedures that Visual Studio is about to generate. Verify that the uspUpdateAppointment and uspDeleteAppointment stored procedures compare the current database values with those originally retrieved by the application. These comparisons prevent the row from being updated or deleted if it has already been modified in the database. After you finish previewing the SQL script, click Close.

i. j. k.

On the Create the Stored Procedures page, click Next. On the Choose Methods to Generate page, ensure that all of the check boxes are selected, and then click Next. On the Wizard Results page, click Finish.

Verify that the DataSet designer now displays a table named Appointments, with an associated table adapter named AppointmentsTableAdapter. 7. Save ContosoMedicalDataSet.xsd.

Task 4: Add relations and constraints to the typed DataSet


1. Add a relation and foreign key constraint between the Doctors and Appointments tables in the ContosoMedicalDataSet.xsd DataSet, to represent the relationship between the DoctorID primary key in the Doctors database table and the DoctorID foreign key in the Appointments database table. Follow these steps: a. b. In the DataSet designer, right-click the Doctors table, point to Add, and then click Relation. In the Relation dialog box, specify the following information, and then click OK: Parent Table: Doctors Child Table: Appointments Key Columns: DoctorID Foreign Key Columns: DoctorID Choose what to create: Both Relation and Foreign Key Constraint

Verify that the DataSet designer displays a line that connects the Doctors and Appointments tables.

L3-42

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

c.

Right-click the DataSet designer surface, and then click Show Relation Labels. Verify that the DataSet designer displays FK_Doctors_Appointments as the label for the relation between the Doctors and Appointments tables.

2.

Add a relation and foreign key constraint between the Patients and Appointments tables in the ContosoMedicalDataSet.xsd DataSet, to represent the relationship between the PatientID primary key in the Patients database table and the PatientID foreign key in the Appointments database table. Follow these steps: a. b. In the DataSet designer, right-click the Patients table, point to Add, and then click Relation. In the Relation dialog box, specify the following information, and then click OK: Parent Table: Patients Child Table: Appointments Key Columns: PatientID Foreign Key Columns: PatientID Choose what to create: Both Relation and Foreign Key Constraint

Verify that the DataSet designer displays a relation named FK_Patients_Appointments between the Patients and Appointments tables. 3. Save ContosoMedicalDataSet.xsd.

Task 5: Review the typed DataSet class definition


1. 2. In Solution Explorer, click the Show All Files icon. In Solution Explorer, in the AppointmentViewer project, expand ContosoMedicalDataSet.xsd, and then double-click ContosoMedicalDataSet.Designer.vb (Visual Basic) or ContosoMedicalDataSet.Designer.cs (Visual C#) to open the source file in the editor.

Lab: Using a DataSet to Retrieve and Modify Data

L3-43

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Verify that the source file defines a ContosoMedicalDataSet class that contains the following strongly typed data table classes: DoctorsDataTable PatientsDataTable AppointmentsDataTable

4.

Verify that the source file defines a namespace named AppointmentViewer.ContosoMedicalDataSetTableAdapters that contains the following strongly typed table adapter classes: DoctorsTableAdapter PatientsTableAdapter AppointmentsTableAdapter

Note: In Visual Basic, the source code specifies the namespace name as ContosoMedicalDataSetTableAdapters. This namespace is implicitly nested in the root namespace for the project, AppointmentViewer.

Results: After this exercise, you should have created a typed DataSet that contains tables named Doctors, Patients, and Appointments. You should also have defined relations and constraints between the Doctors and Appointments tables, and between the Patients and Appointments tables.

Exercise 2: Retrieving Data into a DataSet


Task 1: Review the main form in the AppointmentViewer application
1. In Solution Explorer, in the AppointmentViewer project, double-click MainForm.vb (Visual Basic) or MainForm.cs (Visual C#) to open the form in the designer. Review the following features in the form: The upper DataGridView control, doctorsGridView, will display all the doctors in the DataSet Doctors table. The lower DataGridView control, appointmentsGridView, will display the appointments for the currently selected doctor and date.

2.

L3-44

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Create a typed DataSet instance


1. In Solution Explorer, in the AppointmentViewer project, right-click MainForm.vb (Visual Basic) or MainForm.cs (Visual C#), and then click View Code. Locate the comment TODO: Import the namespace that contains the TableAdapter classes, and add code to import the AppointmentViewer.ContosoMedicalDataSetTableAdapters namespace. Your code should resemble the following:
[Visual Basic] Imports AppointmentViewer.ContosoMedicalDataSetTableAdapters

2.

[Visual C#] using AppointmentViewer.ContosoMedicalDataSetTableAdapters;

3.

Locate the comment TODO: Create a typed DataSet instance, and add code to create a ContosoMedicalDataSet instance named _dataset. Your code should resemble the following:
[Visual Basic] Private _dataset As New ContosoMedicalDataSet()

[Visual C#] private ContosoMedicalDataSet _dataset = new ContosoMedicalDataSet();

Task 3: Populate the DataSet instance


1. In the MainForm class, locate the InitDataSetFromLocalFile method. If a local XML file exists, the application invokes this method during initialization, to fill the DataSet by using the data in the XML file. The XML file stores the DataSet data in DiffGram format. 2. Where indicated by the comment TODO: Fill the DataSet from a local XML file, add code to fill _dataset from the XML file specified by _xmlFileName.

Lab: Using a DataSet to Retrieve and Modify Data

L3-45

MCT USE ONLY. STUDENT USE PROHIBITED

Your code should resemble the following examples.


[Visual Basic] _dataset.ReadXml(_xmlFileName, XmlReadMode.DiffGram)

[Visual C#] _dataset.ReadXml(_xmlFileName, XmlReadMode.DiffGram);

3.

Locate the InitDataSetFromDatabase method. If the local XML file does not exist, the application invokes this method during initialization to fill the DataSet from the database.

4.

Where indicated by the comments in the InitDataSetFromDatabase method, add code to fill the Doctors, Patients, and Appointments tables in the DataSet by using a DoctorsTableAdapter, PatientsTableAdapter, and AppointmentsTableAdapter respectively. Your code should resemble the following example.
[Visual Basic] ' Fill the DataSet Doctors table. Dim doctorsTA As New DoctorsTableAdapter() doctorsTA.Fill(_dataset.Doctors) ' Fill the DataSet Patients table. Dim patientsTA As New PatientsTableAdapter() patientsTA.Fill(_dataset.Patients) ' Fill the DataSet Appointments table. Dim appointmentsTA As New AppointmentsTableAdapter() appointmentsTA.Fill(_dataset.Appointments)

L3-46

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] // Fill the DataSet Doctors table. DoctorsTableAdapter doctorsTA = new DoctorsTableAdapter(); doctorsTA.Fill(_dataset.Doctors); // Fill the DataSet Patients table. PatientsTableAdapter patientsTA = new PatientsTableAdapter(); patientsTA.Fill(_dataset.Patients); // Fill the DataSet Appointments table. AppointmentsTableAdapter appointmentsTA = new AppointmentsTableAdapter(); appointmentsTA.Fill(_dataset.Appointments);

Task 4: Display all of the doctors


1. 2. In the MainForm class, locate the MainForm_Load method. Where indicated by the comment TODO: Display all doctors, add code to iterate through all of the rows in the DataSet Doctors table, and add each doctor to the doctorsGridView control.

Tip: To add a row to the grid view, invoke the doctorsGridView.Rows.Add method. Pass two parameters into the method to display the DoctorID and FullName properties for the doctor.

Your code should resemble the following examples.


[Visual Basic] ' Display all doctors. For Each doctorRow As ContosoMedicalDataSet.DoctorsRow _ In _dataset.Doctors doctorsGridView.Rows.Add(doctorRow.DoctorID, doctorRow.FullName) Next

Lab: Using a DataSet to Retrieve and Modify Data

L3-47

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] foreach (ContosoMedicalDataSet.DoctorsRow doctorRow in _dataset.Doctors) { doctorsGridView.Rows.Add(doctorRow.DoctorID, doctorRow.FullName); }

3. 4.

On the Build menu, click Rebuild Solution, and then verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. Verify that the Appointment Viewer window displays a list of doctors in the upper DataGridView control.

5.

Close the Appointment Viewer window and return to Visual Studio.

Task 5: Display appointments for a particular doctor and date


1. In the MainForm class, locate the DisplayAppointments method. The application invokes this method when the user changes the currently selected doctor or date on the form. 2. Review the code at the start of the method, which performs the following tasks: a. b. c. 3. Clears the contents of the appointmentsGridView control. Gets the doctor ID and the appointment data specified by the user. Creates a filter expression to select appointments for the specified doctor and date.

Where indicated by the comment TODO: Select rows from the DataSet Appointments table, add code to select rows from the DataSet Appointments table by using the filter filter expression. Your code should resemble the following example.
[Visual Basic] Dim appointmentRows() As DataRow = _ _dataset.Appointments.Select(filter)

L3-48

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] DataRow[] appointmentRows = _dataset.Appointments.Select(filter);

4.

Where indicated by the comment TODO: Display each appointment in appointmentsGridView, add code to display each appointment as follows: a. b. c. Iterate through the appointment rows that you obtained in step 3. Get the AppointmentID, PatientID, and AppointmentDateTime columns for the appointment row. Get the row in the Patients table that corresponds to the appointment.

d. Add an item to the appointmentsGridView control to display the appointment ID, patient ID, appointment time (as a short time), patient name, patient gender, and patient date of birth (as a short date.)

Note: The appointment ID and patient ID columns are not visible in the appointmentsGridView control. These columns are included to identify the appointment and patient for other code in the application, which you will write shortly.

Your code should resemble the following example.


[Visual Basic] For Each row As DataRow In appointmentRows Dim appointmentID As Integer = CInt(row("AppointmentID")) Dim patientID As Integer = CInt(row("PatientID")) Dim appointmentDateTime As DateTime = _ CDate(row("AppointmentDateTime")) Dim patientRow As ContosoMedicalDataSet.PatientsRow = _ _dataset.Patients.FindByPatientID(patientID) appointmentsGridView.Rows.Add( _ appointmentID, _ patientID, _ appointmentDateTime.ToShortTimeString(), _ patientRow.FullName, _ patientRow.Gender, _ patientRow.DateOfBirth.ToShortDateString()) Next

Lab: Using a DataSet to Retrieve and Modify Data

L3-49

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] foreach (DataRow row in appointmentRows) { int appointmentID = (int)row["AppointmentID"]; int patientID = (int)row["PatientID"]; DateTime appointmentDateTime = (DateTime)row["AppointmentDateTime"]; ContosoMedicalDataSet.PatientsRow patientRow = _dataset.Patients.FindByPatientID(patientID); appointmentsGridView.Rows.Add( appointmentID, patientID, appointmentDateTime.ToShortTimeString(), patientRow.FullName, patientRow.Gender, patientRow.DateOfBirth.ToShortDateString()); }

5. 6.

On the Build menu, click Rebuild Solution, and verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. Verify that the Appointment Viewer window displays a list of doctors in the upper DataGridView control.

7.

Select the following details in the Appointment Viewer window: Doctor: Ian Jenkins Date: Monday, June 02, 2008

Verify that the application displays the following appointments for the selected doctor and date.
11:00 11:30 12:00 11:30 AM, AM, PM, AM, Isabella Young, Justin Harris, Jenna Parker, Heidi Chandra, F, M, F, F, 12/31/1964 2/1/1966 12/5/1974 1/19/1985

8.

Select the following details in the Appointment Viewer window: Doctor: Ian Jenkins Date: Tuesday, June 03, 2008

L3-50

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

Verify that the application displays the following appointments for the selected doctor and date.
11:00 AM, Olivia Torres, 11:30 AM, Gabriel Chow, 12:00 PM, Fernando King, F, 9/27/1974 M, 12/3/1991 M, 1/2/1980

9.

Select the following details in the Appointment Viewer window: Doctor: Chloe Young Date: Tuesday, June 03, 2008

Verify that the application displays the following appointments for the selected doctor and date.
11:00 AM, Derrick Alonso, M, 6/7/1984 2:00 PM, Meghan Gutierrez, F, 9/8/1978

10. Close the Appointment Viewer window and return to Visual Studio.
Results: After this exercise, you should have created a DataSet instance, populated it from a database or from a local XML file, and displayed the data in a form.

Exercise 3: Modifying Data in a DataSet


Task 1: Review the form to edit appointment notes in the AppointmentViewer application
1. In Solution Explorer, in the AppointmentViewer project, double-click EditNotesForm.vb (Visual Basic) or EditNotesForm.cs (Visual C#) to open the form in the designer. Verify that the form contains a text box named notesTextBox that enables the user to view and edit the notes for a particular appointment. On the View menu, click Code to view the code for the EditNotesForm class. Verify that the EditNotesForm class has a property named Notes that gets and sets the text value in the notesTextBox control.

2. 3. 4.

Lab: Using a DataSet to Retrieve and Modify Data

L3-51

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Modify appointment notes in the DataSet


1. In Solution Explorer, in the AppointmentViewer project, right-click MainForm.vb (Visual Basic) or MainForm.cs (Visual C#), and then click View Code. Locate the appointmentsGridView_DoubleClick method. The application invokes this method when the user double-clicks an appointment in the appointmentsGridView control. 3. Where indicated by the comment TODO: Lookup the appointment row in the DataSet Appointments table, add code to get the row in the Appointments table for the specified appointmentID value. Your code should resemble the following example.
[Visual Basic] Dim appointmentRow As ContosoMedicalDataSet.AppointmentsRow = _ _dataset.Appointments.FindByAppointmentID(appointmentID)

2.

[Visual C#] ContosoMedicalDataSet.AppointmentsRow appointmentRow = _dataset.Appointments.FindByAppointmentID(appointmentID);

4.

Where indicated by the comment TODO: Set the Notes property on the form, add code to set the Notes property on the EditNotesForm instance to display the notes for the current appointment in the DataSet. Your code should resemble the following example.
[Visual Basic] form.Notes = appointmentRow.Notes

[Visual C#] form.Notes = appointmentRow.Notes;

5.

Where indicated by the comment TODO: Store the appointment notes in the appointment row, add code to retrieve the Notes value from the form and assign it to the Notes property for the appointment in the DataSet.

L3-52

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

Your code should resemble the following example.


[Visual Basic] appointmentRow.Notes = form.Notes

[Visual C#] appointmentRow.Notes = form.Notes;

Task 3: Build and test the application


1. 2. 3. On the Build menu, click Rebuild Solution, and verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. Select the following details in the Appointment Viewer window: 4. Doctor: Ian Jenkins Date: Monday, June 02, 2008

In the lower DataGridView control, double-click the first appointment. Verify that the Appointment Notes window displays No notes.

5. 6.

Type new notes into the text box, and then click OK to return to the Appointment Viewer window. In the Appointment Viewer window, in the lower DataGridView control, double-click the first appointment again. Verify that the Appointment Notes window displays the notes that you entered in the previous step.

7.

Close the Appointment Notes window and the Appointment Viewer window, and return to Visual Studio.
Results: After this exercise, you should have modified the appointment notes in the Appointments table in the DataSet.

Lab: Using a DataSet to Retrieve and Modify Data

L3-53

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 4: Saving a DataSet and Resolving Conflicts


Task 1: Pass the DataSet instance into a form to enable the user to save the DataSet
1. In Solution Explorer, in the AppointmentViewer project, double-click CloseApplicationForm.vb (Visual Basic) or CloseApplicationForm.cs (Visual C#) to open the form in the designer. Verify that the form contains four buttons. You will implement the following functionality for the buttons in the form.
Button Save Locally Description of functionality Save the entire DataSet to a local XML file as a DiffGram, which retains information about the modifications made by the user. Save the Appointments table in the DataSet to the database. Discard all of the modifications made to the DataSet since it was downloaded from the database. Cancel the close-form operation.

2.

Save to Database

Discard Changes

Cancel

3. 4.

On the View menu, click Code to view the code for the CloseApplicationForm class. Locate the comment TODO: Import the namespace that contains the TableAdapter classes, and add code to import the AppointmentViewer.ContosoMedicalDataSetTableAdapters namespace. Your code should resemble the following example.
[Visual Basic] Imports AppointmentViewer.ContosoMedicalDataSetTableAdapters

[Visual C#] using AppointmentViewer.ContosoMedicalDataSetTableAdapters;

5.

Locate the comment TODO: Declare a typed DataSet variable, and then add code to declare a ContosoMedicalDataSet instance named _dataset.

L3-54

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

Your code should resemble the following: example.


[Visual Basic] Private _dataset As ContosoMedicalDataSet

[Visual C#] private ContosoMedicalDataSet _dataset;

6.

Locate the comment TODO: Retain a reference to the DataSet instance. Modify the constructor signature to receive a ContosoMedicalDataSet parameter, and then add code inside the constructor to initialize the _dataset instance variable. Your code should resemble the following. The new code is shown in bold.
[Visual Basic] Public Sub New(ByVal dataset As ContosoMedicalDataSet) InitializeComponent() _dataset = dataset End Sub

[Visual C#] public CloseApplicationForm(ContosoMedicalDataSet dataset) { InitializeComponent(); _dataset = dataset; }

7.

In Solution Explorer, in the AppointmentViewer project, right-click MainForm.vb (Visual Basic) or MainForm.cs (Visual C#), and then click View Code. Locate the MainForm_FormClosing method. The application invokes this method when the user closes the main form in the application. The method is empty at the moment; you will copy the code for this method from a file on disk.

8.

9.

In Notepad, go to the folder E:\Labfiles\Starter\VB (Visual Basic) or E:\Labfiles\Starter\CS (Visual C#), and then open the Ex4_Task1.txt file. Copy the entire contents of the file to the Clipboard.

10. In Visual Studio, paste the code into the body of the MainForm_FormClosing method.

Lab: Using a DataSet to Retrieve and Modify Data

L3-55

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Save the DataSet to a local XML file


1. In Solution Explorer, in the AppointmentViewer project, right-click CloseApplicationForm.vb (Visual Basic) or CloseApplicationForm.cs (Visual C#), and then click View Code. Locate the saveLocally_Click method, and add code to save the entire DataSet as an XML file in DiffGram format. Specify _xmlFileName as the name of the XML file. Your code should resemble the following example.
[Visual Basic] _dataset.WriteXml(_xmlFileName, XmlWriteMode.DiffGram)

2.

[Visual C#] _dataset.WriteXml(_xmlFileName, XmlWriteMode.DiffGram);

Task 3: Save the DataSet to the database


1. Locate the saveToDatabase_Click method, and add code to save the DataSet Appointments table to the database as follows: a. b. Create an AppointmentsTableAdapter object. Handle the RowUpdated event on the data adapter for the AppointmentsTableAdapter object. Specify Adapter_RowUpdated as the name of the event handler method. Invoke the Update method on the AppointmentsTableAdapter object, which saves the DataSet Appointments table to the database.

c.

Your code should resemble the following example.


[Visual Basic] Dim ta As New AppointmentsTableAdapter() AddHandler ta.Adapter.RowUpdated, AddressOf Adapter_RowUpdated ta.Update(_dataset.Appointments)

L3-56

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] AppointmentsTableAdapter ta = new AppointmentsTableAdapter(); ta.Adapter.RowUpdated += new SqlRowUpdatedEventHandler(Adapter_RowUpdated); ta.Update(_dataset.Appointments);

2.

Add the Adapter_RowUpdated event-handler method, and implement it so that it detects and resolves optimistic concurrency conflicts, as follows: a. b. Test the RecordsAffected property of the SqlRowUpdatedEventArgs parameter. If RecordsAffected is zero, it indicates that the attempt to update a row in the DataSet Appointments table failed. In this case, display the appointment notes in a message box, and specify that the row should be skipped.

Your code should resemble the following example.


[Visual Basic] Private Sub Adapter_RowUpdated(ByVal sender As Object, _ ByVal e As SqlRowUpdatedEventArgs) If e.RecordsAffected = 0 Then MessageBox.Show( _ e.Row("Notes").ToString(), _ "Optimistic Concurrency Error - Notes Not Saved", _ MessageBoxButtons.OK, _ MessageBoxIcon.Warning) e.Status = UpdateStatus.SkipCurrentRow End If End Sub

Lab: Using a DataSet to Retrieve and Modify Data

L3-57

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] void Adapter_RowUpdated(object sender, SqlRowUpdatedEventArgs e) { if (e.RecordsAffected == 0) { MessageBox.Show( e.Row["Notes"].ToString(), "Optimistic Concurrency Error - Notes Not Saved", MessageBoxButtons.OK, MessageBoxIcon.Warning); e.Status = UpdateStatus.SkipCurrentRow; } }

3.

Locate the discardChanges_Click method, and then add code to discard changes to the DataSet Appointments table. Your code should resemble the following example.
[Visual Basic] _dataset.Appointments.RejectChanges()

[Visual C#] _dataset.Appointments.RejectChanges();

Task 4: Verify that the application saves DataSet data


1. 2. 3. On the Build menu, click Rebuild Solution, and verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging to start the application. Select the following details in the Appointment Viewer window: 4. 5. Doctor: Ian Jenkins Date: Monday, June 02, 2008

In the lower DataGridView control, double-click the first appointment. Type new notes into the text box, and then click OK to return to the Appointment Viewer window.

L3-58

Module 3: Querying and Maintaining Data by Using DataSets

MCT USE ONLY. STUDENT USE PROHIBITED

6. 7.

Close the Appointment Viewer window. In the Save Changes? dialog box, click Save Locally. In Visual Studio, in Solution Explorer, expand the AppointmentViewer project, expand the bin folder, and then expand the Debug folder. Verify that the Debug folder contains a file named ContosoMedicalDataSet.xml, which contains the DataSet data that you just saved.

Note: If the bin folder is not visible in Solution Explorer, click the Show All Files button.

8. 9.

In Visual Studio, on the Debug menu, click Start Without Debugging to start the application again. Select the following details in the Appointment Viewer window: Doctor: Ian Jenkins Date: Monday, June 02, 2008

10. In the lower DataGridView control, double-click the first appointment. Verify that the Appointment Notes window displays the notes that you provided earlier. This confirms that the application has saved and restored the DataSet data to the local XML file successfully. 11. Close the Appointment Notes window and then close the Appointment Viewer window. In the Save Changes? dialog box, click Save to Database.

Task 5: Verify that the application detects and resolves optimistic concurrency conflicts
1. 2. In Visual Studio, on the Debug menu, click Start Without Debugging to start the application. Modify appointment notes in the Appointment Viewer window, as follows: Select the doctor Ian Jenkins. Select the date Monday, June 02, 2008. Edit the notes for the first appointment.

Do not close the Appointment Viewer window yet.

Lab: Using a DataSet to Retrieve and Modify Data

L3-59

MCT USE ONLY. STUDENT USE PROHIBITED

3. 4.

Switch back to Visual Studio. On the Debug menu, click Start Without Debugging to start another instance of the Appointment Viewer application. Modify appointment notes in the new Appointment Viewer window, as follows: Select the doctor Ian Jenkins. Select the date Monday, June 02, 2008. Edit the notes for all the appointments.

5.

Switch to the first Appointment Viewer window, and then close the window. In the Save Changes? dialog box, click Save to Database. Verify that the application closes without any errors, which indicates that the application saved the data to the database successfully.

6.

Close the other Appointment Viewer window. In the Save Changes? dialog box, click Save to Database. Verify that the application displays a message box that indicates an optimistic concurrency error was detected because it has already been updated in the database. Verify that no other error messages appear; this indicates that the application saved the other appointments successfully.

7. 8.

In Visual Studio, on the Debug menu, click Start Without Debugging to start another instance of the Appointment Viewer application. Verify that the application displays the correct appointment notes, as follows: Select the doctor Ian Jenkins. Select the date Monday, June 02, 2008. Verify that the first appointment contains the notes that you supplied in the first Appointment Viewer window. Verify that the other appointments contain the notes that you supplied in the second Appointment Viewer window.

9.

Close the Appointment Viewer window.

10. Close Visual Studio.


Results: After this exercise, you should have saved a DataSet to a local XML file or to the database. You should also have detected and resolved optimistic concurrency errors that might occur when a DataSet is saved to the database.

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-61

MCT USE ONLY. STUDENT USE PROHIBITED

Module 4: Querying and Maintaining Data by Using LINQ

Lab: Querying and Maintaining Data by Using LINQ to SQL


Exercise 1: Defining Entity Classes
Logon information: Virtual machine: 6464A-LON-DEV-04 User name: Student Password: Pa$$w0rd

Estimated time: 75 minutes The following are the detailed steps for the exercise.

Task 1: Open the PrescriptionManager application


1. 2. 3. Click Start, point to All Programs, click Microsoft Visual Studio 2008, and then click Microsoft Visual Studio 2008. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, go to E:\Labfiles\Starter\VB\PrescriptionManager (if you are using Microsoft Visual Basic development system) or E:\Labfiles\Starter\CS\ PrescriptionManager (if you are using Microsoft Visual C# development tool), click PrescriptionManager.sln, and then click Open.

Task 2: Generate LINQ to SQL entity classes


1. In Solution Explorer, right-click the PrescriptionManager project, point to Add, and then click New Item.

L4-62

Module 4: Querying and Maintaining Data by Using LINQ

MCT USE ONLY. STUDENT USE PROHIBITED

2.

In the Add New Item - PrescriptionManager dialog box, create a LINQ to SQL project item named ContosoMedicalDataClasses.dbml, as follows: a. b. c. In the Categories pane, click Data. In the Templates pane, click LINQ to SQL Classes. In the Name box, type ContosoMedicalDataClasses.dbml

d. Click Add. Verify that Visual Studio displays ContosoMedicalDataClasses.dbml in the Object Relational Designer window. 3. In Server Explorer, open a connection to the ContosoMedicalDB database on the local instance of Microsoft SQL Server 2005 Express Edition, as follows: a. b. c. If Server Explorer is not visible, on the View menu, click Server Explorer. In Server Explorer, right-click Data Connections, and then click Add Connection. In the Choose Data Source dialog box, click Microsoft SQL Server, and then click Continue.

d. In the Add Connection dialog box, in the Server name box, type .\SQLEXPRESS e. 4. In the Select or enter a database name box, type ContosoMedicalDB and then click OK.

Generate an entity class to represent the Patients database table, as follows: a. b. c. In Server Explorer, expand the connection for the ContosoMedicalDB database, and then expand Tables. Drag the Patients table onto the left pane in the Object Relational Designer. Verify that the Object Relational Designer displays a box named Patient. This is the entity class that corresponds to the Patients database table.

5.

Delete the Photo property in the Patient entity class because the application does not need to access or view this information. Follow these steps: a. b. In the Patient box, click the Photo property. Press DELETE to delete the Photo property from the Patient entity class.

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-63

MCT USE ONLY. STUDENT USE PROHIBITED

6.

Generate an entity class to represent the Prescriptions database table, as follows: a. b. In Server Explorer, drag the Prescriptions table onto the left pane in the Object Relational Designer. Verify that the Object Relational Designer displays a box named Prescription. This is the entity class that corresponds to the Prescriptions database table.

Task 3: Define an association between entity classes


1. 2. In the Object Relational Designer, right-click the upper section of the Patient box, point to Add, and then click Association. In the Association Editor dialog box, define a one-to-many association between the Patient entity class and the Prescription entity class, as follows: a. b. c. In the Parent Class list, verify that Patient is selected. Expand the Child Class list, and then click Prescription. In the Association Properties table, in the Patient Properties column, expand the first item in the list, and then click PatientID. In the Prescription Properties column, expand the first item in the list, and then click PatientID.

d. Click OK. 3. Verify that the Object Relational Designer displays a one-to-many association between the Patient and Prescription entity classes. The association appears as an arrow from the Patient box to the Prescription box.

Task 4: View the generated classes


1. 2. If you are using Visual Basic, in Solution Explorer, click the Show All Files button. In Solution Explorer, in the PrescriptionManager project, expand ContosoMedicalDataClasses.dbml, and then double-click ContosoMedicalDataClasses.designer.vb (Visual Basic) or ContosoMedicalDataClasses.designer.cs (Visual C#).

L4-64

Module 4: Querying and Maintaining Data by Using LINQ

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Locate the ContosoMedicalDataClassesDataContext class. This is a typed DataContext class that provides type-safe access to tables of Patient and Prescription entity objects. The following table describes some of the members in the ContosoMedicalDataClassesDataContext class.
Member Patients Prescriptions Description Gets a table of Patient entity objects Gets a table of Prescription entity objects

4.

Locate the Patient class. This is an entity class that maps to the Patients table in the ContosoMedicalDB database. The following table describes some of the members in the Patient class.
Member _Prescriptions Description Instance variable that contains an EntitySet of Prescription entities for a patient Property mapped to the PatientID column Property mapped to the FirstName column Property mapped to the LastName column Property mapped to the Gender column Property mapped to the DateOfBirth column Property that gets or sets the prescriptions for the patient. This property is annotated with an Association attribute that describes the one-to-many association between the Patient and Prescription entity classes.

PatientID FirstName LastName Gender DateOfBirth Prescriptions

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-65

MCT USE ONLY. STUDENT USE PROHIBITED

5.

Locate the Prescription class. This is an entity class that maps to the Prescriptions table in the ContosoMedicalDB database. The following table describes some of the members in the Prescription class.
Member _Patient Description Instance variable that contains an EntityRef that refers to the Patient entity for a prescription Property mapped to the PrescriptionID column Property mapped to the PatientID column Property mapped to the Description column Property mapped to the IssueDate column Property mapped to the RepeatCount column Property that gets or sets the patient for the prescription. This property is annotated with an Association attribute that describes the one-to-many association between the Patient and Prescription entity classes.

PrescriptionID PatientID Description IssueDate RepeatCount Patient

Results: After this exercise, you should have generated entity classes for the Patients and Prescriptions tables in the ContosoMedicalDB database, and defined a one-tomany association between the entity classes.

L4-66

Module 4: Querying and Maintaining Data by Using LINQ

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 2: Retrieving Data by Using LINQ to SQL


Task 1: Review the user interface in the application
1. In Solution Explorer, in the PrescriptionManager project, double-click MainForm.vb (Visual Basic) or Mainform.cs (Visual C#) to view the form in the designer. Review the following features in the View by Patient tab in the form: The upper DataGridView control, patientsGridView, displays all of the patient records when the application starts. The lower DataGridView control, prescriptionsGridView, displays the prescriptions for a particular patient. The Repeat Prescriptions, Delete Prescriptions, and New Prescriptions buttons enable the user to modify prescription data. You will implement these features in the next exercise.

2.

3.

Click the View by Date tab in the form, and review the following features: The date picker controls, fromDatePicker and toDatePicker, enable the user to specify a date range. When the user clicks Go, the application retrieves the prescriptions in the specified date range and displays them in the prescriptionsInPeriodGridView control.

Task 2: Retrieve all of the patient records


1. 2. In Solution Explorer, right-click MainForm.vb (Visual Basic) or Mainform.cs (Visual C#), and then click View Code. Expand the Variables, initialization, and selection events code region, and then locate the TODO: Create typed DataContext object comment. Add code to create a new ContosoMedicalDataClassesDataContext object, and assign the new object to an instance variable named _db. Your code should resemble the following:
[Visual Basic] Private _db As New ContosoMedicalDataClassesDataContext()

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-67

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] private ContosoMedicalDataClassesDataContext _db = new ContosoMedicalDataClassesDataContext();

3.

Expand the View by Patient tab - display data code region, and then locate the DisplayPatients method. Where indicated by the TODO comment, add code to get and display all of the patient records from the database, as follows: a. b. Define a For Each loop (Visual Basic) or a foreach loop (Visual C#) to iterate over the entities in the _db.Patients table. On each iteration, create a string that contains the full name of the patient by concatenating the FirstName and LastName properties on the entity. Then add a row to the patientsGridView control, which contains the PatientID and full name of the patient.

Note: To add a row to the patientsGridView control, invoke the patientsGridView.Rows.Add method.

Your code should resemble the following.


[Visual Basic] For Each p As Patient In _db.Patients Dim patientName As String = p.FirstName & " " & p.LastName patientsGridView.Rows.Add(p.PatientID, patientName) Next

[Visual C#] foreach (Patient p in _db.Patients) { string patientName = p.FirstName + " " + p.LastName; patientsGridView.Rows.Add(p.PatientID, patientName); }

4. 5.

On the Build menu, click Build Solution. Verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging.

L4-68

Module 4: Querying and Maintaining Data by Using LINQ

MCT USE ONLY. STUDENT USE PROHIBITED

6. 7.

Verify that the Prescription Manager window appears, and that the upper DataGridView control displays 18 patients. Close the Prescription Manager window.

Task 3: Retrieve prescriptions for a particular patient


1. In the MainForm source file, locate the DisplayPrescriptions method. The application invokes this method when the user highlights a patient on the form. The purpose of the method is to get all of the prescriptions for the highlighted patient and display them in the prescriptionsGridView control on the form. 2. Where indicated by the first TODO comment, add code to define a LINQ query to get the prescriptions for the highlighted patient. Use the following information to help you to define the LINQ query: Specify _db.Prescripitons as the data source for the query. Define a Where clause (Visual Basic) or a where clause (Visual C#) that compares the PatientID for prescriptions with the patientID local variable, so that the query only returns prescriptions for that patient.

Your code should resemble the following.


[Visual Basic] Dim query = From prescription In _db.Prescriptions _ Where prescription.PatientID = patientID _ Select prescription

[Visual C#] var query = from prescription in _db.Prescriptions where prescription.PatientID == patientID select prescription;

3.

Where indicated by the second TODO comment, add code to display the prescriptions returned by the LINQ query, as follows: a. b. Define a For Each loop (Visual Basic) or a foreach loop (Visual C#) to iterate over the LINQ query that you defined in the previous step. On each iteration, add a row to the prescriptionsGridView control, which contains the PrescriptionID, Description, IssueDate, and RepeatCount properties for the prescription.

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-69

MCT USE ONLY. STUDENT USE PROHIBITED

Your code should resemble the following.


[Visual Basic] For Each p As Prescription In query prescriptionsGridView.Rows.Add(p.PrescriptionID, _ p.Description, _ p.IssueDate.ToShortDateString(), _ p.RepeatCount) Next

[Visual C#] foreach (Prescription p in query) { prescriptionsGridView.Rows.Add(p.PrescriptionID, p.Description, p.IssueDate.ToShortDateString(), p.RepeatCount); }

4. 5. 6.

On the Build menu, click Build Solution. Verify that no errors occur. On the Debug menu, click Start Without Debugging. Verify that the Prescription Manager window appears, and that the upper DataGridView control displays 18 patient records. Also verify that the lower DataGridView control displays the prescriptions for the first patient. In the upper DataGridView control, highlight the second patient. Verify that the lower DataGridView control now displays the prescriptions for the second patient. Close the Prescription Manager window.

7.

8.

Task 4: Retrieve prescriptions for a particular period


1. In the MainForm source file, expand the View by Date tab - display data code region, and then locate the go_Click method. The application invokes this method when the user clicks the Go button on the View by Date tab in the form, to get and display prescriptions in a particular period. Review the code that is already provided in the method.

L4-70

Module 4: Querying and Maintaining Data by Using LINQ

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Where indicated by the TODO comment, add the code provided in the Ex2_Task4.txt file that is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code performs the following tasks: a. b. Defines a LINQ query that gets the prescriptions in the specified date range, ordered by issue date. Iterates over the query results, and displays each prescription in the prescriptionsInPeriodGridView control. The code gets the name of the patient for each prescription by using the Patient.FirstName and Patient.LastName properties on the prescription entity.

3. 4. 5. 6.

On the Build menu, click Build Solution. Verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging. In the Prescription Manager window, click the View by Date tab. View the prescriptions between January 1, 2008 and March 31, 2008 as follows: a. b. c. In the From control, select Tuesday, January 01, 2008. In the To control, select Monday, March 31, 2008. Click Go.

Verify that the application displays prescriptions in the specified date range. 7. View the prescriptions between April 1, 2008 and June 30, 2008 as follows: a. b. c. In the From control, select Tuesday, April 01, 2008. In the To control, select Monday, June 30, 2008. Click Go.

Verify that the application displays prescriptions in the specified date range. 8. Close the Prescription Manager window.
Results: After this exercise, you should have defined and executed LINQ to SQL queries to get information about patients and prescriptions from the ContosoMedicalDB database.

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-71

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 3: Modifying Data by Using LINQ to SQL Retrieving


Task 1: Get a specific Prescription entity
1. In the MainForm source file, expand the View by Patient tab - modify data code region, and then locate the TODO: Define a GetPrescriptionEntity method comment. Add the code provided in the Ex3_Task1.txt file that is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

2.

The code defines the GetPrescriptionEntity method, which performs the following tasks: a. b. Defines a LINQ query that gets the prescription that matches the specified prescription ID. Invokes the First method on the LINQ query to retrieve the first, and only, entity in the query result set.

You will use the GetPrescriptionEntity method in the following tasks to locate a Prescription entity that is to be updated or deleted.

Task 2: Update a Prescription entity


1. In the MainForm source file, locate the repeatPrescriptions_Click method. The application invokes this method when the user clicks Repeat Prescriptions on the form. The purpose of the method is to increment the RepeatCount property for Prescription entities that are highlighted by the user. Review the code that has already been provided in the method. 2. Where indicated by the first TODO comment, add code to invoke the GetPrescriptionEntity method to get the Prescription entity for the prescriptionID. Your code should resemble the following.
[Visual Basic] Dim prescription As Prescription = _ GetPrescriptionEntity(prescriptionID)

L4-72

Module 4: Querying and Maintaining Data by Using LINQ

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] Prescription prescription = GetPrescriptionEntity(prescriptionID);

3.

Where indicated by the second TODO comment, add code to increment the RepeatCount property on the Prescription entity. Your code should resemble the following.
[Visual Basic] prescription.RepeatCount += 1

[Visual C#] prescription.RepeatCount++;

Note: At the end of the repeatPrescriptions_Click method, the application invokes the DoSave method. You will implement this method later in this exercise to submit the changes to the database.

4.

On the Build menu, click Build Solution. Verify that no errors or warnings occur.

Task 3: Delete a Prescription entity


1. In the MainForm source file, locate the deletePrescriptions_Click method. The application invokes this method when the user clicks Delete Prescriptions on the form. The purpose of the method is to mark a Prescription entity for deletion. Review the code that has already been provided in the method. 2. Where indicated by the first TODO comment, add code to invoke the GetPrescriptionEntity method to get the Prescription entity for the prescriptionID. Your code should resemble the following.
[Visual Basic] Dim prescription As Prescription = _ GetPrescriptionEntity(prescriptionID)

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-73

MCT USE ONLY. STUDENT USE PROHIBITED

[Visual C#] Prescription prescription = GetPrescriptionEntity(prescriptionID);

3.

Where indicated by the second TODO comment, add code to mark the Prescription entity for deletion from the _db.Prescriptions table. Your code should resemble the following.
[Visual Basic] _db.Prescriptions.DeleteOnSubmit(prescription)

[Visual C#] _db.Prescriptions.DeleteOnSubmit(prescription);

Task 4: Insert a Prescription entity


1. In the MainForm source file, locate the newPrescriptions_Click method. The application invokes this method when the user clicks New Prescriptions on the form. The purpose of the method is to enable the user to create new prescriptions for a patient. 2. Where indicated by the TODO comment, uncomment the code that creates and displays a NewPrescriptionsForm form. Your code should resemble the following.
[Visual Basic] Dim form As New NewPrescriptionsForm(patientID, _db) form.ShowDialog()

[Visual C#] NewPrescriptionsForm form = new NewPrescriptionsForm(patientID, _db); form.ShowDialog();

3.

In Solution Explorer, in the PrescriptionManager project, double-click NewPrescriptionForm.vb (Visual Basic) or NewPrescriptionForm.cs (Visual Basic) to open the form in the designer.

L4-74

Module 4: Querying and Maintaining Data by Using LINQ

MCT USE ONLY. STUDENT USE PROHIBITED

The form enables the user to select a date and to create a series of prescriptions issued on that date. Each time the user clicks Add, the form creates another Prescription entity and adds it to the DataContext. When the user clicks Done, the application returns to the main form. 4. 5. On the View menu, click Code to view the code for the NewPrescriptionForm form. In the NewPrescriptionForm source file, where indicated by the first TODO comment, add code to declare a ContosoMedicalDataClassesDataContext instance variable named _db. Your code should resemble the following.
[Visual Basic] Private _db As ContosoMedicalDataClassesDataContext

[Visual C#] private ContosoMedicalDataClassesDataContext _db;

6.

Where indicated by the second TODO comment, add the code provided in the Ex3_Task4_Constructor.txt file located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code defines a constructor that initializes the _patientID and _db instance variables. The form needs this information so that it can locate a particular Patient entity and then add Prescription entities to the DataContext. 7. Locate the add_Click method. The application invokes this method when the user clicks Add. Where indicated by the TODO comment, add the code provided in the Ex3_Task4_CreatePrescription.txt file that is located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code creates and initializes a Prescription entity, marks it for insertion into the DataContext, and then displays the prescription description on the form.

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-75

MCT USE ONLY. STUDENT USE PROHIBITED

Task 5: Save changes to the database


1. 2. Switch to the MainForm source file, and locate the Do Save method. Where indicated by the TODO: Submit changes to the database comment, add code to invoke the SubmitChanges method on the _db object. Pass ConflictMode.ContinueOnConflict into the method, so that the DataContext object attempts to complete all of the updates even if concurrency conflicts occur. Your code should resemble the following.
[Visual Basic] _db.SubmitChanges(ConflictMode.ContinueOnConflict)

[Visual C#] _db.SubmitChanges(ConflictMode.ContinueOnConflict);

3.

Where indicated by the TODO: Catch ChangeConflictException exceptions comment, add the code provided in the Ex3_Task5.txt file located in the following folder: E:\Labfiles\Starter\VB (Visual Basic) E:\Labfiles\Starter\CS (Visual C#)

The code performs the following tasks: a. b. Catches ChangeConflictException exceptions, which indicate that a concurrency conflict has occurred. Iterates over the collection of change conflicts and displays information about the object that caused a concurrency conflict; the members in conflict; and the current, original, and database values of each such member. Invokes the Resolve method to refresh the current values in memory with the latest values from the database.

c.

Task 6: Test the application


1. 2. On the Build menu, click Build Solution. Verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging.

L4-76

Module 4: Querying and Maintaining Data by Using LINQ

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Update several prescriptions for the first patient, as follows: a. b. In the lower DataGridView control, highlight several prescriptions, and then click Repeat Prescriptions. Verify that the application increases the RepeatCount for each highlighted prescription. Make a note of the prescriptions that you updated.

4.

Delete several prescriptions for the first patient, as follows: a. b. In the lower DataGridView control, highlight several prescriptions, and then click Delete Prescriptions. Verify that the application deletes each of the prescriptions that you highlighted. Make a note of the prescriptions that you deleted.

5.

Add several new prescriptions for the first patient, as follows: a. b. c. Click New Prescriptions. In the New Prescriptions for PatientID 1 dialog box, in the Issue date control, select the current date. In the Description box, type a description for a new prescription, and then click Add.

d. Verify that the Added box displays the description that you just typed. This verifies that the application has created a new prescription. e. f. g. 6. 7. 8. Repeat the previous two steps several times to create several prescriptions. Click Done to return to the main form. Verify that the application displays the new prescriptions that you just added. Make a note of the new prescriptions.

Close the Prescription Manager window. In Visual Studio, on the Debug menu, click Start Without Debugging to start the application again. In the upper DataGridView control, click the first patient record. Verify that the lower DataGridView control shows the correct set of prescriptions for the patient, taking into account the prescriptions that you updated, deleted, and added earlier in this task. In the lower DataGridView control, highlight several prescriptions. Do not click any buttons to affect the prescriptions yet; you will do so later in this task.

9.

Lab: Querying and Maintaining Data by Using LINQ to SQL

L4-77

MCT USE ONLY. STUDENT USE PROHIBITED

10. Switch back to Visual Studio. On the Debug menu, click Start Without Debugging to start another instance of the application. 11. In the upper DataGridView control, click the first patient. 12. In the lower DataGridView control, highlight a subset of the prescriptions that you highlighted in step 9, and then click Repeat Prescriptions to update these prescriptions. 13. Repeat the previous step, step 12, several times to update the RepeatCount property several times. 14. Close the second instance of the application, and return to the first instance of the application. 15. Click Repeat Prescriptions to update the highlighted prescriptions. Verify that the application detects and resolves optimistic concurrency conflicts as follows: For the prescriptions that you modified in the other instance of the application, the current instance of the application should display a message box, which indicates that an optimistic concurrency conflict has occurred. The message box should indicate the current, original, and database values of the RepeatCount property and then update the value in the application with the value from the database. For the prescriptions that you did not modify in the other instance of the application, the current instance of the application should update the prescriptions successfully.

16. Close the Prescription Manager window. 17. Close Visual Studio.
Results: After this exercise, you should have implemented functionality to enable the user to insert, update, and delete entities by using LINQ to SQL, and to detect and resolve optimistic concurrency conflicts.

Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

L5-79

MCT USE ONLY. STUDENT USE PROHIBITED

Module 5: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework
Exercise 1: Creating an Entity Data Model
Logon information: Virtual machine: 6464A-LON-DEV-05 User name: Student Password: Pa$$w0rd

Estimated time: 60 minutes

Task 1: Open the PrescriptionManager application


1. 2. 3. Click Start, point to All Programs, click Microsoft Visual Studio 2008, and then click Microsoft Visual Studio 2008. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, go to E:\Labfiles\Starter\VB\PrescriptionManager (if you are using Microsoft Visual Basic development system) or E:\Labfiles\Starter\CS\PrescriptionManager (if you are using Microsoft Visual C# development tool), click PrescriptionManager.sln, and then click Open.

L5-80

Module 5: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Generate an Entity Data Model


1. 2. In Solution Explorer, right-click the PrescriptionManager project, point to Add, and then click New Item. In the Add New Item - PrescriptionManager dialog box, create an ADO.NET Entity Data Model (EDM) named ContosoMedicalModel.edmx, as follows: a. b. c. In the Categories pane, leave the root node selected. In the Templates pane, click ADO.NET Entity Data Model. In the Name box, type ContosoMedicalModel.edmx

d. Click Add. 3. In the Entity Data Model Wizard dialog box, generate the EDM from the ContosoMedicalDB database on the local instance of Microsoft SQL Server 2005 Express Edition, and then add the Patients and Prescriptions tables to the EDM. To achieve these tasks, follow these steps: a. b. c. On the Choose Model Contents page, verify that the Generate from database option is selected, and then click Next. On the Choose Your Data Connection page, click New Connection. In the Choose Data Source dialog box, click Microsoft SQL Server, and then click Continue.

d. In the Connection Properties dialog box, in the Server name box, type .\SQLEXPRESS and then in the Select or enter a database name box, type ContosoMedicalDB and then click OK. e. f. On the Choose Your Data Connection page, click Next. On the Choose Your Database Objects page, clear the Tables and Stored Procedures check boxes. Expand the Tables option, and then select the Patients (dbo) and Prescriptions (dbo) check boxes. Verify that the Model Namespace box has the value ContosoMedicalDBModel, and then click Finish.

Verify that Visual Studio displays the ContosoMedicalModel.edmx file in the EDM designer window and that the EDM contains boxes named Patients and Prescriptions. 4. In the designer, in the Patients entity, delete the Photo scalar property. The application does not require the photograph of the patient.

Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

L5-81

MCT USE ONLY. STUDENT USE PROHIBITED

5.

In the designer, click the Patients entity. In the Properties window, set the following property values: Name: Patient Entity Set Name: Patient

6.

In the designer, click the Prescriptions entity. In the Properties window, set the following property values: Name: Prescription Entity Set Name: Prescription

Task 3: Define an association between the entities


1. 2. In the designer, right-click the upper section of the Patient box, point to Add, and then click Association. In the New Association dialog box, verify that the default options represent a one-to-many association between the Patient and Prescription entities, and then click OK. Verify that the designer displays a one-to-many association between the Patient and Prescription entities. The association appears as a line between the Patient and Prescription boxes.

3.

Task 4: Map the association between entities


1. 2. In the designer, right-click the PatientPrescription association, and then click Show in Mapping Details. In Visual Studio, at the bottom of the Mapping Details - PatientPrescription window, expand the <Add a Table or View> list, and then click Prescriptions.

Note: When you map an association, you must select the table that contains the foreign keys for the association in the database. In this example, the Prescriptions database table contains foreign keys to the Patients database table, to identify the patient for each prescription.

L5-82

Module 5: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Verify that the Mapping Details - PatientPrescription window defines the following mapping information: For the Patient entity, the PatientID (Int32) entity property is mapped to the PatientID (int) column in the database table. For the Prescription entity, the PrescriptionID (Int32) entity property is mapped to the PrescriptionID (int) column in the database table.

4.

In the main designer window, in the Prescription entity box, delete the PatientID scalar property. The Prescription entity no longer needs the PatientID scalar property, because the Patient navigation property now defines the navigability from a Prescription entity to its associated Patient entity in memory.

5.

On the Build menu, click Build Solution. Verify that there are no compiler errors or warnings.
Results: After this exercise, you should have generated an EDM that represents the Patients and Prescriptions tables in the ContosoMedicalDB database, and defined a one-to-many association between the entities in the EDM.

Exercise 2: Querying Entities in an Entity Data Model


Task 1: Review the user interface in the application
1. In Solution Explorer, in the PrescriptionManager project, double-click MainForm.vb (Visual Basic) or Mainform.cs (Visual C#) to view the form in the designer. Review the following features in the form: The upper DataGridView control, patientsGridView, will display all of the patients when the application starts. The lower DataGridView control, prescriptionsGridView, will display the prescriptions for a particular patient. The Repeat Prescriptions button will enable the user to modify selected prescriptions, by incrementing their RepeatCount property.

2.

Note: For simplicity, the application does not enable the user to insert or delete prescriptions.

Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

L5-83

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Retrieve patients


1. 2. In Solution Explorer, right-click MainForm.vb (Visual Basic) or Mainform.cs (Visual C#), and then click View Code. At the top of the source file, where indicated by the first TODO comment, import the EDM namespace that you generated in the first exercise. The namespace to import is as follows: Visual Basic: PrescriptionManager.ContosoMedicalDBModel Visual C#: ContosoMedicalDBModel

Your code should resemble the following.


[Visual Basic] Imports PrescriptionManager.ContosoMedicalDBModel

[Visual C#] using ContosoMedicalDBModel;

3.

At the top of the source file, where indicated by the second TODO comment, import the System.Data.Objects namespace. Your code should resemble the following.
[Visual Basic] Imports System.Data.Objects

[Visual C#] using System.Data.Objects;

4.

In the MainForm class, locate the DisplayPatients method. The application invokes this method during startup, to display the patients in the patientsGridView control.

5.

Where indicated by the TODO comment, add the code provided in the Ex2_Task2.txt file located in the following folder: If you are using Visual Basic: E:\Labfiles\Starter\VB If you are using Visual C#: E:\Labfiles\Starter\CS

The code creates a ContosoMedicalDBEntities object and contains TODO comments that you will implement in the following steps.

L5-84

Module 5: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

MCT USE ONLY. STUDENT USE PROHIBITED

6.

Where indicated by the TODO: Define an object query comment, define an ObjectQuery object to get all Patient entities from the database. Your code should resemble the following.
[Visual Basic] Dim patientQuery As ObjectQuery(Of Patient) = context.Patient

[Visual C#] ObjectQuery<Patient> patientQuery = context.Patient;

7.

Where indicated by the TODO: Bind the retrieved entities comment, bind the entities that are returned by the query to the patientsGridView control. Your code should resemble the following.
[Visual Basic] Me.patientsGridView.DataSource = patientQuery

[Visual C#] this.patientsGridView.DataSource = patientQuery;

8. 9.

On the Build menu, click Build Solution. Verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging.

10. Verify that the Prescription Manager window appears and that the upper DataGridView control displays 18 patients. 11. Close the Prescription Manager window.

Task 3: Retrieve prescriptions


1. In the MainForm source file, locate the DisplayPrescriptions method. The application invokes this method when the user highlights a patient on the form. The purpose of the method is to get all the prescriptions for the highlighted patient and display them in the prescriptionsGridView control on the form.

Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

L5-85

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Where indicated by the TODO comment, add the code provided in the Ex2_Task3.txt file located in the following folder: If you are using Visual Basic: E:\Labfiles\Starter\VB If you are using Visual C#: E:\Labfiles\Starter\CS

The code is complete and performs the following tasks: a. b. Creates a ContosoMedicalDBEntities object. Defines an object query to get Prescription entities for the highlighted patient. The Where method uses the syntax it.Patient.PatientID to get the Patient entity associated with the current prescription, and then the PatientID property on the Patient entity. The Where method uses the PatientID property to retrieve prescriptions for a particular patient. Iterates over the Prescription entities that are returned by the object query and displays the information in the prescriptionsGridView control.

c. 3. 4. 5.

On the Build menu, click Build Solution. Verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging. Verify that the Prescription Manager window appears and that the upper DataGridView control displays 18 patients. Verify that the lower DataGridView control displays the prescriptions for the first patient. In the upper DataGridView, click the second patient. Verify that the lower DataGridView control displays the prescriptions for the second patient. Close the Prescription Manager window.
Results: After this exercise, you should have defined and executed object queries to get information about patients and prescriptions from the ContosoMedicalDB database.

6. 7.

Exercise 3: Modifying Entities in an Entity Data Model


Task 1: Modify entities
1. In the MainForm source file, expand the Modify data code region and locate the repeatPrescriptions_Click method. The application invokes this method when the user clicks the Repeat Prescriptions button, to repeat selected prescriptions.

L5-86

Module 5: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Review the code that is already provided in the method. The code creates a string variable named prescriptionIDs that contains a list of all the prescription IDs that the user highlighted. You will use this list of prescription IDs in an Entity SQL query later in this task. Where indicated by the TODO comment, add the code provided in the Ex3_Task1.txt file located in the following folder: If you are using Visual Basic: E:\Labfiles\Starter\VB If you are using Visual C#: E:\Labfiles\Starter\CS

3.

The code performs the following tasks: a. b. Creates a ContosoMedicalDBEntities object. Defines an Entity SQL string to get the highlighted Prescription entities. The WHERE and IN operators ensure that the query only retrieves the set of Prescription entities whose PrescriptionID is in the prescriptionIDs list.

4.

Where indicated by the TODO: Create an object query to get the requested prescriptions comment, define an ObjectQuery object to retrieve Prescription entities by using the Entity SQL string. Ensure that the query overwrites any local entity values with the latest values from the database. Your code should resemble the following.
[Visual Basic] Dim prescriptionQuery As New ObjectQuery(Of Prescription)( _ sql, _ context, _ MergeOption.OverwriteChanges)

[Visual C#] ObjectQuery<Prescription> prescriptionQuery = new ObjectQuery<Prescription>(sql, context, MergeOption.OverwriteChanges);

5.

Where indicated by the TODO: For each Prescription entity, increase the RepeatCount comment, iterate over the Prescription entities that are returned by the object query. For each Prescription entity, increment the RepeatCount property.

Lab: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

L5-87

MCT USE ONLY. STUDENT USE PROHIBITED

Your code should resemble the following.


[Visual Basic] For Each p As Prescription In prescriptionQuery p.RepeatCount += 1 Next

[Visual C#] foreach (Prescription p in prescriptionQuery) { p.RepeatCount++; }

6.

Where indicated by the TODO: Save the changes to the database comment, add code to save the object context changes to the database. Your code should resemble the following.
[Visual Basic] context.SaveChanges()

[Visual C#] context.SaveChanges();

Task 2: Test the application


1. 2. 3. On the Build menu, click Build Solution. Verify that no errors or warnings occur. On the Debug menu, click Start Without Debugging. In the Prescription Manager window, verify that the upper DataGridView control displays 18 patients. Verify that the lower DataGridView control displays the prescriptions for the first patient. Click some of the rows in the lower DataGridView control, and then click Repeat Prescriptions. Verify that the application shows the incremented repeat count for the prescriptions. Close the Prescription Manager window. In Visual Studio, on the Debug menu, click Start Without Debugging.

4.

5. 6.

L5-88

Module 5: Implementing an Entity Data Model by Using the ADO.NET Entity Framework

MCT USE ONLY. STUDENT USE PROHIBITED

7.

In the Prescription Manager window, verify that the upper DataGridView control displays 18 patients. Verify that the lower DataGridView control displays the prescriptions for the first patient and that the repeat counts are the incremented values. Close the Prescription Manager window. Close Visual Studio.
Results: After this exercise, you should have modified entities and saved the changes back to the database.

8. 9.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-89

MCT USE ONLY. STUDENT USE PROHIBITED

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

Lab: Building Occasionally Connected Solutions by Using Synchronization Services


Exercise 1: Modifying a Database Schema to Support Synchronization
Logon information: Virtual machine: 6464A-LON-DEV-06 User name: Student Password: Pa$$w0rd

Estimated time: 60 minutes The following are the detailed steps for the exercise.

Task 1: Start the 6464A-LON-DEV-06 virtual machine and log on as Student


1. 2. Open the Virtual Server Remote Control Client and double-click 6464A-LONDEV-06. Log on to 6464A-LON-DEV-06 as Student using the password Pa$$w0rd.

Task 2: Add a Local Database Cache


1. 2. 3. Click Start, point to All Programs, click Microsoft Visual Studio 2008, and then click Microsoft Visual Studio 2008. In Microsoft Visual Studio, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, go to E:\Labfiles\Starter\VB\Appointments (if you are using Microsoft Visual Basic development system) or E:\Labfiles\Starter\CS\Appointments (if you are using Microsoft Visual C# development tool), click Appointments.sln, and then click Open.

L6-90

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

4. 5.

In Solution Explorer, right-click the MobileAppointments project, point to Add, and then click New Item. In the Add New Item - MobileAppointments dialog box, in the Categories pane, click Data. In the Templates pane, click Local Database Cache. In the Name box, type client.sync and then click Add. In the Configure Data Synchronization dialog box, next to the Server connection control, click New. In the Add Connection dialog box, in the Server name box, type .\SQLEXPRESS Expand the Select or enter a database name list, and then click ContosoMedicalDB. Click OK.

6. 7. 8. 9.

10. In the Configure Data Synchronization dialog box, under the Cached Tables control, click Add. The Configure Tables for Offline Use dialog box opens, and the Tables on dbo control shows the tables in the database. 11. In the Configure Tables for Offline Use dialog box, in the Tables on dbo control, select the Appointments check box. The controls on the right side of the dialog box fill with information about the changes that will be made to the server database. 12. Click OK. 13. In the Configure Data Synchronization dialog box, click OK. The wizard performs these steps: a. Generates the server scripts and runs them. The scripts perform the following operations: b. c. They add the date tracking columns to the table in server database. They create the Tombstone table to the server database. They add stored procedures to the server database to insert, update, and delete rows.

Creates the SQL Server CE 3.5 database file, as the local cache, and adds it to the project. Downloads all of the rows from the Appointments table into the local cache.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-91

MCT USE ONLY. STUDENT USE PROHIBITED

14. In the Data Source Configuration Wizard, expand Tables, expand Appointments, and then click the following named items to select the columns to use: AppointmentID PatientID AppointmentDateTime Notes

15. Change the DataSet name to clientDataSet, and then click Finish.

Task 3: Examine the generated code


1. In Class View, expand the MobileAppointments project, expand the MobileAppointments namespace, and then double-click clientClientSyncProvider, to open the generated code in the code editor. View the following classes that were generated by the Local Database Cache wizard:
Description This is the local synchronization provider and holds the code to connect to the local cache. This is the synchronization agent that encapsulates creating the synchronization providers and indicating which tables to synchronize.

2.

Class clientClientSyncProvider

clientSyncAgent

clientSyncAgent.AppointmentsSyncTable This class indicates the table that will be synchronized and the direction of the synchronization. AppointmentsSyncAdapter This is the server synchronization adapter that indicates information about how to access the server database. This is the server synchronization provider.

clientServerSyncProvider

L6-92

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

3.

Locate the clientSyncAgent.AppointmentsSyncTable nested class. The wizard only generates code to perform download-only synchronization. Notice the following: The class does not explicitly declare the value for SyncTable.SyncDirection property so it uses the default, which is DownloadOnly. The constructor invokes the OnInitialized partial method.

4.

In Solution Explorer, in the MobileApplications project, right-click MainForm.vb (Visual Basic) or MainForm.cs (Visual C#), and then click View Code. Change the configuration of the AppointmentsSyncTable class to explicitly specify the synchronization direction by implementing the partial method OnInitialized. In Notepad, go to the folder E:\Labfiles\Starter\VB (Visual Basic) or E:\Labfiles\Starter\CS (Visual C#), and then open the Ex1_Task3_OnInitialized.txt file. Copy the entire contents of the file to the Clipboard.

5.

6.

In Microsoft Visual Studio development system, paste the code into the namespace: If you are using Visual Basic, paste this code at the bottom of the file, after the End Class statement. If you are using Visual C#, paste this code in the namespace immediately before the final closing brace in the file.

7.

Import the Microsoft.Synchronization.Data namespace. Your code should resemble the following example.
[Visual Basic] Imports Microsoft.Synchronization.Data

[Visual C#] using Microsoft.Synchronization.Data;

8.

This code explicitly sets the synchronization direction to DownloadOnly; you will change this in a later exercise.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-93

MCT USE ONLY. STUDENT USE PROHIBITED

Task 4: Examine the database


1. In Server Explorer, right-click lon-dev\sqlexpresss.ContosoMedicalDB.dbo, and then click Refresh to update the values. This might take a few seconds while Visual Studio connects to the database and downloads metadata from the database. 2. Expand lon-dev\sqlexpresss.ContosoMedicalDB.dbo, expand Tables, and verify that the database now contains a table named Appointments_Tombstone. Expand the Appointments table node, and verify that the table contains the following items. Double-click each trigger to examine what it does.
Description The primary key. This is an original column. Identifies the doctor. This is an original column. Identifies the patient. This is an original column. The time and date of the appointment. This is an original column. Notes associated with the appointment. This is an original column. A datetime column that is used to track when a row was last updated. This is a new column. A datetime column that is used to track when a row was inserted. This is a new column. This trigger adds an entry in the tombstone table for the deleted row that has the specified appointment identifier and the current time. If the row has been deleted before then, the tombstone entry is updated to show the current time. Initializes the CreationDate column with the current time. Initializes the LastEditDate column with the current time.

3.

Item AppointmentID DoctorID PatientID AppointmentDateTime Notes LastEditDate CreationDate Appointments_DeletionTrigger

Appointments_InsertTrigger Appointments_UpdateTrigger

L6-94

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

Note: The patient is identified in this table by a number, not the name of the patient. The significance of this becomes apparent in the next exercise.

4.

In Server Explorer, expand the Appointments_Tombstone table node, and verify that the table contains the following items.
Description This is the primary key of the row that was deleted. This is the time and date when the row was deleted.

Item AppointmentID

DeletionDate

Results: After this exercise, you should have altered the database to enable synchronization and generated supporting classes to initiate synchronization.

Exercise 2: Downloading Data to a Client Computer


Task 1: Examine the user interface
1. In Solution Explorer, in the MobileAppointments project, double-click MainForm.vb (Visual Basic) or MainForm.cs (Visual C#), to open the form in the designer. Examine the following controls on the form.
Description Use this text box to provide the identifier for the doctor. Click this button to synchronize between the server database and the local cache. Click this button to save data in the grid to the local cache (in a later exercise). View the data in the local cache.

2.

Control doctorID synchronize

saveCache

appointmentsGrid

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-95

MCT USE ONLY. STUDENT USE PROHIBITED

Task 2: Alter the SyncAdapter class


1. In Solution Explorer, in the ContosoMedicalDatabases project, expand the Create Scripts folder, right click CreateAppointmentStoredProcedures.sql, and then click Run. Verify that the script executes without any errors. 2. In Class View, in the MobileAppointments project, expand the MobileAppointments namespace, and then double-click AppointmentsSyncAdapter to open the generated code in the code editor. The AppointmentstSyncAdapter class is generated for you and provides a method named InitializeCommands that initializes the command to insert, update, and delete rows in the server database, as summarized in the following table.
Command InsertCommand Description This is called to insert a row in the server database. The command first sets the IDENTITY_INSERT T-SQL option so that a value can be provided for the identity row. The command then inserts a row into the table. All of the column values are provided through parameters. The command provides values for the date tracking columns, which is redundant because the insertion trigger will perform this action. Finally, the @sync_row_count session variable is initialized by the value of the number of rows inserted. The row that holds the specific AppointmentID value is deleted under one of two conditions: either this is a force write or the row was not edited since last synchronized. A force write means that the client has indicated that the client changes must be made regardless of any conflicts with the server data. The AppointmentID value, which identifies the appointment row to be deleted, is provided through a parameter. The @sync_row_count session variable is initialized by the value of the number of rows inserted.

DeleteCommand

L6-96

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

(continued)
Command UpdateCommand Description The row with the specified AppointmentID is updated. All the other columns are provided through parameters, including the date tracking columns, which is redundant because the update trigger will perform this action. The update is performed under one of two conditions: either this is a force write or the row was not edited since last synchronized. The @sync_row_count session variable is initialized by the value of the number of rows inserted. The query that is used to determine if there is a deletion conflict. This simply tests the tombstone table for a row with the specified AppointmentID value.

SelectConflictDeletedRowsCommand

SelectConflictUpdatedRowsCommand The query that is used to identify updated rows that conflict with other changes. SelectIncrementalInsertsCommand The query that is used to obtain the rows that were inserted since the last synchronization. The query that is used to obtain the rows that were deleted since the last synchronization. The query that is used to obtain the rows that were updated since the last synchronization.

SelectIncrementalDeletesCommand

SelectIncrementalUpdatesCommand

3.

In Server Explorer, in the lon-dev\sqlexpress.ContosoMedicalDB.dbo database, expand the Stored Procedures node, and then double-click uspGetAppointmentsForDoctor. You will use this stored procedure to get the information from the Appointments table in a form that you can display. You will change the code to use this stored procedure to read rows from the database. In Task 4 of Exercise 1, Modifying a Database Schema to Support Synchronization, you learned that the Appointments table identifies patients by using the value from the identity column of the Patients table. The uspGetAppointmentsForDoctor stored procedure returns the full name of the patient by using a join on the Patients table.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-97

MCT USE ONLY. STUDENT USE PROHIBITED

Note: The uspGetAppointmentsForDoctor stored procedure returns a different number of columns to the number generated by the Local Database Cache Wizard, so the table in the ContosoMedicalDB.sdf file generated by the Local Database Cache Wizard is now incorrect. In addition, the dataset code to access this database file is also incorrect.

4.

You must now change the dataset code to access the local cache database. Visual Studio generates the dataset code for you if it has a database file that contains the correct schema. You must delete the database cache file, ContosoMedicalDB.sdf, which you generated in Exercise 1, and create a new version that contains the correct schema. To remove the old code, follow these steps: a. In Solution Explorer, in the MobileAppointments project, right-click ContosoMedicalDB.sdf, and then click Delete. In the message box that informs you that 'ContosoMedicalDB.sdf' will be deleted permanently, click OK. In Solution Explorer, right-click clientDataSet.xsd, and then click Delete. In the message box that informs you that 'clientDataSet.xsd' will be deleted permanently, click OK.

b.

5.

Add code so that the Synchronization adapter uses the store procedure. In Notepad, go to the folder E:\Labfiles\Starter\VB (Visual Basic) or E:\Labfiles\Starter\CS (Visual C#), and then open the Ex2_Task2_OnInitialized.txt file. Copy the entire contents of the file to the Clipboard. In Visual Studio, paste the code into the namespace: If you are using Visual Basic, right-click MainForm.vb, and then click View Code. Paste the contents of the Clipboard at the bottom of the file. If you are using Visual C#, right-click MainForm.cs, and then click View Code. Paste the contents of the Clipboard in the namespace, immediately before the final closing brace in the file.

6.

This code adds a command that calls the uspGetAppointmentsForDoctor stored procedure. The stored procedure has four parameters, three are provided by the synchronization agent as session variables and the fourth, @doctorID, is provided by your code. You will add the code to initialize the @doctorID parameter in the next task.

L6-98

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

Task 3: Add a new dataset


1. 2. On the View menu, click Designer to open the main form in the designer. Double-click Synchronize to create a Click handler. In Notepad, go to the folder E:\Labfiles\Starter\VB (Visual Basic) or E:\Labfiles\Starter\CS (Visual C#), and then open the Ex2_Task3_synchronize_Click.txt file. Copy the entire contents of the file to the Clipboard. Paste the code you copied into the synchronize_Click method. This method calls the synchronization agent to perform synchronization, as follows: The user provides the doctor identifier by using the doctorID control. When the user changes the contents of the doctorID control, the doctorID_TextChanged event handler sets the newIdentifier field with the new value. In the synchronize_Click method, if doctorIdentifier and newIdentifier are different, the identifier has changed, so the local cache database file should be initialized. The code deletes the old file and then creates a new, empty file, by using the CreateDatabase method. The doctor identifier provides the value for the @doctorID parameter of the stored procedure through a session parameter, by adding the parameter and value to the SyncParameters collection.

3.

4.

Compile and run the application, as follows: a. b. c. On the Build menu, click Build Solution. Confirm that there are no compiler errors. On the Debug menu, click Start Without Debugging.

d. In the Mobile Calendar window, click Synchronize. Nothing appears to happen. This is the expected result. e. 5. Close the application.

In the last step, when the code called the synchronize_Click method, an initial synchronization was performed, which downloaded all of the rows from the server database to the local cache. Synchronization Services created a table in the local cache by using the columns for the output from the uspGetAppointmentsForDoctor stored procedure. The local cache now has the schema that is required by the dataset wizard to create the dataset code.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-99

MCT USE ONLY. STUDENT USE PROHIBITED

6.

Create the dataset code. Add the local cache database to the project and Visual Studio starts the Data Source Configuration Wizard. In Solution Explorer, perform these steps: a. b. c. Click Show All Files. Expand the bin folder, and then expand the Debug folder. Right-click ContosoMedicalDB.sdf, and then click Copy. Right-click the MobileAppointments project node, and then click Paste.

d. Click Show All Files, to hide the build folders. e. f. 7. Right-click the MobileAppointments project node, point to Add, and then click Existing Item. In the Add Existing Item - MobileAppointments dialog box, in the File name box, type ContosoMedicalDB.sdf and then click Add.

In the Data Source Configuration Wizard wizard page, expand the Tables node, expand the Appointments node, and then select the following items: AppointmentID AppointmentDateTime FullName Gender DateOfBirth Notes

8. 9.

In the DataSet name box, type clientDataSet Click Finish.

10. On the MainForm form, in the forms designer, click the appointmentsGrid control. In the Properties windows, locate the DataSource property. Click the down arrow, expand Other Data Sources, expand Project Data Sources, expand clientDataSet, and then click Appointments.

L6-100

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

11. On the MainForm form, in the forms designer, double-click Synchronize. In the code for synchronize_Click method, add the following statement immediately after the call to the agent.Synchronize method, which updates the user interface.
[Visual Basic] Me.AppointmentsTableAdapter.Fill(Me.ClientDataSet.Appointments)

[Visual C#] this.appointmentsTableAdapter.Fill(this.clientDataSet.Appointments) ;

Task 4: View the server test code


1. In Solution Explorer, in the DesktopAppointments project, double-click MainForm.vb (Visual Basic) or MainForm.cs (Visual C#), to open the form in the designer. Familiarize yourself with the controls on this form as summarized in the following table.
Description This navigation control enables you to navigate through the Appointments table on the server. In particular, notice the following buttons:

2.

Control navigator

The Delete button deletes the selected row in the dataset. The Save button saves all of the changes in the dataset to the
server database.

The Refresh button reads the dataset from the database. If


you have already made changes to the dataset, they will be discarded. appointmentsGrid This data grid shows values from the Appointments table. If you add a new row, you must provide values for DoctorID, PatientID, and AppointmentDateTime. The Notes field may be left empty because it is a nullable column.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-101

MCT USE ONLY. STUDENT USE PROHIBITED

Task 5: Compile and test download-only synchronization


1. Compile and run the client application as follows: a. b. c. 2. On the Build menu, click Build Solution. Confirm that there are no compiler errors. On the Debug menu, click Start Without Debugging.

Start the server application: a. b. c. On the Windows taskbar, click Start, and in the search box, type Windows Explorer In the Programs list, click Windows Explorer. Go to E:\Labfiles\Starter\VB\Appointments\DesktopAppointments\bin\De bug (Visual Basic) or E:\Labfiles\Starter\CS\Appointments\DesktopAppointments\bin\De bug (Visual C#). Double-click DesktopAppointments.exe.

3.

Position the Desktop Calendar and Mobile Calendar windows side by side and compare the contents: a. Verify that there are seven appointments shown in the Mobile Calendar and that there are seven appointments with a DoctorID value of 1 in the Desktop Calendar. Verify that the rows in the Mobile Calendar have the same values as the rows with the same AppointmentID in the Desktop Calendar.

b.

Note: When you switch between Mobile Calendar and Desktop Calendar, click the title bar of Desktop Calendar instead of task switching with ALT-TAB. If you use ALT-TAB, the input focus is set to the form, so to use the navigator child controls, you must click the navigator control once before you click the child control. If you switch to Desktop Calendar by clicking the title bar of Desktop Calendar, the input focus is set to the navigator control.

L6-102

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

4.

In the Desktop Calendar add the following rows. On the navigator, click Add new, and then fill all of the cells except for the AppointmentID cell. After you enter the values for all of the new rows, on the navigator, click Save. a. Add the first new appointment with the information from the following table.
Value 1 5 06/03/2008 9:00 First new appointment

Column DoctorID PatientID AppointmentDateTime Notes

b.
Column

Add the second new appointment with the information from the following table.
Value 2 10 06/03/2008 10:00 Second new appointment

DoctorID PatientID AppointmentDateTime Notes

5. 6. 7. 8.

Confirm that when you click Save, the grid updates the AppointmentID value for the new rows. The new values should not be negative numbers. Confirm that the Mobile Calendar window still shows seven rows. Close the Mobile Calendar window. In Visual Studio, on the Debug menu, click Start Without Debugging to run the MobileAppointments application again. Confirm that you still see just seven rows. This confirms that the application has read the data from the local cache instead of the server database. In the Mobile Calendar window, click Synchronize.

9.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-103

MCT USE ONLY. STUDENT USE PROHIBITED

10. Verify that the Mobile Calendar now shows eight rows and that the new row has the following values.
Column AppointmentID AppointmentDateTime FullName Gender DateOfBirth Notes Value 10 06/03/2008 9:00 AM Richard Garcia M 07/02/1997 First new appointment

Synchronization has copied the new row to the local cache. 11. In the Desktop Calendar window, make a change to the new row for doctor 1. a. b. Change the Notes field for the row that you just inserted for doctor 1. Change First new appointment to Updated notes Click Save.

12. In the Mobile Calendar window, click Synchronize. Verify that the row that previously had First new appointment in the Notes cell now has Updated notes in that cell. 13. In the Desktop Calendar window, select the entire row that has Updated notes in the Notes column. Click Delete, and then click Save, to save the results to the database. 14. In the Mobile Calendar window, click Synchronize. Verify that the previous row has been deleted and that there are now seven rows. 15. Close the Mobile Calendar window, but keep the Desktop Calendar window open because you will use it again in the next exercise.
Results: After this exercise, you should have implemented an application that performs download-only synchronization with a SQL Server database. You should have shown that synchronization works for inserted, updated, and deleted rows.

L6-104

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

Exercise 3: Uploading Data Changes to the Database


Task 1: Change the MobileAppointments class to use bidirectional synchronization
1. In Solution Explorer, in the MobileAppointments project, right-click MainForm.vb (Visual Basic) or MainForm.cs (Visual C#), and then click View Code. Locate the clientSyncAgent class. In the AppointmentsSyncTable nested class, modify the OnInitialized method so that the synchronization direction is bidirectional. Your code should resemble the following example.
[Visual Basic] Me.SyncDirection = _ Microsoft.Synchronization.Data.SyncDirection.Bidirectional

2. 3.

[Visual C#] this.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;

4.

Next, you must provide a workaround for the code that was generated by the wizard. The InsertCommand and UpdateCommand objects that were generated by the wizard provide values for the LastEditDate and CreationDate columns through parameters named @LastEditDate and @CreationDate. However, these parameters are not initialized and cause a run-time error if you use them. The solution to this problem is to remove the parameters from the commands, because the commands do not require these parameters. In Notepad, open Ex3_Task1_OnInitialized.txt, and then copy the entire contents to the Clipboard.

5.

In Visual Studio, locate the AppointmentsSyncAdapter class, and then locate the OnInitialized method. Paste the contents of the Clipboard to the end of the method. In the Forms Designer for the MainForm form, double-click Save to Cache to open the Click handler for this button. This button enables users to save changes in the grid to the local cache.

6.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-105

MCT USE ONLY. STUDENT USE PROHIBITED

7.

Add the following code to save the data by using the table adapter object.

[Visual Basic] Me.Validate() Me.appointmentsBindingSource.EndEdit() Me.appointmentsTableAdapter.Update(Me.clientDataSet.Appointments)

[Visual C#] this.Validate(); this.appointmentsBindingSource.EndEdit(); this.appointmentsTableAdapter.Update(this.clientDataSet.Appointments);

8.

Compile and run the application: a. b. c. On the Build menu, click Build Solution. Confirm that there are no compiler errors. On the Debug menu, click Start Without Debugging.

9.

In the Mobile Calendar window, perform these steps: a. b. c. Click in the Notes cell of one of the appointments and change the value. Click Save to Cache to save the change to the local cache. Click Synchronize to synchronize the changes to the server.

10. Switch to the Desktop Calendar window, and then click Refresh. Verify that the Notes column of the appointment that you changed has changed to the value you used. 11. Close the Mobile Calendar window.

Task 2: Add conflict handling


1. In Solution Explorer, in the MobileAppointments project, double-click HandleConflict.vb (Visual Basic) or HandleConflict.cs (Visual C#) to open the Handle Conflict dialog box in the forms designer.

L6-106

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

2.

Examine the controls on this form.


Description This text box displays the conflict that has occurred. It gives the type of conflict and the conflicting client and server rows. This radio button group enables you to determine if you will allow the default action to occur or if you want to force another action. The default action is to accept the server value.

Control The following conflict has occurred

How do you want to handle this?

3. 4.

On the View menu, click Code. Examine the code in this class. There are two properties. The Action property returns an ApplyAction value based on the radio button selected. The ConflictType property displays information about the conflict in the text box on the form.

5. 6.

View the code for the MainForm form, and then locate the synchronize_Click method. Immediately before the call to agent.Synchronize method call, add the following code to handle the ApplyChangeFailed event.
[Visual Basic] Dim remote As clientServerSyncProvider = _ CType(agent.RemoteProvider, clientServerSyncProvider) AddHandler remote.ApplyChangeFailed, _ AddressOf remote_ApplyChangeFailed

[Visual C#] clientServerSyncProvider remote = agent.RemoteProvider as clientServerSyncProvider; remote.ApplyChangeFailed += new EventHandler<ApplyChangeFailedEventArgs>( remote_ApplyChangeFailed);

7.

In Notepad, open Ex3_Task2_ApplyChangeFailed.txt and copy the entire contents to the Clipboard.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-107

MCT USE ONLY. STUDENT USE PROHIBITED

8.

In Visual Studio, paste the contents of the clipboard immediately after the synchronize_Click method. This new code creates an instance of the HandleConflict form and passes to the form information about the conflict. If the user clicks OK on this form, the ApplyChangeFailed handler uses the Action property on the form to indicate how the conflict should be handled.

Task 3: Build and run the application


1. 2. 3. 4. On the Build menu, click Build Solution. Confirm that there are no compiler errors. On the Debug menu, click Start Without Debugging. Add a new row to the server database, as follows: a. b.
Column AppointmentID DoctorID PatientID AppointmentDateTime Notes

In the Desktop Calendar window, on the navigator, click Add new. Add the following values in all of the cells, except for the AppointmentID cell.
Value Do not change this cell. 1 5 06/03/2008 9:00 No notes.

c. 5. 6.

On the navigator, click the Save to save the data to the server database.

In the Mobile Calendar window, click Synchronize. Verify that the new row is copied to the client cache. The client cache and the server are synchronized. Generate a conflict, as follows: a. b. In the Mobile Calendar window, click the Notes cell for the new row, and then type client In the Mobile Calendar window, click Save to Cache.

L6-108

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

c.

In the Desktop Calendar window, click the Notes cell for the new row, and then type server

d. In the Desktop Calendar window, click Save. 7. 8. In the Mobile Calendar window, click Synchronize. Verify that the client application detects a conflict and displays a Handle Conflict dialog box with values similar to these:

Mobile Calendar updated a row that Desktop Calendar also updated. Client rows: 12 06/03/2008 09:00:00 5 Richard Garcia M 07/02/1997 00:00:00 client Server rows: 12 1 5 06/03/2008 09:00:00 server 02/04/2008 13:19:46 02/04/2008 13:15:06

In the preceding results, the first line indicates that both applications have changed the same row since the last synchronization. The third line is the data in the client cache. The values shown are: AppointmentID, AppointmentDateTime, PatientID, FullName, Gender, DateOfBirth, and Notes. The fifth line is the data in the server database. The values shown are: AppointmentID, DoctorID, PatientID, AppointmentDateTime, Notes, LastEditDate, and CreationDate. 9. Compare the Notes value for these two conflicting rows: the last item for the client row and the fifth item for the server row. Confirm that these are different values.

10. In the Handle Conflict dialog box, click Continue with the current action, and then click OK. 11. Verify that the Mobile Calendar window is updated with the results from the server, that is, the Notes cell for the new row has the value server.

Note: The Mobile Calendar application handles the ApplyChangeFailed event for the remote synchronization provider, which detects conflicts when attempting to make changes to the server database. The default action (Continue action) accepts the changes that are made to the server.

Lab: Building Occasionally Connected Solutions by Using Synchronization Services

L6-109

MCT USE ONLY. STUDENT USE PROHIBITED

12. In the Mobile Calendar window, change the Notes cell for the row that was added by synchronization: a. b. c. In the Mobile Calendar window, in the Notes cell that currently has the value server, type client2 Click Save to Cache. In the Desktop Calendar window, in the cell that currently has the value server, type server2

d. Click Save. 13. In the Mobile Calendar window, click Synchronize. 14. Verify that the client application detects a conflict. 15. In the Handle Conflict dialog box, click Force this write, and then click OK. 16. In the Mobile Calendar window, confirm that the Notes field of the row you changed still reads client2. 17. In the Desktop Calendar window, click Refresh to refresh the grid with values from the server database. Verify that the Notes field of the row you changed reads client2.

Note: The RetryWithForceWrite action for the ApplyChangeFailed event on the remote synchronization provider forces the client changes on the server.

18. In the Desktop Calendar window, select the new row, click Delete, and then click Save. 19. In the Mobile Calendar window, change the Notes field to client3 and then click Save to Cache. 20. Click Synchronize. 21. Verify that the client application detects a conflict. The text of this conflict is: Mobile Calendar updated a row that Desktop Calendar deleted. 22. In the Handle Conflict dialog box, click Force this write, and then click OK. 23. Verify that the row remains in the local cache.

L6-110

Module 6: Building Occasionally Connected Solutions by Using Synchronization Services

MCT USE ONLY. STUDENT USE PROHIBITED

24. In the Desktop Calendar window, click Refresh, and then verify that the row has been re-inserted into the server database. 25. Close the Desktop Calendar window, and then close the Mobile Calendar window 26. Close Visual Studio.
Results: After this exercise, you should have implemented the application so that it handles synchronization conflicts and you can specify whether changes in the client override changes in the server.

You might also like