TE AM FL Y
i-xxvi.qxd 2/24/03 9:58 AM Page i
.NET Framework Professional Projects
i-xxvi.qxd 2/24/03 9:58 AM Page ii
This page intentionally left blank
i-xxvi.qxd 2/24/03 9:58 AM Page iii
Angshuman Chakraborti Uday Kranti Roopendra Jeet Sandhu WITH
.NET Framework Professional Projects
i-xxvi.qxd 2/24/03 9:58 AM Page iv
©2002 by Premier Press, Inc. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system without written permission from Premier Press, except for the inclusion of brief quotations in a review.. The Premier Press logo, top edge printing, and related trade dress are trademarks of Premier Press, Inc. and may not be used without written permission. All other trademarks are the property of their respective owners. Important: Premier Press cannot provide software support. Please contact the appropriate software manufacturer's technical support line or Web site for assistance. Premier Press and the author have attempted throughout this book to distinguish proprietary trademarks from descriptive terms by following the capitalization style used by the manufacturer. Information contained in this book has been obtained by Premier Press from sources believed to be reliable. However, because of the possibility of human or mechanical error by our sources, Premier Press, or others, the Publisher does not guarantee the accuracy, adequacy, or completeness of any information and is not responsible for any errors or omissions or the results obtained from use of such information. Readers should be particularly aware of the fact that the Internet is an ever-changing entity. Some facts may have changed since this book went to press. ISBN: 1-931841-24-1 Library of Congress Catalog Card Number: 2001097000 Printed in the United States of America 02 03 04 05 06 RI 10 9 8 7 6 5 4 3 2 1
Publisher: Stacy L. Hiquet Marketing Manager: Heather Buzzingham Managing Editor: Sandy Doell Editorial Assistant: Margaret Bauer Book Production Services: Argosy Cover Design: Mike Tanamachi
i-xxvi.qxd 2/24/03 9:58 AM Page v
About NIIT NIIT is a global IT solutions corporation with a presence in 38 countries. With its unique business model and technology-creation capabilities, NIIT delivers software and learning solutions to more than 1,000 clients across the world. The success of NIIT’s training solutions lies in its unique approach to education. NIIT’s Knowledge Solutions Business conceives, researches, and develops all of its course material. A rigorous instructional design methodology is followed to create engaging and compelling course content. NIIT trains over 200,000 executives and learners each year in information technology areas using stand-up training, video-aided instruction, computer-based training (CBT), and Internet-based training (IBT). NIIT has been featured in the Guinness Book of World Records for the largest number of learners trained in one year! NIIT has developed over 10,000 hours of instructor-led training (ILT) and over 3,000 hours of Internet-based training and computer-based training. IDC ranked NIIT among the Top 15 IT training providers globally for the year 2000. Through the innovative use of training methods and its commitment to research and development, NIIT has been in the forefront of computer education and training for the past 20 years. Quality has been the prime focus at NIIT. Most of the processes are ISO-9001 certified. It was the 12th company in the world to be assessed at Level 5 of SEI-CMM. NIIT’s Content (Learning Material) Development facility is the first in the world to be assessed at this highest maturity level. NIIT has strategic partnerships with companies such as Computer Associates, IBM, Microsoft, Oracle, and Sun Microsystems.
i-xxvi.qxd 2/24/03 9:58 AM Page vi
This page intentionally left blank
i-xxvi.qxd 2/24/03 9:58 AM Page vii
About the Authors Angshuman Chakraborti is an MCSD (Microsoft Certified Solution Developer) and MCSE (Microsoft Certified Systems Engineer). He is also a CNA (Certified Novell Administrator). He has been working with NIIT for the past four years. He started working with NIIT as an instructor on various technologies, including C, C++, VC++, VB, UNIX, Linux, Windows NT, Windows 2000, and TCP/IP, for individuals as well as corporate clients. Angshuman has created training materials for various U.S.–based clients and also has written books on various technologies including A+, Network+, NetWare6, VPN, CCNA, Linux, Mac OS, JavaScript, and HTML among others. Uday Kranti is currently a development executive with NIIT. As a member of the Microsoft Center of Competence for the Knowledge Solutions Business (KSB) division, Uday is a consultant to various teams working on Microsoft projects, ranging from technical documentation to web-based learning solutions. As a subject matter expert (SME), Uday provides support to various ongoing Microsoft projects. In addition, Uday’s responsibilities include writing white papers on upcoming technologies and their implications on the current systems and also developing applications, such as creating web applications for NIIT Web sites, such as Tecknowpark.com. Roopendra Jeet Sandhu is an instructional designer for Knowledge Solutions Business (KSB) division of NIIT Ltd. During her two-year tenure at NIIT Ltd., she has developed content for computer-based training, web-based training, and instructor-led training for clients such as Course Technology, NetVarsity, and ITT. She has independently developed a couple of web-based training projects. She has been developing content on technical areas, such as operating systems, security, and database management systems.
i-xxvi.qxd 2/24/03 9:58 AM Page viii
This page intentionally left blank
i-xxvi.qxd 2/24/03 9:58 AM Page ix
Contents at a Glance Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxv
Part I
.NET Framework Overview . . . . . . . . . . . . . . . . 1 1 2 3
.NET Vision and Design Goals . . . . . . . . . . . . . . . . . . . . . 3 The .NET Family . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Introduction to the .NET Framework . . . . . . . . . . . . . . . 67
Part II
Professional Project 1 . . . . . . . . . . . . . . . . . 91
PROJECT 1
DATABASE INTEGRATION 4 5 6 7 8
WITH
.NET . . . . . . . . . . . . . 93
Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Introduction to ADO.NET . . . . . . . . . . . . . . . . . . . . . . 101 Creating a Windows Application in Visual Basic Using ADO.NET to Implement Database Connectivity . . . . . . 145 Creating a Windows Application in C# Using ADO.NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Transactions in .NET—Overview and Implementation . . 305
Part III
Professional Project 2 . . . . . . . . . . . . . . . . 313
PROJECT 2
XML DESIGNER: CREATING XML SCHEMAS . . . . . . . 315 9 10
Overview of XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Creating a Data Viewer Application Using XML Schema, Typed DataSet, and XSLT . . . . . . . . . . . 347
Part IV
Professional Project 3 . . . . . . . . . . . . . . . . . 403
PROJECT 3
WEB FORMS USING ASP.NET . . . . . . . . . . . . . . . 405 11 12 13
Introduction to ASP.NET . . . . . . . . . . . . . . . . . . . . . . . 407 Creating an Entity Modification Web Application Using ASP.NET (in Visual Basic .NET) . . . . . . . . . . . . 445 Creating an Entity Modification Web Application Using ASP.NET (in C#) . . . . . . . . . . . . . . . . . . . . . . . . 489
i-xxvi.qxd 2/24/03 9:58 AM Page x
Contents at a Glance
Part V
Professional Project 4 . . . . . . . . . . . . . . . . . 513
PROJECT 4
WEB SERVICES. . . . . . . . . . . . . . . . . . . . . . . . . 515 14 15 16
Introduction to Web Services . . . . . . . . . . . . . . . . . . . . . 517 Creating a Web Service Using C# and Using It in a Visual Basic .NET Application . . . . . . . . . . . . . . . . . . . 535 Creating a Web Service in Visual Basic .NET and Using It in a C# Application . . . . . . . . . . . . . . . . . . 559
Professional Project 5 . . . . . . . . . . . . . . . . . 591
PROJECT 5
SECURITY MODEL 17 18
AM FL Y
Part VI
IN THE
.NET FRAMEWORK . . . . . . . 593
Overview of .NET Framework Security . . . . . . . . . . . . . 595 Implementing Security . . . . . . . . . . . . . . . . . . . . . . . . . . 623
Part VII
Professional Project 6 . . . . . . . . . . . . . . . . . 649
PROJECT 6
COM INTEROP . . . . . . . . . . . . . . . . . . . . . . . . . 651 19 20 21
TE
x
Introduction to COM Interop . . . . . . . . . . . . . . . . . . . . 653 Creating a .NET Component in C# and Using It in a Visual Basic 6.0 Application . . . . . . . . . . . . 665 Creating a COM Component in Visual Basic 6.0 and Using It in a C# Application . . . . . . . . . . . . . . . . . . 697
Part VIII
Professional Project 7 . . . . . . . . . . . . . . . . . 749
PROJECT 7
PERFORMANCE COUNTERS . . . . . . . . . . . . . . . . . . 751 22 23
Part IX
Introduction to Performance Counters in .NET . . . . . . . 753 Implementing Performance Counters . . . . . . . . . . . . . . . 769
Beyond The Lab . . . . . . . . . . . . . . . . . . . . . . 821 24
Mobile Applications in .NET . . . . . . . . . . . . . . . . . . . . . 823
Team-Fly®
i-xxvi.qxd 2/24/03 9:58 AM Page xi
Contents at a Glance
Part X
Appendixes . . . . . . . . . . . . . . . . . . . . . . . . . 841 A B C D E F
Upgrading/Migrating from Visual Basic 6.0 to Visual Basic .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . 843 Migrating from VC++ 6.0 (unmanaged code) to VC++.NET (managed extensions) . . . . . . . . . . . . . . . 851 ATL for VC Programmers . . . . . . . . . . . . . . . . . . . . . . . 869 .NET Configuration Files . . . . . . . . . . . . . . . . . . . . . . . 883 Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 895 Windows Forms Designer Generated Code . . . . . . . . . . 911 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921
xi
i-xxvi.qxd 2/24/03 9:58 AM Page xii
This page intentionally left blank
i-xxvi.qxd 2/24/03 9:58 AM Page xiii
Contents Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxv
PART I
.NET FRAMEWORK OVERVIEW . . . . . . . . . . . 1
Chapter 1
.NET Vision and Design Goals. . . . . . . . . . . . . . 3 The .NET Vision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 The Philosophy of .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Advantages of the .NET Framework . . . . . . . . . . . . . . . . . . . . 6 Architectural Shift in .NET . . . . . . . . . . . . . . . . . . . . . . . . . . 7 .NET Framework Design Goals . . . . . . . . . . . . . . . . . . . . . . . . . 10 Availability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Manageability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Reliability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Scalability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Securability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Chapter 2
The .NET Family . . . . . . . . . . . . . . . . . . . . . . . 27 .NET Enterprise Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Application Center 2000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 BizTalk Server 2000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Commerce Server 2000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Content Management Server 2001 . . . . . . . . . . . . . . . . . . . . 32 Exchange 2000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Host Integration Server 2000 . . . . . . . . . . . . . . . . . . . . . . . . 35 ISA Server 2000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Mobile Information 2001 Server . . . . . . . . . . . . . . . . . . . . . . 39 SharePoint Portal Server 2001 . . . . . . . . . . . . . . . . . . . . . . . . 41
i-xxvi.qxd 2/24/03 9:58 AM Page xiv
xiv
Contents
SQL Server 2000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 The Whistler Family . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 .NET Passport Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Visual Studio .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Chapter 3
Introduction to the .NET Framework. . . . . . . . 67 .NET Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Class Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Language Enhancements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Visual Basic .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Visual C++ .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Visual Studio .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
PART II
PROFESSIONAL PROJECT 1 . . . . . . . . . . . 91
PROJECT 1
DATABASE INTEGRATION
Chapter 4
Project Case Study . . . . . . . . . . . . . . . . . . . . 95
WITH
.NET . . . . . . . . . . . . . 93
TecPublishers—A Publishing Consortium . . . . . . . . . . . . . . . . . 96 Project Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 High-Level Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Low-Level Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
i-xxvi.qxd 2/24/03 9:58 AM Page xv
Contents
Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 User Acceptance Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Chapter 5
Introduction to ADO.NET . . . . . . . . . . . . . . . 101 ADO.NET Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 .NET Data Provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Dataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 ADO.NET and XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Chapter 6
Creating a Windows Application in Visual Basic Using ADO.NET to Implement Database Connectivity . . . . . . . . 145 Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Project Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Chapter 7
Creating a Windows Application in C# Using ADO.NET . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 C# Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Evolution of C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Promise of C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Data Types in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 Creating a Windows Application . . . . . . . . . . . . . . . . . . . . . . . 229 Create New Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Create the Titles Authored by Each Author Form . . . . . . . . 232 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
xv
i-xxvi.qxd 2/24/03 9:58 AM Page xvi
xvi
Contents
Chapter 8
Transactions in .NET—Overview and Implementation . . . . . . . . . . . . . . . . . . . . . . 305 What Is a Transaction? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Transaction Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 Implementing Manual Transactions in an Application Using ADO.NET . . . . . . . . . . . . . . . . . . . . . . 309 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
PART III
PROFESSIONAL PROJECT 2 . . . . . . . . . . 313
PROJECT 2
XML DESIGNER: CREATING XML SCHEMAS . . . . . . . 315
Chapter 9
Overview of XML . . . . . . . . . . . . . . . . . . . . . 317 Overview of XML and Related Specifications . . . . . . . . . . . . . 318 XML and HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 XML Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 Validating XML Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 XML Integration with Relational Data . . . . . . . . . . . . . . . . 344 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
Chapter 10 Creating a Data Viewer Application Using XML Schema, Typed DataSet, and XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 Execution Phase of the Project Lifecycle . . . . . . . . . . . . . . . . . . 349 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
i-xxvi.qxd 2/24/03 9:58 AM Page xvii
Contents
PART IV
PROFESSIONAL PROJECT 3 . . . . . . . . . . . 403
PROJECT 3
WEB FORMS USING ASP.NET . . . . . . . . . . . . . . . 405
Chapter 11 Introduction to ASP.NET . . . . . . . . . . . . . . . 407 The Evolution of ASP.NET . . . . . . . . . . . . . . . . . . . . . . . . . . . 408 Benefits of ASP.NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 ASP.NET: A Part of .NET Framework SDK . . . . . . . . . . . . . . 411 ASP.NET Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Web Forms Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414 Components of Web Forms . . . . . . . . . . . . . . . . . . . . . . . . . 414 Hands-on Instruction for Creating Web Forms . . . . . . . . . . . . . 415 IIS Application Root Directory . . . . . . . . . . . . . . . . . . . . . . 420 The ASP.NET Web Forms Server Controls . . . . . . . . . . . . 423 HTML Server Controls vs. Web Controls . . . . . . . . . . . . . . . . 425 Adding Server Controls to a Form . . . . . . . . . . . . . . . . . . . . 426 Setting Properties for Web Controls . . . . . . . . . . . . . . . . . . 427 Handling Events of Web Controls . . . . . . . . . . . . . . . . . . . . 429 Commonly Used Web Controls . . . . . . . . . . . . . . . . . . . . . . 430 Validation Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432 More about Validation Controls . . . . . . . . . . . . . . . . . . . . . 432 Using Validation Controls . . . . . . . . . . . . . . . . . . . . . . . . . . 433 Using Multiple Validation Controls . . . . . . . . . . . . . . . . . . . 441 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
Chapter 12 Creating an Entity Modification Web Application Using ASP.NET (in Visual Basic .NET). . . . . . . . . . . . . . . . . . 445 Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446 Execution Phases of the Project Lifecycle . . . . . . . . . . . . . . . . . 447 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
xvii
i-xxvi.qxd 2/24/03 9:58 AM Page xviii
xviii
Contents
Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
Chapter 13 Creating an Entity Modification Web Application Using ASP.NET (in C#) . . . . 489 Project Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
PART V
PROFESSIONAL PROJECT 4 . . . . . . . . . . . 513
PROJECT 4
WEB SERVICES. . . . . . . . . . . . . . . . . . . . . . . . . 515
Chapter 14 Introduction to Web Services . . . . . . . . . . . 517 What Is a Web Service? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519 XML Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519 Web Services as a Mechanism for Distributed Computing . . 520 Web Services and the .NET Framework . . . . . . . . . . . . . . . 521 XML Web Services: The .NET Strategy . . . . . . . . . . . . . . . 522 Architecture of Web Services . . . . . . . . . . . . . . . . . . . . . . . . 524 Building a Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526 Securing a Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . 528 Introducing SOAP with Respect to Web Services . . . . . . . . . . . 529 Features of SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529 Architecture of SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530 Composition of SOAP Messages . . . . . . . . . . . . . . . . . . . . . 530 Understanding UDDI with Respect to Web Services . . . . . . . . 532 The UDDI Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
i-xxvi.qxd 2/24/03 9:58 AM Page xix
Contents
Chapter 15 Creating a Web Service Using C# and Using It in a Visual Basic .NET Application . . . . . . . . . . . . . . . . . . . . . . . . . 535 Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536 Project Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
Chapter 16 Creating a Web Service in Visual Basic .NET and Using It in a C# Application . . . . . . 559 Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560 Execution Phases of the Project Lifecycle . . . . . . . . . . . . . . . . . 561 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563 Coding and Construction . . . . . . . . . . . . . . . . . . . . . . . . . . 566 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590
PART VI
PROFESSIONAL PROJECT 5 . . . . . . . . . . . 591
PROJECT 5
SECURITY MODEL
IN THE
.NET FRAMEWORK . . . . . . . 593
Chapter 17 Overview of .NET Framework Security . . . . . 595 The .NET Framework Security Solution . . . . . . . . . . . . . . . . . 597 The Building Blocks of Microsoft .NET Framework Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598 How Security Is Specified . . . . . . . . . . . . . . . . . . . . . . . . . . 609 Common Authentication Mechanisms . . . . . . . . . . . . . . . . . . . 610 Forms Authentication in ASP.NET . . . . . . . . . . . . . . . . . . . 610 Windows Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . 617
xix
i-xxvi.qxd 2/24/03 9:58 AM Page xx
Contents
Passport Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . 618 Code Access Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 622
Chapter 18 Implementing Security . . . . . . . . . . . . . . . . 623
AM FL Y
Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624 Project Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626 Building and Testing the Application . . . . . . . . . . . . . . . . . . 646 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647
PART VII
PROFESSIONAL PROJECT 6 . . . . . . . . . . . 649
PROJECT 6
COM INTEROP . . . . . . . . . . . . . . . . . . . . . . . . . 651
TE
xx
Chapter 19 Introduction to COM Interop . . . . . . . . . . . . 653 Introduction to COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654 COM Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654 The Need for COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655 COM to .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655 COM Interoperability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656 Creating Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656 COM Interop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657 COM Callable Wrapper . . . . . . . . . . . . . . . . . . . . . . . . . . . 657 Runtime Callable Wrapper . . . . . . . . . . . . . . . . . . . . . . . . . 658 Implementing COM Interoperability . . . . . . . . . . . . . . . . . . . . 659 Create a CCW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660 Declare a COM Coclass . . . . . . . . . . . . . . . . . . . . . . . . . . . 660 Create a COM Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661
Team-Fly®
i-xxvi.qxd 2/24/03 9:58 AM Page xxi
Contents
Declare a COM Interface . . . . . . . . . . . . . . . . . . . . . . . . . . 661 Access the COM Component . . . . . . . . . . . . . . . . . . . . . . . 663 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663
Chapter 20 Creating a .NET Component in C# and Using It in a Visual Basic 6.0 Application . . . . . . . . . . . . . . . . . . . . . . . . . 665 Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666 Project Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696
Chapter 21 Creating a COM Component in Visual Basic 6.0 and Using It in a C# Application . . . . . . . . . . . . . . . . . . . . . . . 697 Project Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 698 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
PART VIII
PROFESSIONAL PROJECT 7 . . . . . . . . . . . 749
PROJECT 7
PERFORMANCE COUNTERS . . . . . . . . . . . . . . . . . . 751
Chapter 22 Introduction to Performance Counters in .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 753 Performance Counter Categories . . . . . . . . . . . . . . . . . . . . . . . 754 Sampling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755 PerformanceCounter Components . . . . . . . . . . . . . . . . . . . . 756
xxi
i-xxvi.qxd 2/24/03 9:58 AM Page xxii
xxii
Contents
Performance Counter Types . . . . . . . . . . . . . . . . . . . . . . . . . 761 The Lifetime of Performance Counters . . . . . . . . . . . . . . . 762 Using Performance Counters in .NET Applications . . . . . . . 763 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766
Chapter 23 Implementing Performance Counters . . . . . . 769 Project Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 770 Project Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 771 Requirements Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 771 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 772 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 820 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 820
PART IX
BEYOND THE LAB . . . . . . . . . . . . . . . . . . 821
Chapter 24 Mobile Applications in .NET . . . . . . . . . . . . . 823 The Microsoft Mobile Internet Toolkit . . . . . . . . . . . . . . . . . . . 824 Mobile Web Forms Controls . . . . . . . . . . . . . . . . . . . . . . . . 825 Creating a Mobile Web Application by Using the Mobile Internet Toolkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 826 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 839
PART X
APPENDIXES . . . . . . . . . . . . . . . . . . . . . 841
Appendix A Upgrading/Migrating from Visual Basic 6.0 to Visual Basic .NET . . . . . 843 Migration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 844
i-xxvi.qxd 2/24/03 9:58 AM Page xxiii
Contents
Appendix B Migrating from VC++ 6.0 (unmanaged code) to VC++.NET (managed extensions) . . . . . . . . . . . . . . . . 851 Considerations for Using Managed Code . . . . . . . . . . . . . . . . . 852 Advantages of Using Managed Extensions . . . . . . . . . . . . . . 853 Managed Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 854 Creating a Managed Application . . . . . . . . . . . . . . . . . . . . . . . 855 Adding Managed Code to an Application . . . . . . . . . . . . . . . . . 858 Changing Project Settings . . . . . . . . . . . . . . . . . . . . . . . . . . 858 Adding the Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 860
Appendix C ATL for VC Programmers . . . . . . . . . . . . . . . 869 What Is ATL Server? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 871 Request Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 873 Other Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 875 Creating an ATL Server Application . . . . . . . . . . . . . . . . . . 876
Appendix D .NET Configuration Files . . . . . . . . . . . . . . . 883 Machine Configuration Files . . . . . . . . . . . . . . . . . . . . . . . . . . 884 Application Configuration Files . . . . . . . . . . . . . . . . . . . . . . . . 885 EXE-hosted Applications . . . . . . . . . . . . . . . . . . . . . . . . . . 886 ASP.NET-hosted Applications . . . . . . . . . . . . . . . . . . . . . . 886 Internet Explorer-hosted Applications . . . . . . . . . . . . . . . . . 886 Security Configuration Files . . . . . . . . . . . . . . . . . . . . . . . . . . . 886 .NET Framework Configuration Tool . . . . . . . . . . . . . . . . . . . 888 Configuration and Management of Assemblies . . . . . . . . . . 888 Adjusting the Remote Settings . . . . . . . . . . . . . . . . . . . . . . 889 Configuration and Management of Security . . . . . . . . . . . . 889
xxiii
i-xxvi.qxd 2/24/03 9:58 AM Page xxiv
xxiv
Contents
Managing the Applications Configured by the .NET Configuration Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 891 Code Access Security Policy Tool . . . . . . . . . . . . . . . . . . . . . . . 891 Create a Code Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 893 Delete a Code Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 893 Change Code Group Permissions . . . . . . . . . . . . . . . . . . . . 893
Appendix E Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . 895 Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 896 Private and Shared Assemblies . . . . . . . . . . . . . . . . . . . . . . 898 Global Assembly Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . 900 Benefits of Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 900 Assembly Versioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 902 Contents of an Assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . 903 Creating Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 903 Assembly Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 Public and Private Keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 Assembly Location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 907 Converting a Private Assembly to a Shared Assembly . . . . . 908
Appendix F Windows Forms Designer Generated Code . . . . . . . . . . . . . . . . . . . . . 911 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921
i-xxvi.qxd 2/24/03 9:58 AM Page xxv
Introduction Goal of the Book This book is designed as a “getting started” book for those programmers who want to get into programming using the predominant .NET languages, Visual Basic.NET and C#. In addition, the book enables readers to have a quick start on other salient programming features of the .NET Framework, such as Web services and mobile applications. This book is aimed at readers with programming knowledge of earlier versions of languages, such as Visual Basic and Visual C++. These readers are assumed to be experienced application developers who have knowledge of the earlier versions of Visual Basic. In addition, hands-on experience in Visual C++ is preferred. This book provides a hands-on approach to learning programming using Visual Basic.NET and C#. The book starts with a few overview chapters that introduce the .NET vision, .NET Framework, and .NET Server family to readers. A major part of the book revolves around professional projects, which are based on real-life situations. These projects follow a simple to complex approach to cover specific subject areas and guide the readers in implementing their learning in practical scenarios. Some of these projects include creating Windows applications using ADO.NET as the data access model, creating Windows applications illustrating the use of XML, creating Web applications using ASP.NET, creating Web services, creating mobile applications, and so on. The highlight of this book is that it guides the readers to create projects using both Visual Basic.NET and C#. These projects help readers to accomplish their goals by understanding the practical and real-life application of the various programming features of the .NET Framework using Visual Basic.NET and C#. Apart from the overview chapters and the professional projects, this book also includes another section, Appendixes. This section acts as a quick reference to some of the additional concepts that will help a reader to know about one other .NET language Visual C++.NET and also some additional information on Visual Basic.NET and other salient .NET programming features, such as .NET configuration files and assemblies.
i-xxvi.qxd 2/24/03 9:58 AM Page xxvi
xxvi
Introduction
How to Use This Book This book has been organized to facilitate a better grasp of content covered in the book. The various conventions used in the book include the following: ◆ Analysis. The book incorporates an analysis of code, explaining what the code does and why, line-by-line. ◆ Tips. Tips have been used to provide special advice or unusual shortcuts with the product. ◆ Notes. Notes give additional information that may be of interest to the reader, but is not essential to performing the task at hand. ◆ Cautions. Cautions are used to warn users of possible disastrous results if they perform a task incorrectly. ◆ New term definitions. All new terms have been italicized and then defined as a part of the text.
001-002.qxd 2/24/03 10:02 AM Page 1
PART
I
.NET Framework Overview
001-002.qxd 2/24/03 10:02 AM Page 2
This page intentionally left blank
003-026.qxd 3/5/03 2:16 PM Page 3
Chapter 1 .NET Vision and Design Goals
003-026.qxd 3/5/03 2:16 PM Page 4
he world of computing is fast moving towards the Web. Businesses today operate on varied technologies and platforms. The need of the hour is a uniform base for businesses to operate on and developers to develop on. The uniform base will enable developers to work on independent platforms and, at the same time, not bother about compatibility with other systems. Also, platforms that fully integrate with the Internet will provide businesses an opportunity that they never had before. Microsoft kept in mind these growing needs for the computer community when designing the .NET Framework. In this chapter, I’ll talk about the .NET vision and also about the design goals for developing effective business solutions using the .NET platform.
AM FL Y
T
TE
The .NET Vision
The .NET initiative aims at addressing the challenges facing organizations by combining an architectural vision with a complete set of Microsoft technologies. Application architects use these technologies to develop, deploy, and support multitier, distributed applications. The vision of the .NET initiative was to provide a highly integrated but flexible platform to enable developers to build end-to-end business solutions that can leverage existing architectures and applications. The Windows DNA architecture aimed at building tightly coupled, distributed Web applications. However, as the requirements for distributed applications moved towards more loosely coupled principles, Microsoft evolved the architecture to .NET.
The Philosophy of .NET The .NET philosophy aimed at providing a logical approach for developing successful business solutions. This philosophy intended to provide the ability to developers for developing flexible and scalable applications. The key principle of
Team-Fly®
003-026.qxd 3/5/03 2:16 PM Page 5
.NET VISION AND DESIGN GOALS
Chapter 1
creating distributed applications with the .NET Framework is to logically partition an application into three fundamental tiers or layers: ◆ Presentation layer ◆ Business logic layer ◆ Data access and storage layer By partitioning applications along these lines, by using component-based programming techniques, and by fully utilizing the features of the .NET Framework, developers can now build highly scalable and flexible applications and thus create successful business solutions. A simple application model consists of a client, or the presentation layer, that communicates with the middle tier. The middle tier, or the business logic layer, consists of the application server and an application containing the business logic. The application, in turn, communicates with a database that supplies and stores data, which is the data access and storage layer. Now I’ll talk about the elements of each tier in some more detail, starting with the presentation layer.
Presentation Layer The presentation layer consists of either a rich-client or thin-client interface to an application. The rich-client interface provides a full programming interface to the operating system’s capabilities and uses components extensively, either directly by using the Microsoft Win32 API or indirectly through Windows Forms. Using a thin-client interface (such as a Web browser), a developer can build business logic that can be executed on any of the three application tiers. With the features that the .NET Framework provides, the thin-client is able to provide a visually rich, flexible, and interactive user interface to applications. Thin-clients are also more portable across platforms.
Business Logic Layer The business logic layer, also called the application layer, is divided into application servers and services that support clients. Web applications can be written to take advantage of COM+ services, directory services, and security services using the .NET Framework. Application services, in turn, can interact with several data services on the data access layer.
5
003-026.qxd 3/5/03 2:16 PM Page 6
6
Part I
.NET FRAMEWORK OVERVIEW
Data Access and Storage Layer The data access and storage layer consists of data services that support data access and storage. The common data access services include: ◆ ADO.NET. Provides a simplified programmatic access to data by using either scripting or programming languages. ◆ OLE DB. An established universal data provider. ◆ XML. A markup standard for specifying data structures.
NOTE XML is a standard put forward by the Internet community. HTML focuses on how information is rendered by the browser and displayed on the screen. However, the goal of XML is to handle data structure and its representation.
Advantages of the .NET Framework By adopting the .NET Framework’s distributed application model, developers can derive many advantages. The .NET Framework provides developers with: ◆ A rich programming framework for building Win32 client applications ◆ A unified Web development platform that provides the services necessary for developers to build enterprise-class Web applications ◆ A URL-addressable resource that programmatically returns information to clients who have requested it ◆ The ability to build components that efficiently manage data from multiple data sources and that support disconnected scenarios ◆ A standards-based support for processing XML ◆ The ability to interact with COM components, .NET Framework services, external type libraries, and many operating system services ◆ The ability to control access to operations and resources based on policy and a set of configurable rules to determine which permissions to grant to code, based on the code’s domain, user, and assembly ◆ The ability to pass objects by value or by reference between distributed applications
003-026.qxd 3/5/03 2:16 PM Page 7
.NET VISION AND DESIGN GOALS
Chapter 1
◆ A programming interface to many of the protocols found on the network, such as HTTP, DNS, TCP, and UDP ◆ The ability to use the COM+ Services including transactions, object pooling, and queued components ◆ Access to the Active Directory from managed code ◆ Lower total cost of ownership by enabling powerful enterprise-class management of systems, applications, and devices ◆ Support for globalization and localization of resources As you can derive from these advantages, the .NET Framework offers a lot more than the ancestral programming languages and platforms. There is quite obviously an architectural shift in the way .NET is designed. I’ll now discuss the shift in the .NET Framework architecture, its causes, and its impact on the computer community.
Architectural Shift in .NET Ever since the computing mainstream moved towards Internet technologies, business computing models changed dramatically. This change was based on a complex, costly, and often, proprietary model, called the client/server-computing model. This was the revolutionary Web model. You can characterize the Web model as a collection of diverse information and applications that reside on varied hardware platforms. Since the inception of the Internet, constantly imploring the minds of the developer community has been the desire to provide a common information-delivery platform that is scalable, extensible, and highly available. The Web platform is flexible and limited by only the computer capacity and the imagination of the application designer. As the Web browser rapidly became omnipresent and Web servers proliferated throughout companies, it was clear—despite the best efforts of client/server software producers to Web-enable their products—that developers needed a radically different way of thinking about the application model. Obviously, new techniques and tools were required to meet the technology shifts and challenges facing developers.
7
003-026.qxd 3/5/03 2:16 PM Page 8
8
Part I
.NET FRAMEWORK OVERVIEW
Technology Shifts and Developer Challenges Once the Internet revolution took hold and new technologies appeared, developers faced several challenges that existing design models and tools could not address adequately. The following issues were central to the developers’ dilemma: ◆ Heterogeneous environments. One of the earliest, and perhaps biggest, challenges was the need to build applications that could easily integrate heterogeneous environments. Most large organizations had a diverse range of terminals, rich-clients, and thin-(Web)clients. In addition to accommodating the large client base, new applications had to interact with legacy data and applications hosted on mainframe and mid-range computers, often from different hardware vendors. ◆ Scalability. Before Internet technologies overwhelmed the computer community, the computing environment was a closed system due to the limitations in resources and access requirements. Scalability was, therefore, an issue that was easy to manage because strategists had ample historical data to base their projections for scaling the computing environment to match consumer demand. Also, the application development life cycle typically spanned several years, thus providing planners with ample time to plan for system and application scaling. However, the influx of the Internet altered the corporate mindset significantly. Organizations viewed this new technology as an ideal, low-cost method for sharing information throughout the organization. With the advantages, organizations realized the challenges. The new design paradigm required system designs to accommodate a user base size from less than one hundred to more than one million. The traditional foundation for scalability planning crumbled when companies opened their doors to the outside world. ◆ Rapid application development and deployment. The intranet and Internet phenomena highlighted the possibility of, and need for, rapid application deployment. As a result, the viability of the traditional development platform and processes were questioned. Organizations were not prepared to wait for years to be able to use an application. From an investment perspective, the business community questioned any investment in applications that would be legacy systems by the time they were completed. The concept of rapid application development changed even
003-026.qxd 3/5/03 2:16 PM Page 9
.NET VISION AND DESIGN GOALS
Chapter 1
further as organizations expanded their applications horizon from the intranet to the Internet. To be competitive, developers needed to create applications virtually on demand for immediate use—just-in-time ( JIT) development. To achieve this, they needed to completely revamp and revitalize their approach to applications development. ◆ Platform administration and management. It did not take long for professionals to realize that the Internet world was far from perfect. Professionals soon discovered that the freedom and flexibility brought a completely new set of administration and management issues that revolved around clients, applications, and hosts. The browser, for one, did not have an industry standard and, from a development perspective, the lack of standardization meant that application designers had to accommodate the HTML rendering capabilities of each browser version separately. Application deployment was even more difficult to manage because system administrators had to contend with large numbers of content providers rather than a single developer group. Dynamic and data-driven content on the Web sites made management even more difficult due to the existence of diverse data stores and different scripting languages, as did the users’ expectations of 24-hour/7-day uninterrupted access. ◆ Network-aware applications. Advances in portable computing technology and the decline in cost for portable computers, such as laptops, notebooks, and palmtops, put the final nail in the coffin for Web application developers. Mobile computing has evolved at an unprecedented rate. Developers no longer have the liberty to distinguish between offline and online usage because the user community expects to be able to use applications and services at all times. All these challenges posed problems that the developer community needed solutions to. The .NET Framework architecture provided all these solutions and more, as you’ll see through the course of this book. The .NET Framework guided application developers to be able to create welldesigned applications to overcome the challenges posed by the traditional development platforms. Precise goals for the design phase of the application development life cycle were defined in order to provide a direction to developers. In the following sections, I’ll talk about the design goals of the .NET Framework.
9
003-026.qxd 3/5/03 2:16 PM Page 10
10
Part I
.NET FRAMEWORK OVERVIEW
.NET Framework Design Goals During the design phase of an application, design goals are established. The design goals relate to the following aspects of application development: ◆ Availability. Is the application to be present and ready for use? ◆ Manageability. Can the application be administered? ◆ Performance. What is the measure of an application’s operation under load? ◆ Reliability. Is the application able to perform in a predictable manner? ◆ Scalability. Can the application match increasing demand with an increase in resources? ◆ Securability. Is the application ready to protect its resources? In the subsequent sections, I’ll discuss each of the preceding aspects in detail and also discuss how the .NET Framework supports application development with these design goals in mind.
Availability All applications must be available at least some of the time, but Web-based applications and mission-critical enterprise applications must typically provide roundthe-clock services. If your enterprise application needs to work round-the-clock, you need to design your application for high availability. Availability implies the uptime for your applications—the amount of time your applications are available for use. Advances in hardware and software have dramatically increased the quality of high-availability applications. However, availability is not easy to implement and requires a considerably more complex architectural infrastructure than the previous generations of client/server applications. If your application requires high availability, you’ll need to understand how design choices help maximize application availability and how testing can validate planned service levels. Companies that increasingly rely on Web-based, distributed applications for important business activity need a range of availability engineering options to meet service level requirements in a cost effective manner. Web-based applications usually depend on multiple servers, perhaps hundreds or thousands of client workstations, internal and external network communications, database services,
003-026.qxd 3/5/03 2:16 PM Page 11
.NET VISION AND DESIGN GOALS
Chapter 1
operational processes, and a host of other infrastructure services that must all work uniformly together. Where the business ideal is a continuous flow of information, creating high-availability applications becomes an important business strategy. Realistically, not all applications require 100% uptime. However, some applications must provide very high availability with virtually no perceivable downtime. But as the complexity and access volume of distributed applications grows, the chances of application failures also increases. Application failures occur for many reasons, including: ◆ Lack of stable software engineering processes ◆ Weak code ◆ Inadequate testing ◆ Change management problems ◆ Lack of constant monitoring and analysis ◆ Interaction with external services or applications ◆ Different operating conditions, such as usage level changes and peak overloads ◆ Unusual events, such as security failures and broadcast storms ◆ Hardware failures, such as disks, controllers, network devices, servers, power supplies, memory, and CPU failures ◆ Natural disasters If applications fail as a result of natural disasters, there’s not much that you can do. However, such causes for application failures are pretty low as compared to the causes that you can prevent—just about 10% of the total application downtime. The other 90% of application downtime is a combined result of inadequate testing, change management problems, lack of ongoing failure monitoring, and lack of rigorous procedures and backup/restoration errors. Availability is, for the mathematicians out there, a percentage calculation based on how often the application is actually available to handle service requests when compared to the total, planned, available runtime. The application downtime, obviously, includes the time to repair because applications being repaired are not available for use. Commonly, availability is expressed as a percentage, such as 99% availability.
11
003-026.qxd 3/5/03 2:16 PM Page 12
12
Part I
.NET FRAMEWORK OVERVIEW
What might surprise you is the fact that 99% availability is not too great by industry standards. In fact, if your application is 99% available, it is actually down for 88 hours in a year. Similar calculations disclose that 99.9% availability means 8.5 hours of downtime per year and 99.99% availability means a downtime of 1 hour per year. As per industry standards, it is common for enterprise applications to have 99.9% availability. However, as you move towards greater availability, you face greater challenges in the form of: ◆ Increasing hardware costs for the application due to server, network, and disk redundancy ◆ Greater difficulty in identifying and eliminating complex failures ◆ Growing requirements for comprehensive testing of every automatic and people-based procedure that may affect your application Choosing the right hardware and software technology infrastructure certainly helps the high-availability cause. Also, high levels of availability are not possible without a serious commitment to skilled personnel, quality lifecycle processes, and operational excellence.
Planning Availability Levels Determining the satisfactory availability levels for your requirements is never easy. Not only is it difficult to estimate the actual required availability that satisfies the anticipated business requirements and also meets budget and schedule expectations, also the usage pattern and running environment of software can change over time. The original availability assumptions might change and, as a result, might require reconsideration of the original availability plans. In deciding what level of availability is appropriate for your application, you need to answer a few questions: ◆ Who are the customers and what are their expectations? ◆ How much downtime is acceptable? ◆ Do internal company processes depend on the service? ◆ What is the schedule and budget? A project’s schedules and budget should not conflict with a requirement for business- or mission-critical availability. While it is tempting to build and deploy a less-than-perfect version of your application, don’t do it: the cost of round-the-
003-026.qxd 3/5/03 2:16 PM Page 13
.NET VISION AND DESIGN GOALS
Chapter 1
clock maintenance hassles and lost customers isn’t worth it. If you must implement a high-availability application and the budget and schedules aren’t viable, the right thing to do is to retarget the scope of the project and get the appropriate funding. Designing for availability poses difficult challenges. Because of the wide variety of application architectures, no single availability solution works for every situation. The decision to deploy a comprehensive, fault-tolerant, fully redundant, load-balanced solution may be appropriate for high-volume, online transaction processing. On the other hand, some applications can accept modest downtime with little consequence to the customers. Ultimately, such design decisions depend on a combination of business requirements, application-specific data, and the available budget. If your work revolves round Web-based distributed applications, you must realize that such applications have a certain recurring architectural theme—front-end Web services, back-end data services, and management infrastructure. The main technique for increasing availability is redundancy, so you take a close look at your application’s architecture and decide to implement full redundancy including cloned front-end servers, redundant network infrastructure, and cloned back-end servers.
Designing for Availability Engineering your applications for availability is all about doing your best to create reliable applications. You must also be ready to accept the fact that your application will probably fail sometimes. So, you must design quick recovery mechanisms to minimize downtime. The single most important aspect in designing for availability is minimizing downtime. To achieve this, you must anticipate, detect, and automatically resolve hardware or software failures before they result in service errors, event faults, or data corruption. Some design ideas for generating highly available applications are listed below. However, you must not forget the basic requirements of having tested and proven lifecycle processes, trained staff, and a rigorous commitment to availability. ◆ Avoid older, traditional approaches to availability, such as multiple CPUs and duplicated system with fully replicated components. These approaches have several drawbacks.
13
003-026.qxd 3/5/03 2:16 PM Page 14
.NET FRAMEWORK OVERVIEW ◆ Reduce unplanned downtime with clustering. Cluster service with a shared disk avoids most downtime and provides automatic recovery from hardware or software failures. ◆ Use network load balancing to redefine clusters and redirect traffic to other servers in case of failures. ◆ Use redundant array of independent disks (RAID) for data stores to use multiple hard disks so that data is stored in multiple places. ◆ Reduce planned downtime by using rolling upgrades available with Windows 2000 Advanced Server.
AM FL Y
Part I
◆ Isolate mission-critical applications. Eliminate data and system dependencies by using separate physical backbones for each in case of missioncritical applications. ◆ Use queuing to enable your application to communicate with other applications by sending and receiving asynchronous messages. ◆ Use Distributed File System (DFS) to resolve drive letters to Universal Naming Conventions (UNC) names to provide real file nomenclatures.
TE
14
Testing for Availability
Testing for availability means running an application for a planned period of time, collecting failure events and repair times, and comparing the availability percentage to the original estimate. Some testing concepts that can help you create long-term, highly available applications are listed below. ◆ Test the change control process ◆ Test catastrophic failure and recover technologies ◆ Test the failover technologies ◆ Test the monitoring technology ◆ Test the help desk procedures ◆ Test for resource conflicts
Team-Fly®
003-026.qxd 3/5/03 2:16 PM Page 15
.NET VISION AND DESIGN GOALS
Chapter 1
Best Practices for Availability The following best practices are recommended for creating applications with high-availability: ◆ Use clustering ◆ Use network load balancing ◆ Use service level agreements ◆ Provide vigilant monitoring ◆ Establish a help desk to reduce downtime ◆ Test the recovery plan ◆ Choose good infrastructure ◆ Synchronize all clocks ◆ Use data backups ◆ Review all security plans ◆ Advocate training and certification ◆ Pay attention to the budget
Manageability Managing distributed applications can be a whole new experience than managing traditional, stand-alone applications because distributed Web-based applications pose an interesting problem. While customer access and data exchange with business partners has become easier, the ability to diagnose and resolve emerging capacity and resource problems has become more difficult. Distributed applications make you worry about where things are on the network, how components are deployed and configured, and how to set the security attributes for thousands of different users. You also can’t help wondering if the application is working as intended. Managing an enterprise application contributes highly to the total cost of ownership. But to minimize operation and management costs, you want the cost of ongoing application administration to decrease. This is a dilemma that the new emerging technologies have brought with them. As a solution, you need an efficient way to deploy, configure, upgrade, and monitor all local and remote components and services of your distributed application.
15
003-026.qxd 3/5/03 2:16 PM Page 16
16
Part I
.NET FRAMEWORK OVERVIEW
Managing a modern .NET application requires an efficient way to handle local and remote application support processes, including: ◆ Initial deployment ◆ Configuration tuning ◆ Scheduled and unscheduled maintenance ◆ Frequent health checks ◆ Occasional troubleshooting
Designing for Manageability Designing an application for manageability involves providing an information infrastructure so that the application and all its important supporting services and devices can be monitored for possible corrective and preventive action. Manageability for an enterprise-scale application should include some efficient way to handle common administrative tasks such as local and remote installation, configuration changes, and maintenance updates over the lifetime of the application. Generally, designing manageable distributed applications requires three design features: ◆ Management agents. Each hardware device, operating system service, and application service requires a management agent. Management agents monitor the local resource and publish data about the resource’s current state and performance. Management agents also provide local configuration services as a way to make remote management possible. ◆ Collection process. The information collection process collects, filters, correlates, and stores information from all of the management agents. ◆ Management console. The management console workstation aggregates and reports on application management information. From this central console an administrator can monitor all devices, analyze operational profiles, automate certain recurring activities, receive notifications from managed elements, and initiate remote configuration changes. In addition to a sound design, you also need to collate application information over the applications’ lifetime to ensure constant manageability. Following is a list of sources from which you can collect application information to help you identify problems and derive solutions to manage distributed applications efficiently:
003-026.qxd 3/5/03 2:16 PM Page 17
.NET VISION AND DESIGN GOALS
Chapter 1
◆ Performance counters ◆ Event Log ◆ Operating services ◆ Windows installer ◆ Active Directory ◆ Registry ◆ Server, network, and workstation hardware ◆ Application services ◆ Windows Driver Model (WDM) ◆ HTTP requests ◆ File transfer protocol (FTP) requests ◆ Internet Control Message Protocol (ICMP) messages ◆ Simple Mail Transfer Protocol (SMTP) messages The .NET Framework, along with Windows 2000 Server, provides tools, utilities, features, and technologies that facilitate effective management of distributed applications, including the following: ◆ Desktop Configuration. Active Directory structures a network into a hierarchy of sites, domains, and smaller working units instead of a flat list of users. Administrators can easily install Windows 2000 anywhere on the network. IntelliMirror helps with data management for roaming users. IntelliMirror also handles automatic software installation and upgrades, group policy enforcement, and central management of user environment settings. The Windows Installer Server handles application modification, repairs, and removal. Remote OS Install helps with setting up a new computer, reformatting, and reinstalling on an existing workstation. ◆ Infrastructure Management. The Microsoft Management Console (MMC) is a consistent, self-revealing, easy-to-use interface for all administrative activities. Windows Management Instrumentation (WMI) helps create, store, and analyze application operational data. Other infrastructure management features include the Systems Management Server (SMS), Server Configuration Wizard, Terminal Services, Task Scheduler, Unattended Setup, Disk duplication, Repair Command Console, Safe
17
003-026.qxd 3/5/03 2:16 PM Page 18
18
Part I
.NET FRAMEWORK OVERVIEW
Mode Boot, Security Services, Security Configuration Manager, Public Key Infrastructure (PKI), and Kerberos Authentication. ◆ Storage Management. The Removable Storage Manager (RSM) enables multiple applications to share tape and disk drives. With RSM, administrators can initiate real-time tasks while the system remains online. The Hierarchical Storage Management (HSM) feature handles migration of infrequently used data to archive storage devices. The Server Backup Utility protects applications from accidental data loss. ◆ Single Image Cluster Management. All servers in single cluster are viewed as just one server. You can easily add new servers and maintain existing servers. It is easy to maintain important information such as machine names, IP addresses, network interface cards, and the application image that defines the exact component configuration for your application. With cluster synchronization, any change to the application image can update all servers automatically either on demand or at a periodic time interval. ◆ Network Load Balancing. Network Load Balancing (NLB) delivers scalable, high-performance failover protection for business- and missioncritical applications. NLB dynamically distributes incoming client requests across multiple servers. A side benefit of NLB is that it will automatically detect the failure of a server and redirect client traffic, thus providing continuous service. ◆ Change Management. Change management allows upgrades to servers without introducing downtime. Enables controlled, staged deployment from development workstations through to the final production environment. Provides quick rollback of failed deployments. ◆ Application Synchronization. Application synchronization keeps your application content, configuration, and components consistent across all the computers in the server cluster. ◆ Monitoring Capabilities. Monitoring capabilities provides real-time views of system configuration and operational performance to facilitate proactive fault detection and automated recovery from both server and application problems. ◆ Manual or Automated Processes. Besides extensive manual processes, you can use scripting languages to handle complex, repetitive tasks.
003-026.qxd 3/5/03 2:16 PM Page 19
.NET VISION AND DESIGN GOALS
Chapter 1
These tasks might include automated configuration of NLB, Component Load Balancing (CLB), or application deployment. ◆ Systems Management Server. Systems Management Server (SMS) provides tools for planning, deploying, and diagnosing distributed software without making on-site visits. These include utilities such as remote reboot and a server monitoring utility called HealthMon for displaying critical performance information. ◆ Performance Monitor. PerfMon is useful for monitoring system resources, application bottlenecks, and program efficiency. Common uses for PerfMon are to monitor how much memory an application is using, how badly a computer is paging, and how much CPU time a process is taking. PerfMon can be used to log data, send alert messages to the Event Log when a counter exceeds a preset boundary, and even run a program when a counter goes over a limit you have set. ◆ System Preparation Tool. SysPrep enables administrators to prepare Windows 2000 System Images as part of an automated deployment procedure. You can easily use SysPrep to deploy Windows 2000 installations on multiple machines. First, complete an initial setup on a single system and then simply duplicate the initial machine with a few configuration differences (such as IP address and machine name). ◆ Simple Network Management Protocol. You can use Simple Network Management Protocol (SNMP) to configure remote devices, monitor network performance, audit network usage, and detect network faults or inappropriate access. ◆ HTTP Monitoring Tool. HTTPMon provides a statistical analysis of Web server activity. ◆ Robocopy. Robocopy simplifies the task of maintaining an identical copy of a directory tree in multiple locations either on the same machine or in separate network locations. You can use Robocopy to replicate files on demand. ◆ Microsoft Web Capacity Analysis Tool. Microsoft Web Capacity Analysis Tool (WCAT) runs simulated workloads on client/server configurations. Using WCAT, you can test how Internet Security and Acceleration Server (ISA) and your network configuration respond to a variety of different client requests and workload situations. The results of these tests can be used to optimize the server and network configuration.
19
003-026.qxd 3/5/03 2:16 PM Page 20
20
Part I
.NET FRAMEWORK OVERVIEW ◆ Visual Studio Analyzer. Visual Studio Analyzer analyzes performance problems, isolates faults, and can help you understand the structure of your distributed applications. This tool dynamically explores the structure of distributed applications by using the data instrumentation already built into Windows 2000 technologies (such as COM+, ADO.NET, and MTS).
Testing for Manageability Testing for manageability is about making sure that the deployment, maintenance, and monitoring technologies you have designed into your application are working as expected. Some important testing recommendations for verifying that you have created a manageable application include: ◆ Testing cluster configuration ◆ Testing network load balancing ◆ Testing application synchronization ◆ Testing change control procedures The most significant best practice for manageability is to build health checks into your application.
Performance Commonly application metrics, such as transaction throughput and resource utilization, define application performance. Network throughput and disk access are common application performance bottlenecks. From a user’s perspective, application response time defines performance. But often, you’ll find yourself at a crossroad, where one path leads you to high performing applications, and the other leads to cost control. You must take your pick intelligently. Performance problems typically do not become apparent until testers place an application under an increased load. However, the responsibility for application performance is eminent both at design time and at run time. At design time, developers must prevent using code that could hinder the application’s performance. Developers can follow accepted programming practices and take advantage of the inherent performance enhancing capabilities of the pro-
003-026.qxd 3/5/03 2:16 PM Page 21
.NET VISION AND DESIGN GOALS
Chapter 1
gramming language. A common method for identifying troublesome code is to conduct routine code reviews and audits. At run time, the application should undergo extensive performance testing to identify application bottlenecks, such as contention for resources or slow-running code. However, before conducting extensive performance tests make sure that the application is functionally sound.
Designing for Performance It is imperative that you define performance requirements before you start development and debugging. You must do the following before you start developing your application: ◆ Identify project constraints, such as schedules or choice of tools and technologies that you can use. ◆ Determine services that the application will perform, including performance scenarios, database access, and other services. ◆ Specify the load on the application, such as the number of clients that will use this application and how much time elapses between the response and request chain. You can then use this information to select appropriate metrics and determine specific performance goals.
Testing for Performance After you identify specific performance requirements and have developed your application, you can begin testing to determine whether the application meets those requirements. Performance testing presumes that the application is functioning, stable, and robust. Performance monitoring is primarily a collection of the following related activities: ◆ Measuring performance ◆ Defining performance tests ◆ Determining baseline performance ◆ Performing stress testing ◆ Solving performance problems
21
003-026.qxd 3/5/03 2:16 PM Page 22
22
Part I
.NET FRAMEWORK OVERVIEW
Reliability As distributed Web-based applications continue to influence everything from your customers’ experience to your relationship with vendors, there is an increasing need to improve the reliability and operating quality of software. Reliability is all about an application’s ability to operate failure free. Reliability is important primarily because: ◆ The cost of application failure is high. ◆ The expense of repairing corrupted data is high. ◆ Users bypass unreliable Web sites, resulting in lost revenue and reduced future sales. ◆ Unreliable systems are difficult to maintain or improve because the failure points are typically hidden throughout the system. ◆ Modern software technology makes it easy to create reliable applications. It is important that you become familiar with how to include reliability characteristics in your application design in the pursuit of reliability through the entire software development lifecycle.
Designing for Reliability The process of designing applications for reliability involves estimating the application’s expected usage pattern, specifying the required reliability profile, and engineering the software architecture with the intention of meeting the profile. Creating a high-reliability application depends on the entire software development lifecycle from early design specification, through building and testing, to deployment and ongoing operational maintenance. Good reliability designs typically do the following: ◆ Put reliability requirements in the design specification ◆ Use good architectural infrastructure ◆ Build management information into the application ◆ Use redundancy for reliability ◆ Use quality development tools ◆ Use built-in application health checks ◆ Use consistent error handling
003-026.qxd 3/5/03 2:16 PM Page 23
.NET VISION AND DESIGN GOALS
Chapter 1
Testing for Reliability Testing for reliability is about exercising an application so that failures are discovered and removed before the system is deployed. It is no doubt difficult to identify all potential problems, but you should aim at identifying as many as you can by estimating various usage scenarios. Important testing strategies include the following: ◆ Component stress testing ◆ Integration stress testing ◆ Real-world testing ◆ Random destruction testing
Best Practices for Reliability For creating and deploying reliable applications, it is important that you keep reliability as a foremost concern throughout the application development life cycle. Best practices for reliable application development include: ◆ Investing in people ◆ Using a robust operating system ◆ Removing failure points from your application design ◆ Providing ongoing reliability monitoring ◆ Investing in quality software engineering processes ◆ Using smart testing ◆ Deploying changes very carefully
Scalability Scalability is the capability to add resources to an application to produce an equivalent increase in service capacity. A scalable application follows the principle that additional load only requires additional resources rather than extensive modification of the application itself. Scalability must be part of the design process because it is not a discrete feature that you can add later.
23
003-026.qxd 3/5/03 2:16 PM Page 24
.NET FRAMEWORK OVERVIEW
Designing for Scalability Design of an application has the greatest impact on its scalability. Smart designs can greatly improve the scalability of applications. Other factors that influence scalability, though on a lesser scale, include hardware, software, and code. The primary goal when designing for scalability is to ensure efficient resource management. To design applications for high scalability, keep the following design aspects in mind: ◆ The application must not have to wait any more than is absolutely necessary for using vital resources.
AM FL Y
Part I
◆ The application must not have to contend for resources, such as memory, processor, and bandwidth, with other applications. ◆ The application must be designed for commutability—operations should be able to be applied in any order to achieve the same results. ◆ The application must be designed for interchangeability by using resource pooling with technologies such as COM+ and ODBC connections.
TE
24
◆ The relationship between resources and activities must be minimized to avoid bottlenecks.
Testing for Scalability To make truly scalable applications, it is critical that you rigorously and regularly test it for scalability problems. The purpose of scalability testing is to identify major workloads and mitigate bottlenecks that can impede the scalability of the application. If your application does not meet performance requirements, you should analyze data from the test results to identify bottlenecks in the system and to derive a cause. You can also identify bottlenecks using tools such as Windows Task Manager, Windows Performance Monitor, and the Component Services administrative tool. You can often alleviate bottlenecks through performance tuning.
Team-Fly®
003-026.qxd 3/5/03 2:16 PM Page 25
.NET VISION AND DESIGN GOALS
Chapter 1
Securability Securability is the ability to provide security to an application and its data. The securability of an application is impacted by numerous design choices, such as the selection of communication protocols and the method of user authentication. Security is about controlling access to a variety of resources, such as application components, data, and hardware.
Designing for Securability Security is an issue that can affect your application, and consequently you, everyday. New security threats emerge daily. You want your applications to contend with malicious code, unauthorized users, and many such security threats. It is extremely important that securability of your application is constantly monitored. Following are some guidelines to help you design secure applications: ◆ Analyze the impending threats. Threats could include spoofing identity, tampering with data, repudiability, information disclosure, denial of service, and elevation of privilege. ◆ Prioritize the threats based on the criticality, effort involved in eliminating the threat, and potential damage to your application. ◆ Apply available security policies to your application. ◆ Select appropriate and applicable security technologies based on the type of threats. ◆ Design security services that your application must support.
Testing for Securability Security testing is about validating your application’s security services and identifying potential security flaws. However, there are no standard methods of conducting security testing since attackers have no standard method of breaking into things. Some methods that you can use to test the securability of your applications include: ◆ Testing for buffer overflows ◆ Conducting source-code security reviews ◆ Validating contingency plans ◆ Attacking your application
25
003-026.qxd 3/5/03 2:16 PM Page 26
26
Part I
.NET FRAMEWORK OVERVIEW
Best Practices for Securability The following are some best practices for developing secure applications: ◆ Exercise constant vigilance ◆ Conduct periodic reviews ◆ Establish and follow security policies ◆ Secure data ◆ Use access control mechanisms ◆ Use the least-access approach ◆ Enable strong authentication ◆ Encourage the use of strong passwords ◆ Use system-integrated authorization ◆ Avoid buffer overflows ◆ Require minimal privileges ◆ Layer your application ◆ Validate user input ◆ Develop contingency plans ◆ Conduct scheduled backups ◆ Monitor not-found errors ◆ Use a perimeter network to protect your internal network ◆ Develop applications using the .NET Framework
Summary In the preceding sections, you learned about the vision of .NET and the roots behind its evolution. You also learned how to design world-class applications by following the standard design goals and approaches. In the subsequent chapters of this book, I’ll take you through the various technologies that constitute the .NET Framework. I'll show you how to design applications in the .NET Framework, how to secure them, and how to deploy them. Welcome to the .NET Framework!
027-066.qxd 2/24/03 10:30 AM Page 27
Chapter 2 The .NET Family
027-066.qxd 2/24/03 10:30 AM Page 28
ith the current emphasis on the .NET Framework and its benefits to e-commerce, Microsoft has introduced a set of products and services that you can use to implement business solutions using the .NET Framework. These products and services essentially form the .NET family and comprise .NET Enterprise Servers, .NET Server, Windows XP, and the .NET Passport service. In addition, Visual Studio.NET forms an integral part of the aforementioned set by helping you to create applications by using the .NET Framework.
W
In this chapter, you will be introduced to .NET Enterprise Servers, .NET Server, and Windows XP and will examine their roles in the .NET Framework. You will also look at the benefits and working of .NET Passport service. In addition, you will get an overview of Visual Studio.NET.
.NET Enterprise Servers An important requirement in business is to continually find better and easier ways to enhance business opportunity and get an edge over competitors. This constant endeavor requires companies to look for and implement solutions to build an integrated and scalable business infrastructure. .NET Enterprise Servers provide the solution to such a quest. .NET Enterprise Servers provide an environment that enables you to benefit from the latest technology, the .NET Framework, and apply the technology to meet the growing demands of the online market. .NET Enterprise Servers allow companies to create scalable business infrastructures that can be implemented with ease and reliability. An enterprise can use .NET Enterprise Servers to implement and manage solutions to Web enable businesses. With a view to Web enable businesses, .NET Enterprise Servers have been designed keeping two considerations in mind. The first consideration is to provide accessibility to all Web users. To facilitate this, the servers have been built using open Web standards such as XML. The second consideration is the interoperability and the scalability of the servers. The servers have been created to ensure interoperability with the existing infrastructure.
027-066.qxd 2/24/03 10:30 AM Page 29
THE .NET FAMILY
Chapter 2
The .NET Enterprise Servers include: ◆ Application Center 2000 ◆ BizTalk Server 2000 ◆ Commerce Server 2000 ◆ Content Management Server 2001 ◆ Exchange 2000 ◆ Host Integration Server 2000 ◆ Internet Security and Acceleration (ISA) Server 2000 ◆ Mobile Information 2001 Server ◆ SharePoint Portal Server 2001 ◆ SQL Server 2000 The next sections will discuss the role of each .NET Enterprise Server in the .NET Framework.
Application Center 2000 Often, companies host high-availability Web applications. As a developer or a Web site administrator, you can deploy and manage such applications built on Windows 2000 by using Application Center 2000. Application Center 2000 is a server that facilitates the deployment and management of Web applications by implementing clustering. Application Center 2000 allows you to create groups that include elements of an application, such as Web sites and COM+ components, which can be managed through an Application Center cluster. Further, cluster management is simplified by allowing you to manage an entire cluster of servers as a single server. Application Center 2000 also supports the automation of application deployment from one cluster to another. The changes resulting from a deployment are synchronized across all the members in a cluster. Therefore, an Application Center cluster offers the same content to users independent of the cluster member catering to client requests. Additionally, Application Center clusters are scalable, thereby allowing you to add or remove members to or from the cluster based on requirement. For instance, a Web site offers e-mail services. However, the increased traffic on the site demands
29
027-066.qxd 2/24/03 10:30 AM Page 30
30
Part I
.NET FRAMEWORK OVERVIEW
the addition of a server to the existing cluster. In such a case, you can add an offthe-shelf server with Application Center 2000 installed to the existing cluster. You might also need to remove an Application Center cluster member in the event of a server failover or when the capacity requirement of Web applications decreases. You can add or remove servers to and from the Application Center cluster without any disruption in the availability of the Web site. Therefore, applications always remain available irrespective of the fact that a server component has been removed or is malfunctioning. In its effort to ensure the continued availability of a Web site, Application Center 2000 also offers monitoring capabilities. Application Center 2000 can be used for performance checks on either an entire cluster or individual members of a cluster. You can also use Application Center 2000 to automate responses to specific events or conditions. For instance, when the processor usage of a cluster member exceeds the threshold limit, all subsequent user requests for similar resources will be redirected to an alternate cluster member. As an additional feature to manage clusters and maintain Web site availability, Application Center 2000 supports the distribution of workload among members of a cluster. Application Center 2000 supports Network Load Balancing (NLB) to balance IP requests and Component Load Balancing (CLB) to balance the activation of COM+ components across cluster members.
BizTalk Server 2000 With a vast range to choose from, you can create applications in different formats based on the ease of use or the functionality required. This poses compatibilityand interoperability-related problems across platforms. You can integrate applications created using different formats by using BizTalk Server 2000. BizTalk Server 2000 provides a suite of tools and services that you can use to create and deploy integrated business processes within an organization or across organizations. These graphical tools, such as BizTalk Orchestration Designer and BizTalk Messaging Manager, empower you to integrate, manage, and automate dynamic business processes. The all-important task of online document exchange across organizations involves an entirely different set of problems. The first and foremost concern is the integrity and security of the document in transit. BizTalk Server 2000 not only ensures the integrity of all communication and data exchange between transacting parties, it also ensures the security of the communication and data transfer.
027-066.qxd 2/24/03 10:30 AM Page 31
THE .NET FAMILY
Chapter 2
To facilitate a secure document exchange, BizTalk Server 2000 implements secure and reliable connections irrespective of the operating system, programming language, or programming model. For this purpose, BizTalk Server 2000 uses technologies such as public key encryption and digital signatures. Apart from the security risks, the electronic exchange of documents is also marred with problems related to exchange across different platforms. BizTalk Server 2000 resolves the exchange of documents across platforms by managing data translation, encryption, and data tracking services. For instance, BizTalk Server 2000 tools, such as BizTalk Mapper, ensure transformation of documents into a commonly accepted format. BizTalk Server 2000 uses an open industry framework called BizTalk Framework 2.0 to facilitate routing and analysis of data and documents exchanged across electronic or organizational barriers. Another important tool in BizTalk Server 2000 that allows you to manage document exchange between applications and trading partners is the BizTalk Messaging Manager.
NOTE To facilitate document exchange across dissimilar systems, all documents are exchanged in the XML format.
BizTalk Server 2000 also offers tools, such as BizTalk Orchestration Designer, that allow the use of XLANG, an XML-based language. BizTalk Orchestration Designer is used to create drawings that depict the interactions and procedures during a process. Business process drawings created using BizTalk Orchestration Designer can be compiled and run as XLANG schedules. An XLANG schedule describes the business processes that help bind the process to application services.
Commerce Server 2000 Generally, organizations are in search of a scalable platform that they can readily customize to create e-commerce Web sites in a cost-effective and less cumbersome way. This is exactly what Commerce Server 2000 has to offer. Commerce Server 2000 is a server that provides you with the ability to create e-commerce sites quickly and with ease. To facilitate the creation of e-commerce sites, Commerce Server 2000 provides Solution Sites that you can readily use as templates to create your own Web sites. You can build upon Solution Sites by adding new functionalities and enhancements
31
027-066.qxd 2/24/03 10:30 AM Page 32
32
Part I
.NET FRAMEWORK OVERVIEW
as per customer and organizational requirements. For instance, Commerce Server 2000 provides an infrastructure that is capable of product and service management, transaction processing, and user profiling. You can customize this infrastructure to meet your requirements. Commerce Server 2000 also empowers business managers to manage Web sites in a real-time environment. This, in turn, implies that whenever the content on the Web site is updated to meet customer requirements, the changes take effect immediately. As a result, it gives them a chance to provide highly personalized and relevant content on their site at all times. Additionally, with Commerce Server 2000, you can provide business managers with essential decision-support mechanisms, such as data warehousing and data mining. The server also incorporates analytical capabilities that can be used to analyze business scenarios and update sites in real time based on the results of the analysis. For instance, business managers can use Commerce Server 2000 to analyze site usage and then enhance the content or functionality with a view to increase the number of users visiting the site. You can integrate Commerce Server 2000 with other .NET Enterprise Servers to provide enhanced functionalities. A few .NET Enterprise Servers that you can integrate with Commerce Server 2000 are BizTalk Server 2000 and Host Integration Server 2000. You can use such integrations to create enhanced systems that can utilize e-commerce sites built using Commerce Server 2000. For instance, you can integrate Commerce Server 2000 with BizTalk Server 2000 to ensure data and document exchange across dissimilar systems. You can also integrate COM+ services to create scalable and distributed applications.
NOTE COM+ combines Microsoft Component Object Model (COM) with Microsoft Transaction Server (MTS). You can use COM+ to create and deploy highly scalable, distributed, and component-based solutions.
Content Management Server 2001 Not only is the maintenance of content-driven Web sites difficult, the creation of such sites is also time consuming. As the name of the server suggests, Content Management Server 2001 enables content providers to effectively manage Web content. You can readily develop, publish, and maintain highly dynamic
027-066.qxd 2/24/03 10:30 AM Page 33
THE .NET FAMILY
Chapter 2
content-driven Web sites for the Internet and intranet by using Content Management Server 2001. Content providers can use the built-in templates called presentation templates to create Web sites. These templates are used to design the Web site and the layout of the site. These templates also provide you the flexibility to redesign the Web site in real time. To ensure consistency in the Web site design and exercise control over the content on the Web site, you can use Template Galleries and Resource Galleries. This feature of Content Management Server 2001 manages the templates and resources of a Web site. The content on the Web site is not bound to the presentation templates that govern the design and layout of the Web site. Therefore, it is possible to publish content to multiple locations or Web sites and dynamically publish content in real time. To ensure dynamic and real-time updating of Web content, Content Management Server 2001 implements caching of objects in RAM and on the hard disk. This considerably reduces the time taken to download content. Content Management Server 2001 offers a novel way to archive all the updated documents automatically. You can also track versions of a particular document. In addition, Content Management Server 2001 permits multiple levels of review and approval of the document before the document is published on a Web site. It is also possible for users to schedule the publication and archival of content by using scheduling tools. Apart from real-time updating and archiving of content, it is also possible to provide personalized content based on the profile or the browsing device. You can ensure customized content based on the profiles of audiences, devices used, and the purpose for viewing content. For instance, if an existing document needs to be changed, a reviewer of the document gets a version of the document marked for review. At the same time, an end user will only be able to view the last published version of the document. The new edited and reviewed document will be available to the user only after it is signed off and published. As with other .NET Enterprise Servers, Content Management Server 2001 permits scalability to meet the growing demands of an ever-changing online market. You can create clusters of servers running Content Management Server 2001 and ensure workload balancing. Content Management Server 2001 also supports integration with Windows 2000 Advanced Server, SQL Server 2000, Commerce Server 2000, and FrontPage 2000.
33
027-066.qxd 2/24/03 10:30 AM Page 34
Part I
.NET FRAMEWORK OVERVIEW
Exchange 2000 Communication forms the backbone for any business establishment. With most commercial transactions shifting to the Internet, it becomes essential to supply the right information to the right person at the right time. Therefore, there lies an emphasis and requirement for a reliable and scalable messaging service. Exchange 2000 is a messaging infrastructure that can provide the necessary solutions to the communication-related problems of an enterprise.
AM FL Y
To meet the growing demands of an organization in terms of communication, Exchange 2000 supports a range of collaborative activities. A few of these activities include discussion groups and scheduling capabilities. To facilitate access to information across geographic and organizational barriers, Exchange 2000 supports features such as instant messaging and video conferencing. For audio and video conferencing, you can use Exchange 2000 Conferencing Server. Exchange 2000 also allows you to set up online conferences by using standard meeting requirement forms in Microsoft Outlook. With Exchange 2000 Conferencing Server, you can set up conferences with any T.120 client by using MS NetMeeting on any platform including UNIX and Macintosh. The Web client that ships with Exchange 2000 Conferencing Server includes NetMeeting 3.01, which is a Web-based T.120 control. The Conference Management Service of Exchange 2000 allows you to control access to conferences. Additionally, Exchange 2000 provides services such as contact and task management.
TE
34
Exchange 2000 provides a single platform that you can use for e-mail, voice mail, fax, and page messages. Additionally, Exchange 2000 provides chat services based on the Internet Relay Chat (IRC) protocol for text-based chat. Users can also access e-mail and contacts remotely from the Internet. Organizations constantly need to share data in the form of files and applications. Exchange 2000 supports such data exchange and also allows you to conduct discussions through data conferencing. In an online business, it becomes imperative to allow remote access to information and data. Users can also access the data stored in Exchange 2000 from a Web browser. For interoperability sake, Exchange 2000 supports Internet standards, such as XML and HTTP. You can also create Web Forms in Exchange 2000. Additionally, Outlook Web Access forms an integral component of Exchange 2000. Outlook Web Access has been updated in scalability and functionality from its earlier version. For instance,
Team-Fly®
027-066.qxd 2/24/03 10:30 AM Page 35
THE .NET FAMILY
Chapter 2
Outlook Web Access in Exchange 2000 supports embedded messages and meeting requests. It also supports addition of audio and video clips to a message. Exchange 2000 also supports clustering. This allows high availability and scalability. The Enterprise Edition of Exchange 2000 supports multiple storage groups and databases. To ensure that a message reaches the intended destination despite malfunctioning mail server or network links, Exchange 2000 uses enhanced routing algorithms. Exchange 2000 also provides features to ensure secured communication. For instance, you can set permissions for items or documents and achieve new levels of security for the workflow applications.
Host Integration Server 2000 You can handle interoperability with non-Windows systems by using Host Integration Server 2000. This means that you can utilize existing AS/400 and mainframe systems data or applications by using Host Integration Server 2000 while retaining them in their original form. To achieve this, Host Integration Server 2000 allows you to develop applications that integrate host system to Internet or host system to intranet. Host Integration Server 2000 allows three-fold interoperability. It allows you to interact with host systems through data integration, network integration, and application integration. To access host resources, Host Integration Server 2000 offers MS ActiveXenabled, Web-deployable clients. Host Integration Server 2000 can support a maximum of 30,000 simultaneous client connections per server. In addition, the range of mainframe systems and AS-class host systems supported exceeds that of any other server. You can also access SQL Server, DB2, and flat-file data on mainframes, AS/400, UNIX, Windows 2000, and Windows NT Server systems. Further, to achieve enhanced interoperability, Host Integration Server 2000 allows you to integrate Microsoft Transaction Server and COM+ with IBM’s CICS or IMS transaction environments. To achieve network integration, Host Integration Server 2000 supports a multitude of protocols and network service types. Using Host Integration Server 2000, you can also use Windows 2000 features such as Microsoft Message Queue (MSMQ), Component Object Model (COM)+, and Application Center 2000 services.
35
027-066.qxd 2/24/03 10:30 AM Page 36
36
Part I
.NET FRAMEWORK OVERVIEW
Host Integration Server 2000 also makes it a simple task to log on to a host system. For instance, any user logging on to Windows NT is automatically authenticated for Windows NT and the host system log on simultaneously. To ensure authentication in the host system, the user ID and the password from Windows NT Server Directory Service are mapped to the host system’s user ID and password. Using Host Integration Server 2000 you can also reap the benefits of a comprehensive security system that incorporates the Windows 2000 Active Directory and Windows NT 4.0 domain security model as well as the host-based security. This security system ensures that all client-to-server and network-to-network virtual private network (VPN) connections are secure and tunneled by using Host Integration Server 2000. Host Integration Server 2000 offers an invaluable tool to integrate the best that Internet, intranet, and client/server technologies have to offer. As with other .NET Enterprise Servers, Host Integration Server 2000 also supports clustering and workload balancing. It is also possible to integrate host systems with .NET-based applications. For instance, you can integrate Host Integration Server 2000 with BizTalk and Commerce Server 2000.
ISA Server 2000 As more and more organizations turn to the Internet for business opportunities, there is an increasing need for fast and secure connections to the Internet. With this in mind, Microsoft developed the ISA Server 2000. ISA Server 2000 implements a Web cache to facilitate fast Internet access. Additionally, to secure the connection to the Internet without compromising the network performance, ISA Server 2000 implements a firewall. You can, therefore, use this server to enhance the Internet access and implement organizational security policies. ISA Server 2000 maintains a Web cache of all the frequently accessed Web objects, such as HTML pages, images, and files. This helps to improve the network performance by reducing the network traffic because the objects are not accessed from the Internet but are served from the ISA Server 2000 cache. This allows you to manage the Internet network traffic and reduces the time taken to access the Web. For fast Web access, ISA Server 2000 implements RAM caching and stores the cache contents in a location on the hard disk.
027-066.qxd 2/24/03 10:30 AM Page 37
THE .NET FAMILY
Chapter 2
It is also possible to scale the Web cache by adding additional ISA servers. Alternatively, you can increase the capacity of an ISA Server 2000 Web cache by adding multiple processors, implementing symmetric multiprocessing (SMP), increasing disk space, or increasing RAM. Additionally, ISA Server 2000 implements multiple caching technologies. These caching technologies are listed next.
Forward Caching In forward caching, clients from within the network of an organization access the servers on the Internet. The frequently accessed Web content is cached on the ISA Server.
Distributed Caching An ISA Server implements distributed caching when multiple ISA Server computers are used. In such a case, ISA Server uses Cache Array Routing Protocol (CARP) that creates a single logical cache by using ISA Server computers.
Hierarchical Caching In a hierarchy of interconnected ISA Server computers, you can ensure that users access caches that are located in geographic proximity. To do so, you can place ISA Server Web caches in a hierarchy depending on geographical location and link client nodes to the nearest leaf node of the hierarchy. Whenever the client makes a request for a resource, it goes to the nearest (leaf ) node and then travels up the hierarchy till the requested object is found.
Scheduled Caching You can update the ISA Web cache by scheduling the automatic update of the cache content. Such a caching mechanism is called scheduled caching.
Reverse Caching In reverse caching, an ISA server is placed as a layer over an organization’s Web server. In this case, all incoming requests from clients are catered to from the ISA cache. If the requested object is not available in the ISA cache, the request is forwarded to the underlying Web server that it sheaths. This secures the
37
027-066.qxd 2/24/03 10:30 AM Page 38
38
Part I
.NET FRAMEWORK OVERVIEW
communication between clients on the Internet and the publishing Web servers located within an organization. To ensure that the content in the Web cache is not accessed by unauthorized users, ISA Server implements a dedicated firewall. You can customize the firewall to meet the requirements of the organization. Most of the time, the client receives cached pages from the ISA Server and does not directly interact with the Web server, therefore ISA Server also provides end-to-end security by using Secure Sockets Layer (SSL) bridging. ISA Server also allows you to create policies or rules that restrict the entry of malicious content into a corporate network. In addition, you can also create rules governing the kind of traffic permitted for a particular component of a network, such as a user, a group, or an application. You can also create content and site rules that govern the content type and list of sites that can be accessed. To prevent unauthorized access, ISA Server examines all the incoming data and blocks all data packets that violate security rules. You can create protocol rules to govern which protocols can be used for incoming and outgoing communication. ISA Server allows you to maintain network security while publishing internal servers to the Internet. Later, you can specify rules to determine which requests should be sent to the server. In other words, ISA Server forms an intermediate protective layer between the Internet and the internal servers. ISA Server intercepts the traffic meant for the internal server. Therefore, all the client requests meant for the server are first received and filtered by the ISA Server. The ISA Server protects networks from external threats, infiltration, and unauthorized access. For instance, you can monitor the usage and access of resources on the network by using ISA Server. ISA Server also inspects the traffic at the packet, circuit, and application level. Another advantage is the extensibility factor of the ISA Server. You can integrate functionalities, such as virus scanning, blocking of Web sites, and filtering of content, with the ISA Server. This allows for customization of ISA Server to better suit the organizational requirements. Additionally, you can filter the content displayed by your site. Therefore, you can implement ISA Server to protect an internal Web server from any Internet attacks, such as malicious worms and hacking attempts. You can also inspect the incoming and outgoing network traffic. The ISA Server also provides features that you can use to monitor the security and the performance of the network. For instance, you can use graphical reports and alerts to view the performance- and security-related issues.
027-066.qxd 2/24/03 10:30 AM Page 39
THE .NET FAMILY
Chapter 2
Additionally, you can set bandwidth throttling based on users, groups, application, destination site, or content type. For example, you might want to give higher priority to e-mail downloads compared to evaluation software file downloads.
Mobile Information 2001 Server With the large-scale use of mobile devices and state-of-the-art innovations in mobile devices, there is a tendency and emphasis to access data and perform commercial transactions through mobile devices. Therefore, it has become the aim of any enterprise to remain connected while not being wired. To achieve this aim, Microsoft launched the Mobile Information 2001 Server. This server enables users to access data and content from the intranet of an organization around the clock by using wireless mobile devices, such as mobile phones and hand-held PCs with connectivity. In addition, the server allows mobile users to access their email, contacts, schedules, and line-of-business applications. Mobile Information 2001 Server includes the Microsoft Outlook Mobile Access application. You can use this application to extend the utility of Microsoft Outlook by allowing access to e-mail, calendar, contacts, and list of tasks from Microsoft Outlook. Mobile Information 2001 Server provides the capability to develop mobile applications by using standard Web and Wireless Application Protocol (WAP) applications authoring tools. The server also provides .NET Mobile Web SDK to design and render Web applications. You can also create applications with a common interface regardless of the mobile device used to access the application. This is possible because Mobile Information 2001 Server allows you to use mobile controls and Web Forms, which ensure that the content and interface that you create remain compatible with various mobile devices.
NOTE Web Forms are an ASP.NET technology that you use to create programmable Web pages.
With the mobile access to information arises the question of security and privacy of the data accessed. Mobile Information 2001 Server ensures end-to-end security of the information accessed and communications across mobile devices.
39
027-066.qxd 2/24/03 10:30 AM Page 40
40
Part I
.NET FRAMEWORK OVERVIEW
Mobile Information 2001 Server prevents unauthenticated access to information. To prevent unauthorized interception of data and communications, all notifications from enterprise applications are sent to mobile devices securely through technologies such as SSL, IP Security Protocol (IPSec), and VPN solutions. Additionally, the server application allows the use of the .NET Passport service, PKI, and smartcards. Mobile Information 2001 Server supports Web standards, such as HTTP, HTTP-Distributed Authoring and Versioning (DAV), Simple Mail Transfer Protocol (SMTP), and the like, to provide interoperability with mobile devices and integration with the existing applications and infrastructure. You can build connectors and services to make the existing applications accessible to mobile users, while retaining their existing functionality and interface. In addition, Mobile Information 2001 Server supports mobile devices with the WAP 1.1 browser. Mobile Information 2001 Server is also capable of sending notifications to mobile devices capable of receiving Short Message Service (SMS) or an SMTP addressable device, such as pagers. You can use Mobile Information 2001 Server to ensure accessibility of applications through other .NET Enterprise Servers, and the accessibility of content and information hosted by the intranet of an enterprise to mobile users. For instance, Mobile Information Server 2001 includes the Software Development Kit that allows you to extend BizTalk 2000 Server orchestration processes to mobile devices. To achieve mobile accessibility of content and information, Mobile Information 2001 Server performs clustering and load balancing. Already the beta version of the Mobile Information Server 2002 has been released. Mobile Information Server 2002 allows users to access mobile applications by using the latest mobile devices, such as mobile phones and Pocket PC 2002. For instance, users can access their Exchange inbox/mailbox from Pocket PC 2002. The Mobile Information Server 2002 Enterprise Edition includes certain new features. Some of these features are:
Microsoft Server ActiveSync The Microsoft Server ActiveSync feature has been added to synchronize information, such as e-mail and calendar, from Microsoft Exchange 2000 Server to a
027-066.qxd 2/24/03 10:30 AM Page 41
THE .NET FAMILY
Chapter 2
Pocket PC 2002-based device. This feature securely synchronizes the required information over a wireless link.
Enhanced Security The Mobile Information Server Enterprise Edition allows you to use either SSL or IPSec to secure the link between Mobile Information Server Enterprise Edition and Mobile Information Server Carrier Edition. In addition, all mobile phones that implement Microsoft Mobile Explorer 3.0 can connect to the enterprise network directly.
SharePoint Portal Server 2001 It is more often than not a tedious task to locate specific information in an organization. In such a case, a location where information can be readily accessed is a welcome respite. This can be achieved by using intranet portals. All frequently accessed information or other such information that would be required by people is hosted at intranet portals by organizations in a well-structured manner. In addition, with the built-in search feature of the site, users can locate specific content from the entire gamut of enterprise data. The search feature allows auto-categorization of the searched content. This allows users to restrict their search to a specific category of information. Users can also subscribe to the portals to receive notifications whenever the content on the site or the site as such is updated. The day is not far when all information will be located on intranet portals exclusively, altogether eliminating the need for separate storage for different kinds of content. SharePoint Portal Server 2001 also includes document management features, such as document locking and versioning. To ensure that the correct version of the document is published, there is a need to monitor the creation of the document and coordinate the work being done on the document by different users, maybe simultaneously. With each users contributing to the document in a specific way, it becomes essential to retain the latest changes to the document and prevent simultaneous access to the document. SharePoint Portal Server allows a user to address this by providing features, such as document locking and versioning. These features make it easier to control and track the document that passes through different phases in its lifecycle before it finally sees the light of day or is published. The approval routing feature allows you to track changes as a document passes through
41
027-066.qxd 2/24/03 10:30 AM Page 42
42
Part I
.NET FRAMEWORK OVERVIEW
different phases in its lifecycle. In order to further ease the life of the user, SharePoint Portal Server 2001 integrates these features with the applications that you use to create and manage documents, such as Microsoft Word. You can also allow only users with the appropriate access to view the documents. SharePoint Portal Server 2001 also provides the facility to store documents and keep track of the metadata related with business documents in Document Profile forms. Additionally, SharePoint Portal Server provides features that help you work with documents with ease, such as Document Collaboration, Profiling, and Lifecycle Management. To ensure interoperability, the server supports all Internet standards, such as XML and HTTP, and supports ActiveX Data Objects (ADO) and object linking and embedding database (OLE DB) for data access. Therefore, it becomes possible for you to integrate Active Server Pages (ASP) functionality into the Web portal. SharePoint Portal Server 2001 also consists of built-in services that you can use to create Web-based applications. It is possible to customize the server and its features such as its interface according to your organizational needs. It is also possible to add Web application functionalities such as ASP classic pages and ASP .NET Web Forms to SharePoint Portal Server 2001. For users to benefit from the features of SharePoint Portal Server 2001, a user interface needs to be created. To create a user interface for SharePoint Portal Server 2001, you use the Microsoft Digital Dashboard technology. Digital dashboards are Web applications that run on Windows 2000 IIS and can be accessed by using Web browsers such as Internet Explorer. Digital dashboards make extensive use of Web Part technology.
NOTE Each digital dashboard is composed of individual sections known as Web Parts. A Web Part is a customizable section that encapsulates a script fragment with a custom property schema that Microsoft defines. You can either use third-party Web Parts or create customized Web Parts by using HTML, XML, and JavaScript.
027-066.qxd 2/24/03 10:30 AM Page 43
THE .NET FAMILY
Chapter 2
SQL Server 2000 The need to store and maintain information in a systematic manner that can be queried with ease can never be overlooked by an organization. To meet this requirement, organizations can use SQL Server 2000. SQL Server 2000 is a server that allows you to create databases and analyze and query the data in these databases. Some of the features of SQL Server 2000 include: ◆ Comprehensive data store ◆ Enhanced analytical capabilities ◆ Full text search ◆ Indexed views ◆ Support for Web-enabled database applications ◆ Enhanced application development features ◆ Scalability
Comprehensive Data Store SQL Server 2000 allows you to create a comprehensive store of all the data from multiple sources, such as other relational database management system (RDBMS), flat files, and XML files, at a single location. You can create databases that can be accessed from the Internet and can serve content in XML format. This makes it possible to create client applications that access data from an SQL server across the Internet. SQL Server 2000 is fully integrated with the Web and allows you to access the data and query databases from the Web itself.
Enhanced Analytical Capabilities Functionalities that enhance the analytical features of SQL Server 2000, such as Analysis Services, data mining, and closed loop analysis, have also been added. The Analysis Services feature introduces data mining to locate information in online analytical processing (OLAP) cubes and relational databases. These features can help you to analyze and predict useful information by using the data stored in SQL Server 2000 databases.
43
027-066.qxd 2/24/03 10:30 AM Page 44
.NET FRAMEWORK OVERVIEW
SQL Server 2000 delivers an enhanced OLAP. With OLAP, it is possible to code for the dependency of subsequent steps in a business process based on the results of an analysis. You can also analyze the data by using the remote OLAP cubes that can be accessed from the Web.
Full Text Search You can use the full text search feature of SQL Server 2000 to query the data stored in SQL Server 2000 databases. It is also possible to perform full-text search on the documents in the database and query the database in English.
Indexed Views
AM FL Y
Part I
A new feature called indexed views, which allows you to create a unique clustered index on a view, is introduced in SQL Server 2000. Indexed views simplify data access resulting in application performance boost.
TE
44
Support for Web-Enabled Database Applications SQL Server 2000 supports XML data exchange with client applications and data access through ADO, OLE DB, and open database connectivity (ODBC). The server application provides a flexible platform for online transaction processing (OLTP) and e-commerce applications. Therefore, in SQL Server 2000, it is possible to create and maintain Web-enabled database applications.
Enhanced Application Development Features It is possible to ensure high availability of business applications by using the SQL Server 2000 features such as online backups, clustering, and log shipping. For a developer, SQL Server 2000 simplifies application development by allowing userdefined functions, cascading referential integrity, and integrated T-SQL debugger. You can also import data from heterogeneous systems such as flat files and legacy databases by using routines that can extract, transform, and load the data automatically. The most important feature provided by SQL Server 2000 is the Meta Data Services that allow you to store, view, and retrieve descriptions of objects in your applications and system.
Team-Fly®
027-066.qxd 2/24/03 10:30 AM Page 45
THE .NET FAMILY
Chapter 2
Scalability To meet the needs of an ever-expanding business environment, it is possible to scale SQL Server 2000 by adding multiple processors and additional RAM. You can also create clusters of SQL Server 2000 and distribute the database and data across servers. Additionally, you can interactively tune and debug queries, and quickly move and transform data to and from any source. The server application also supports replication of the data on multiple servers while synchronizing the content. With a view to provide access to the databases and applications to users on the move, the support for handheld devices such as Microsoft Windows CE handheld units has been built into SQL Server 2000. SQL Server 2000 allows you to use XML as a tool for integration of back-end systems and data transfer across firewalls. SQL Server 2000 also allows you to integrate with other .NET Enterprise Servers such as BizTalk Server and Commerce Server. The previous sections discussed the .NET Enterprise Servers that allow you to create and deploy solutions to use the .NET Framework. An additional set of Microsoft products designed as a foundation for the .NET platform is the Whistler group of products.
The Whistler Family The Whistler family of products incorporates enhancements to enable businesses to implement the .NET Framework with ease. For instance, the Whistler family of products supports real-time communications such as instant messaging and voice and video exchange. Additionally, a built-in support for enhanced Windows Media Services also enables these products to meet the .NET vision. The Whistler family of Microsoft products includes the Windows .NET Server family of server applications and client-side Windows XP. The next sections discuss the features of each of these products.
Windows .NET Server Family The Windows .NET Server family forms the foundation for the .NET framework and building solutions to .NET-enable businesses. The server family allows
45
027-066.qxd 2/24/03 10:30 AM Page 46
46
Part I
.NET FRAMEWORK OVERVIEW
you to create, deploy, and run XML Web services as well as other .NET solutions. To facilitate this, Windows .NET Server family supports all the XML Web services standards such as XML, SOAP, and Web Services Description Language (WSDL). The support for XML Web services allows integration and interoperability of applications across organizations breaking the network and platform barriers. To facilitate the access to applications and resources across networks and platforms, Windows .NET Server implements features such as Kerberos V5, Active Directory, .NET Passport services, and Microsoft Passport Trust Network. The Windows .NET Server also includes several other features, such as: ◆ Support for .NET technologies ◆ Improved security ◆ Enhanced caching ◆ Support for Windows Media Services
Support for .NET Technologies The Windows .NET Server family of products provides an integrated support for .NET technologies. To support .NET technologies, Windows .NET includes the following features: ◆ Integration with .NET Framework ◆ Integration of .NET Passport with Active Directory ◆ Support for SOAP-based XML message parsing in Microsoft Message Queuing (MSMQ) ◆ Integration of COM+ component architecture with XML Web services An integrated support for XML Web services also means that services such as COM+ and MSMQ can readily utilize XML Web services. COM+ applications can be called using XML or SOAP. It is also possible to send SOAP and XML in native format to make MSMQ interoperable with other applications that use SOAP. Windows .NET Server allows you to create Web services easily by using ASP.NET in which the content is not bound to the code. This allows you to deliver services via SOAP and other public protocols.
027-066.qxd 2/24/03 10:30 AM Page 47
THE .NET FAMILY
Chapter 2
Improved Security Windows .NET Server also implements Active Directory for ensuring security. For instance, you can bind multiple Lightweight Directory Access Protocol (LDAP) directories to authenticate users. The server family also allows you to create applications that extend the Active Directory schema while eliminating schema conflicts. Any authentication mechanism implemented at the front end is transitioned to Kerberos on the back end. The server also provides an integrated support for .NET Passport. This allows users’ to be validated and logged on when the Passport is implemented at the front-end server. Additionally, passport credentials can also be mapped to Active Directory. Windows .NET Server allows management of front-end servers, such as Web servers, as a trusted Key Distribution Center (KDC). The KDC authorizes and logs on users without credentials. You, as an administrator, can also configure these servers to delegate these tasks to the back-end servers that implement Kerberos. Additionally, the Windows .NET Server family can also be used to protect and extend the existing infrastructure while .NET-enabling it.
Enhanced Caching You can implement caching by using the ASP.NET programming model. The implementation of caching allows storage of completely rendered pages in an output cache and partial pages in a fragment cache. In addition, objects can be stored in the cache by applications, HTTP modules, and request handlers.
Support for Windows Media Services Windows Media Services enables real-time communications between employees, clients, and customers. Windows Media Services in Windows .NET Server supports streaming media and allows you to send live broadcasts to desktops within organizations. This feature also supports the delivery of digital media over the corporate intranet as well as the Internet. The entire communication and collaboration infrastructure is built on Session Initiation Protocol (SIP). SIP enables the creation and management of sessions, such as audio, video, instant messaging, and applications sharing. The Real Time Communications (RTC) SIP Proxy Server component can be used for securing Windows Messenger. This component can also be used to maintain the bandwidth across a network.
47
027-066.qxd 2/24/03 10:30 AM Page 48
48
Part I
.NET FRAMEWORK OVERVIEW
The Windows .NET Server family builds upon the existing Windows 2000 Server family. Most of the products in the Windows .NET Server family implement eight-node clusters. These clusters facilitate the addition and removal of hardware from a cluster dispersed across geographical boundaries. To further enhance scalability of Web services, Windows .NET Server implements ADO.NET. ADO.NET communicates messages in XML format between the data source and the Web application. To provide the previously mentioned features and to service businesses depending upon their requirements, the Windows .NET Server family comprises four products. ◆ Windows .NET Web Server is used to host Web sites and serve client requests for the sites. You can use Windows .NET Web Server to build and deploy XML Web services and applications by using ASP.NET. ◆ Windows .NET Standard Server is an enhanced version of Windows 2000 Server. Windows .NET Standard Server is an operating system that is used to deliver business solutions. The operating system is installed over an organizational network server to aid everyday activities such as file and printer sharing, providing secure Internet connectivity, and centralized desktop application deployment. The server supports two-way symmetric multiprocessing. ◆ Windows .NET Enterprise Server is an enhanced version of Windows Advanced Server. Windows .NET Enterprise Server includes the necessary features to enable e-commerce transactions and business-specific applications. ◆ Windows .NET Datacenter Server is used to implement scalable databases and large volumes of transaction processing. This server is used mostly for high-availability and high-scalability businesses. The server can also be used to develop solutions for databases, enterprise resource planning (ERP) software, real-time transaction processing, and server consolidation. To facilitate such solutions, the Windows .NET Datacenter Server provides eight-node clustering and load balancing services. You looked at the features and the products of the server component of the Whistler family. Windows XP comprises the client side for the Whistler family. The following section will discuss the features of Windows XP.
027-066.qxd 2/24/03 10:30 AM Page 49
THE .NET FAMILY
Chapter 2
49
Windows XP Windows XP is the client component of the Whistler family. Windows XP also supports XML Web services interoperability. Windows XP is available in two editions, Professional Edition and Home Edition. Both the editions include some common features, such as: ◆ Side-by-Side Component Sharing. Side-by-side component sharing allows you to install multiple versions of components simultaneously. Applications are bound to the specific versions of the compoMANIFEST nents with which they were creManifest is an XML file that contains ated. Typically, side-by-side description of an assembly or an applicacomponent sharing is useful in tion. Binding and activation metadata, isolated applications because it is such as COM classes, interfaces, and more reliable and not affected by type libraries, is stored in this manifest. A changes made by other applicamanifest file, along with its corresponding tions to components. The sidecomponent, is deployed in the application by-side component sharing mechanism uses a manifest file. ◆ Fast User Switching. Fast user switching allows multiple users to work on the same computer by implementing computer sharing functionality and multiple sessions. This is based on Windows 2000 Terminal Services. To enable fast user switching, users are always logged on and can switch between accounts. ◆ Support for .NET Alerts. The Windows Messenger 4.5, a component of Windows XP, provides numerous features that enhance communication. Some of these include the ability to send .NET Alerts and make phone calls from a computer. Users can send .NET Alerts, such as MSN Calendar alert for scheduling and MSN CarPoint alert for traffic. Windows Messenger can also be used to provide voice conversations, video conferences, data collaboration sessions, and file sharing. ◆ Support for .NET Passport. Windows XP implements .NET Passport authentication for single sign-in authentication by using a standard application program interface (API). This means that users can sign in to .NET Passport from Windows XP. Optionally, users can choose to store
027-066.qxd 2/24/03 10:30 AM Page 50
50
Part I
.NET FRAMEWORK OVERVIEW
their credentials in the Windows XP Credential Manager thereby eliminating the need to re-enter the credentials for every Web site registered with .NET Passport. To make the sign in even simpler, Windows XP allows users to create a .NET Passport by using the .NET Passport Wizard. You just looked at the implementation of .NET Passport by Windows XP. Now you’ll look at the .NET Passport service.
.NET Passport Service How many times have you ended up typing an incorrect password or forgetting the password because there are so many log on and password pairs to remember? Fret not. Microsoft provides a solution to such problems with the .NET Passport service. .NET Passport is an Internet-based authentication service that allows users to sign in to multiple participating Web sites by using a single e-mail address and password. This means that Web sites need not maintain separate authentication mechanisms. In addition, .NET Passport eliminates the need to type personal information repeatedly for each site visited during a Web browsing session. This makes the entire process of personalization of Web sites based on user profiles a simple and fast task. Users can also PARTICIPATING WEB SITE store credit card information in .NET Passport. Therefore, not only is the time taken A participating Web site is a site that has for online transactions reduced, but the registered with .NET Passport. entire process is also simplified. For a user to benefit from .NET Passport, the user needs to create a .NET Passport account. A .NET Passport account is created when a user registers for .NET Passport. A user can choose to register for .NET Passport by using any of the following methods: ◆ Signing up for an e-mail account on www.Hotmail.com or www.MSN.com ◆ Registering at the .NET Passport site, www.passport.com ◆ Registering at a participating Web site such as www.McAfee.com ◆ Using Windows XP Registration Wizard
027-066.qxd 2/24/03 10:30 AM Page 51
THE .NET FAMILY
Chapter 2
A user having an e-mail account on www.Hotmail.com or www.MSN.com is automatically registered as a .NET Passport user. For such a user, the .NET Passport account is created automatically. While the home page of .NET Passport allows you to register directly by using the .NET Passport registration page, a participating Web site will redirect all potential .NET Passport users to a .NET Passport registration page. Figure 2-1 displays the .NET Passport registration page. Additionally, while the home page of a .NET Passport site only requires the e-mail address and password to create a .NET Passport account, a participating site might require additional information. For instance, a participating site might require the user’s address. Such additional information is stored in the user’s .NET Passport account, if indicated by the site by the presence of an icon.
FIGURE 2-1 .NET Passport registration page
51
027-066.qxd 2/24/03 10:30 AM Page 52
52
Part I
.NET FRAMEWORK OVERVIEW
While creating a .NET Passport account, users can specify the information that can be shared with the participating sites during a Web browsing session. For instance, users can specify whether a participating Web site has access to their e-mail address or first and last names only. Optionally, users can share all the remaining information besides the e-mail address and first and last names. Therefore, in .NET Passport service, users exercise complete control over their information. Regardless of the information that a user has shared while registering for .NET Passport, all participating sites besides the site used for registration receive the information that the user has chosen to share. In any case, the password of a user is never communicated to a participating Web site. A .NET Passport account created for a user stores credentials pertaining to the user. These credentials are unique and are used to validate the user whenever the user visits a participating Web site. A .NET Passport account consists of the following information: ◆ .NET Passport Unique Identifier (PUID). PUID is a 64-bit numeric value that is assigned by .NET Passport. ◆ .NET Passport User Profile. .NET Passport User Profile stores all the information specified while registering for .NET Passport, such as first name, last name, e-mail address, phone number, city, state, and postal code. ◆ .NET Passport Credential. This component of the .NET Passport account consists of two components, Standard .NET Passport Credential and Security key. Standard .NET Passport Credential stores the basic inputs that are required to create a .NET Passport account. These inputs are the e-mail address or phone number of the user along with a password or PIN. Security key is a four-digit key that is required to sign in to the strong credential security level. While creating the key, the user selects three questions and specifies the answers for these questions. These questions help the user to restore the key in case the server disables the account as a precautionary measure. You will learn about the strong credential security level later in this chapter. ◆ .NET Passport wallet. A user can create .NET Passport wallet to store credit card information and billing and shipping addresses while registering from the .NET Passport site or accessing the Member services page.
027-066.qxd 2/24/03 10:30 AM Page 53
THE .NET FAMILY
Chapter 2
After a .NET Passport account has been created for a user, the user can implement the services offered by .NET Passport. .NET Passport provides a set of services to implement user authenticity, security, and privacy. The .NET Passport services are: ◆ .NET Passport Single Sign-In (SSI) ◆ .NET Passport Express Purchase ◆ Kids .NET Passport Each of these services enhances the Web experience for users in its own way. The following sections look at each of the .NET Passport services in detail.
.NET Passport Single Sign-In The .NET Passport SSI service enables users to use a single .NET Passport account across Web sites. Therefore, during a single Web browsing session, a user can navigate across participating sites by supplying his or her sign-in name and password once. This eliminates the need to authenticate the user at all the sites visited by the user. .NET Passport prevents unauthorized access to Web sites and the services offered by the sites by using powerful Internet security technologies. Some of the security-based implementations in .NET Passport are: ◆ Use of standard Web technologies and techniques such as SSL, HTTP redirects, cookies, and JavaScript. ◆ Non-sharing of the password used by users to sign-in to .NET Passport. ◆ Encryption of all authentication- and profile-related information when sent to a participating site. ◆ User control on information to be shared between participating sites. ◆ Implementation of security levels. From among the aforementioned methods, the security levels can be implemented at three different types depending on the sensitivity of the content or the service offered by the site. The three security levels of authentication provided by .NET Passport are: ◆ Standard Sign-In. Participating Web sites implement the standard signin if the content or service offered by the sites is not sensitive enough to merit high security.
53
027-066.qxd 2/24/03 10:30 AM Page 54
Part I
.NET FRAMEWORK OVERVIEW ◆ Secure Channel Sign-In. The secure channel sign-in shares most features of standard sign-in. The essential difference lies in the implementation of an end-to-end secure channel for authentication. In this security level, the .NET Passport ticket is written in a secure format to avoid any manipulation. Even the .NET Passport sign-in page is displayed using SSL with up to 128-bit encryption level.
AM FL Y
◆ Strong Credential Sign-In. Strong credential sign-in is designed to ensure security and privacy for the most sensitive data. This level involves a two-stage sign-in. While the first stage is similar to the secure channel sign-in, the second stage requires the user to enter a four-digit security key on a sign-in page. To ensure end-to-end security, the second sign-in page is displayed using SSL. Further, the key is disabled after five consecutive unsuccessful attempts to type the correct key. To enable the key, the user needs to reset the security key to regain access to the .NET Passport account. This key resetting process requires the user to answer three secret questions that the user decided while selecting the secret key.
TE
54
.NET Passport Express Purchase The information stored in the .NET Passport wallet is used when the user makes use of the .NET Passport express purchase service. To implement this service, participating sites need to accept labels for e-commerce POST data complying with Electronic Commerce Modeling Language (ECML). Additionally, the site needs to add the .NET Passport express purchase link or button. This button is used ECML to redirect a .NET Passport user to the ECML is an XML-based standard that respective .NET Passport wallet. This initiallows the automation of information ates a .NET Passport express purchase. exchange between users and merchants through digital wallets.
When a user initiates a .NET Passport express purchase, the following sequence of activities occurs:
◆ Site ID of the participating site is authenticated by the .NET Passport wallet server. ◆ A user already signed in to .NET Passport is required to enter his or her password. Users who have not signed in are required to sign in to .NET Passport.
Team-Fly®
027-066.qxd 2/24/03 10:30 AM Page 55
THE .NET FAMILY
Chapter 2
55
◆ The user selects the credit card and the billing and shipping addresses from his or her .NET Passport wallet. ◆ Credit details, card number, and the billing and shipping addresses are encrypted using an encryption key and sent back to the participating site. ◆ The participating site decrypts the information by using the .NET Passport Manager. Similarly, with a special emphasis on the online security and privacy of children, .NET Passport provides the Kids .NET Passport service.
SITE ID
AND
ENCRYPTION KEY
When a site registers as a .NET Passport participating site, .NET Passport grants a unique ID and encryption key to the site. The ID granted to the site is known as Site ID. Site ID is used to authenticate the site whenever it redirects a user to .NET Passport Login server. The encryption key is used to retrieve the user-related information sent by the .NET Passport Login server.
Kids .NET Passport Kids .NET Passport service is implemented by using .NET Passport SSI. The service essentially requires all registered participating sites to comply with Children’s Online Privacy Protection Act (COPPA). The Kids .NET Passport service allows parents or guardians of children less than 13 years of age to control the information and its subsequent use by Web sites. To use the service, the .NET Passport users register their children to create Kids .NET Passport accounts. When a child COPPA signs in to a participating site, .NET Passport follows a two-stage authenticaCOPPA is an Internet law that seeks to tion process. In the first stage, .NET ensure the online privacy of children. The Passport verifies the child’s date of birth law ensures that the collection, use, and by using the profile information. In the disclosure of all the personal information related to children by online services and second stage, if the child is younger than Web sites are done following parental 13, the Kids .NET Passport account is consent. checked to determine whether a consent level has been granted to the site for the child. The Kids .NET Passport account is used to store information such as name, date of birth, and e-mail address. In addition, the account stores information
027-066.qxd 2/24/03 10:30 AM Page 56
56
Part I
.NET FRAMEWORK OVERVIEW
about the sites that can be accessed by children and the associated level of consent for the site. Kids .NET Passport allows parents and guardians to specify three levels of consent for each participating sites. Based on the level of the consent, the collection and use of personal information related to children is restricted. The consent levels that a parent or guardian can grant to a site are: ◆ Deny. The Deny consent level is used to prevent a site from collecting any information from the child. Additionally, this consent might also disable the use of the services offered by the sites or the sites themselves. ◆ Limited. The Limited consent level allows participating sites to only collect, store, and use the information collected from the child. This consent level does not allow the disclosure of the information to any third party except if necessary for the working of the site or services. ◆ Full. The use of the Full consent level allows a site or service to collect, store, and use the information collected from children. In addition, this consent level allows the disclosure of this information to a third party. To use either of the .NET Passport services mentioned earlier, a user needs to sign in to a .NET Passport participating site. A .NET PASSPORT MANAGER user can sign in to a .NET Passport participating site by clicking on the .NET PassTo implement .NET Passport SSI and Kids port sign-in link located on the site. When .NET Passport services, each participating site needs to install .NET Passport a user clicks on the sign-in link, the site Manager. .NET Passport Manager is a redirects the user to .NET Passport Login COM object located on the server side server. that manages the authentication and profile information of the users as the users navigate from or within a participating Web site.
One reason why .NET Passport Manager is a COM object is that not every participating site would be required to have .NET Framework components. Besides, the .NET Passport service can easily interoperate with COM components.
While redirecting the user to .NET Passport Login server, the site sends its Site ID. The .NET Passport Login server verifies the site from the list of registered participating Web sites by using the Site ID. Figure 2-2 illustrates this stage of the .NET Password authentication process.
027-066.qxd 2/24/03 10:30 AM Page 57
THE .NET FAMILY
If a matching entry is found, the .NET Passport Login server displays a sign-in page. The participating site can either cobrand the .NET Passport sign-in page or embed a small sign-in module within a page. The user enters .NET Passport credentials on the page. These credentials are then authenticated by the .NET Passport Login server by using the .NET Passport database. The .NET Passport database stores the credentials and authenticationand profile-related information, such as the PUID, for all the users who have registered for .NET Passport. On locating a matching record in the database, the .NET Passport Login server retrieves the .NET PUID and the sharable user profile information for the respective user from the database. This
Chapter 2
57
SIGNING ON TO .NET PASSPORT PARTICIPATING SITES When a user authenticated by .NET Passport visits a site where the user has not signed in, the user needs to click on the .NET Passport sign-in link. The participating site initiates the .NET Passport authentication process. Henceforth, the user can visit any other participating site by simply clicking on the sign-in link on the site. Some users owning a private computer might prefer to be signed in automatically to .NET Passport. To facilitate this, users can store their .NET Passport sign-in name and password on their computer. This option enables users to remain signed in to .NET Passport at all times on the computer where the .NET Passport credentials are stored. However, users with access to a public computer only may choose not to do so.
FIGURE 2-2 Stage 1 of .NET Password authentication process
027-066.qxd 2/24/03 10:30 AM Page 58
58
Part I
.NET FRAMEWORK OVERVIEW
entire process is known as the .NET Passport authentication process. Figure 2-3 illustrates this stage of .NET Password authentication process. Using the information retrieved from the database, the .NET Passport Login server creates three .NET Passport cookies, namely: ◆ Ticket cookie ◆ Profile cookie ◆ Visited sites cookie The ticket cookie stores the PUID and the time stamp when the user was authenticated. All the information related to the user profile is stored in the profile cookie. In addition, the visited sites cookie is constantly updated with the names of the sites to which a user signs in. Next, the data stored in the ticket and profile cookies is encrypted by the .NET Passport Login server and sent to the user’s browser. From the browser, the information is forwarded to the respective participating site. The participating site sends this information to .NET Passport Manager. At .NET Passport Manager, the information is decrypted to obtain the user’s PUID and the profile information. .NET Passport Manager uses the profile information to personalize the content on the Web site based on the user preferences. Figure 2-4 illustrates this stage of the .NET Password authentication process.
FIGURE 2-3 Stage 2 of .NET Password authentication process
027-066.qxd 2/24/03 10:30 AM Page 59
THE .NET FAMILY
Chapter 2
59
FIGURE 2-4 Stage 3 of .NET Password authentication process
The user can now navigate within the site or to other participating sites. However, when the time specified in the ticket cookie expires, the user is unable to access the participating site. In this case, USE OF INFORMATION RELATED TO A to resume access to the site, the user needs .NET PASSPORT USER to sign in to the participating site again. To sign in to the site, the user is required The use of information related to a .NET Passport user is bound by the privacy polto re-enter the password. Failure to do so icy of the site. The participating site can denies .NET Passport services to the user. also store the PUID and the profile inforAdditionally, if a user types an incorrect mation of a user in its own database. In password several times, .NET Passport addition, the information can also be writblocks access to the .NET Passport ten by the site to cookies and stored on account. the user’s computer. To sign out from .NET Passport, the user needs to click on the sign-out link placed on the participating Web site. The participating site replaces the sign-in link with a sign-out link after a user has been authenticated. When a user clicks on the .NET Passport sign-out link, the .NET Passport server ensures that each participating site visited by the user during the browsing session deletes the cookies
027-066.qxd 2/24/03 10:30 AM Page 60
60
Part I
.NET FRAMEWORK OVERVIEW
placed on the user’s computer during sign-in. As such, the cookies placed on the user’s computer are deleted when the user ends a Web browsing session. However, this is not the case when the user signs in automatically to .NET Passport. The cookies can also be set for expiration by .NET Passport or the participating site. With the widespread and ever-increasing dependability on wireless devices, .NET Passport has been enhanced for use on wireless cell phones and pocket PC devices. However, not all the features related to .NET Passport are supported on mobile devices. For instance, features such as strong credential sign-in and online sign-in are not supported on mobile devices because, currently, the processing and network capabilities of such devices create a bottleneck. So far you have looked at the .NET Passport service and its benefits. You will now look at Visual Studio.NET, the integrated environment for creating applications by using .NET languages.
Visual Studio .NET Visual Studio.NET provides an integrated development environment that allows you to create solutions for the .NET Framework. Visual Studio.NET integrates the best of programming languages in a single interface that you can use to develop enterprise-scale Web applications and high-performance desktop applications. Visual Studio.NET allows you to create a myriad of applications. Some of the applications commonly developed using Visual Studio.NET are: ◆ Console applications ◆ Windows applications ◆ ASP.NET applications ◆ Web services You can create Web services and applications by using the languages offered by Visual Studio.NET. Visual Studio.NET provides the following programming languages: ◆ Visual Basic.NET ◆ Visual C#
027-066.qxd 2/24/03 10:30 AM Page 61
THE .NET FAMILY
Chapter 2
◆ Visual Foxpro ◆ Visual C++.NET With so many languages to choose from, you might be wondering which language to use for developing applications in Visual Studio.NET. You can use any language from the suite of languages made available by Visual Studio.NET. It is likely that familiarity with a previous version of the language will guide the selection of the language. Apart from the incorporated feature of the programming languages, Visual Studio.NET includes certain enhanced features of its own. Some of these features are: ◆ Implementation of Web Forms ◆ Implementation of Web services ◆ Implementation of Windows Forms ◆ Implementation of project-independent object model ◆ Enhanced debugging ◆ Support for ASP.NET programming ◆ Enhanced integrated development environment (IDE) The subsequent sections in the chapter will elaborate each of these features.
Implementation of Web Forms Visual Studio.NET provides Web Forms to enable you to create Web applications. The applications created using Web Forms can be implemented on any browser or mobile device. To ensure compliance across devices, Web Forms implement controls that render HTML compliant to the specific browser. Web Forms are implemented as classes that are compiled into the Dynamic Link Library (DLL), thereby ensuring server-side code security.
Implementation of Web Services Another important feature of Visual Studio.NET is the creation, deployment, and debugging of Web services. The support for Internet standards such as HTTP and XML allows use of Web services across platforms.
61
027-066.qxd 2/24/03 10:30 AM Page 62
62
Part I
.NET FRAMEWORK OVERVIEW
Implementation of Windows Forms Visual Studio.NET supports Windows Forms that you can use to create Windows applications for the .NET Framework. Windows Forms are object-oriented and consist of an extensible set of classes. You can implement Windows Forms and Windows Forms controls to create the presentation tier.
Implementation of Project-Independent Object Model Visual Studio.NET as a rapid application development (RAD) tool has various ways to represent IDE tools, the components of a solution, and the information exchange with the developer. Visual Studio.NET implements a project-independent object model to access the components and events of the Visual Studio.NET IDE. This model includes components that represent solutions, projects, tools, code editors, debuggers, code objects, documents, and events. You can use this model through macros, add-ins, wizards, and the Visual Studio.NET Integration Program (VSIP). VSIP is a program that can be used to extend the Visual Studio.NET IDE. This program provides you with additional objects and interfaces to create customized tools, file types, and designers.
Enhanced Debugging Visual Studio.NET provides an integrated debugger that can be used to debug solutions written in different languages. In addition, you can associate the debugger to a currently executing program. This allows you to debug multiple programs simultaneously. You can also debug multithreaded programs or a program executing on a remote computer.
Support for ASP.NET Programming An important feature of Visual Studio.NET is support for ASP.NET programming. This tool incorporates technologies, such as ASP.NET, that simplify the design, development, and deployment of business solutions. You can create Web applications by using Visual Studio.NET. You can also use the Visual Studio.NET tools such as Visual designer for Web pages and code-aware text editors for writing code.
027-066.qxd 2/24/03 10:30 AM Page 63
THE .NET FAMILY
Chapter 2
Enhanced IDE The Visual Studio.NET IDE extends across the programming languages supported by Visual Studio.NET. You can even create customized tools to enhance the capabilities of Visual Studio by creating macros and using the customization features of the IDE. Visual Studio now also allows you to simultaneously debug and troubleshoot a Web application such as an ASP .NET page, along with its corresponding DLLs. Now you will familiarize yourself with the main features of the IDE. However, before proceeding, you will spend a little time familiarizing yourself with the interface that is displayed when you start Visual Studio.NET. This interface is known as the Start Page. Figure 2-5 displays the Start Page of Visual Studio.NET. The Start Page is the default page that allows you to perform tasks such as searching for information and specifying preferences such as the keyboard scheme, window layout, and help filter. The Start Page also allows you to create a new project or open an existing project.
FIGURE 2-5 Start Page of Visual Studio.NET
63
027-066.qxd 2/24/03 10:30 AM Page 64
.NET FRAMEWORK OVERVIEW
The projects created using Visual Studio.NET are stored in containers for easy manageability and accessibility. Containers are used to store components of applications, such as files and folders. Visual Studio.NET provides two types of containers. These are: ◆ Project. A project consists of all the interrelated components of an application. ◆ Solution. A solution consists of one or more related projects. A solution container can be used to store projects. You can also implement solutions to apply specific settings and options to multiple projects. To create a project, you can select the New Project button on the Start Page.
AM FL Y
Part I
When you begin creating a Windows Application project from the Start Page, the following components are displayed. Figure 2-6 displays the components of Visual Studio.NET IDE.
TE
64
FIGURE 2-6 Components of Visual Studio.NET IDE
Team-Fly®
027-066.qxd 2/24/03 10:30 AM Page 65
THE .NET FAMILY
Chapter 2
◆ Windows Forms Designer. You use the Windows Forms Designer to design the user interface for the application. ◆ Solution Explorer. Solution Explorer provides a hierarchical view of application-related information, such as project name, solution name, references, and the various files that are a part of the solution. ◆ Properties window. You use the Properties window to view the characteristics associated with an object, such as a text box control on a form. ◆ Toolbox. Toolbox includes multiple tabs. Each tab has a list of items providing functionalities to aid the creation of applications. ◆ Output window. You use Output window to view the status of the activities performed by Visual Studio.NET, such as updating references and building satellite assemblies. ◆ Task List. You use the Task List to identify the errors detected while applying enterprise template policies, editing code, or compiling code. Other features include user notes for the solution. ◆ Server Explorer. You use the Server Explorer to view information related to the servers available on the network. In addition, Server Explorer allows you to perform administrative tasks. ◆ Dynamic Help window. You use the Dynamic Help window to view a context-specific list of help topics. ◆ Component tray. You use the Component tray to view the invisible controls, such as OleDbDataAdapter, in an application and modify these while creating the application. ◆ Class View window. You use the Class View window to view the classes, methods, and properties associated with a solution. ◆ Code and Text Editor. Code and Text Editor provides you with word processing capabilities that facilitate you to enter and edit code and text.
Summary In this chapter, you learned that .NET Enterprise Servers allow companies to create scalable business infrastructures that can be implemented with ease and reliability. To facilitate this, the servers have been built using open Web standards such as XML and ensure interoperability with the existing infrastructure. Each of the .NET Enterprise Servers plays an important role in the .NET Framework.
65
027-066.qxd 2/24/03 10:30 AM Page 66
66
Part I
.NET FRAMEWORK OVERVIEW
You also learned that the Whistler family of Microsoft products enables businesses to implement the .NET Framework with ease. The Whistler family comprises the Windows .NET Server family and Windows XP. Windows XP implements .NET Passport, which is an Internet-based authentication method that allows users to sign in to multiple participating Web sites by using a single email address and password. Additionally, .NET Passport provides a set of services. These services are: ◆ .NET Passport SSI ◆ .NET Passport Express Purchase ◆ Kids .NET Passport The .NET Passport SSI service enables users to use a single .NET Passport account across Web sites. The .NET Passport express purchase service allows users to performs online transactions. Whereas, the Kids .NET Passport service has been created to ensure privacy and security of personal data related to children. Finally, you learned that Visual Studio.NET is an application development tool based on the .NET Framework. Visual Studio.NET provides a myriad of programming languages that you can use to create Web services and applications. Some of the languages included in Visual Studio.NET are Visual Basic.NET, Visual C#, and Visual C++.NET.
067-090.qxd 2/24/03 10:31 AM Page 67
Chapter 3 Introduction to the .NET Framework
067-090.qxd 2/24/03 10:31 AM Page 68
n this world of online computing, people using a variety of devices, such as PCs, laptops, and cellular phones, connect through the Web. The diversity that exists on the Web in terms of hardware and software makes it necessary to develop applications that work on multiple platforms. There arises a need to develop applications for the distributed Web environment. Web services are distributed applications that provide the functionality of accessing the code from different platforms. These services include reusable software components that can be used by applications across platforms.
I
The .NET Framework provides a computing platform for developing, deploying, and executing Web services. It provides a collection of supporting classes to create and use Web services applications. In this chapter, you will look at the architecture of the .NET Framework. You will also look at the language enhancements in Visual Basic.NET, Visual C++.NET, and C# as they form a part of .NET suite of languages. This chapter also provides an overview of Visual Studio.NET.
.NET Framework You can create and deploy distributed applications using the .NET Framework. It provides an environment that supports different platforms and languages. It minimizes software deployment and version-related conflicts. Some of features of the .NET Framework are: ◆ Multi-language support. The .NET Framework supports multiple languages. This allows you to write code using the language of your choice. ◆ Code reusability. Using the .NET Framework, you can create your own classes that can be accessed by third-party applications. This makes it extremely simple to reuse code and market products for vendors. ◆ Automatic resource management. The .NET Framework automatically manages resources, such as files, memory, network connections, and database resources. The common language runtime (CLR) component of .NET Framework makes automatic resource management possible.
067-090.qxd 2/24/03 10:31 AM Page 69
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
◆ XML Web services. These services allow you to access code through the Web by using any device. Using the .NET Framework, you can easily transform a standard application into an XML Web service. ◆ ADO.NET. This is a new technology included in the .NET Framework. This technology based on XML is used to access data on the Web. ◆ ASP.NET. This is the development platform provided by the .NET Framework for building server-based Web applications. ASP.NET supports advanced compilation and caching features that help improve the performance of ASP applications. ASP.NET also monitors the applications running currently and restarts them at defined intervals. ◆ SOAP. It is a simple, XML-based protocol supported by the .NET Framework that is used for exchanging structured and type information on the Web. SOAP forms the standard protocol for all communication between processes. ◆ Cross-language integration. .NET Framework allows code written in different languages to be integrated with one another.
Architecture The .NET Framework includes the necessary classes, namespaces, and assemblies to create Web services. The .NET Framework includes two components. These components are: ◆ CLR ◆ .NET Framework class library One of the components of the .NET Framework, CLR, is the runtime engine provided by the .NET Framework. It manages the execution of code and provides services that simplify the development of applications. It provides an infrastructure to execute applications and allows them to interact with other parts of the .NET Framework. The runtime provides services, such as cross-language integration, code access security, object lifetime management, and debugging and profiling support. In the subsequent sections, I’ll discuss the CLR component of the .NET Framework in detail.
69
067-090.qxd 2/24/03 10:31 AM Page 70
70
Part I
.NET FRAMEWORK OVERVIEW
CLR As I’ve already mentioned, CLR is the runtime environment provided by the .NET Framework, which manages the execution of code. CLR provides built-in support for language interoperability. It allows applications developed using different languages to integrate and interoperate. CLR also ensures memory and thread management and the security of the executing code. It also provides features that reduce the time taken to code an application. For example, it provides features such as lifetime management, strong type naming, cross-language exception handling, and dynamic binding.
NOTE
Some of the features provided by CLR are described in the following list. ◆ Language integration. The CLR component of the .NET Framework allows languages to be integrated with one another. For example, it is possible to create a class in C++ that derives from a class created in Visual Basic. The .NET Framework can enable this because it defines a type system common to all .NET languages. The Microsoft Common Language Specification (discussed later) describes the rules that compiler vendors must follow in order for their languages to integrate with other languages. ◆ Code reusability. CLR also supports code reusability. You can create your own components that can be accessed by third-party applications. ◆ Automatic resource management. CLR is responsible for automatic resource management in the .NET Framework. It manages resources, such as files, memory, and database resources, by automatically tracking resource usage and eliminating resource leaks. This avoids the most common application bugs. ◆ Type safety. The .NET CLR ensures type safety of your code. Type safety implies that allocated objects are always accessed in compatible ways. For example, if an input parameter is declared to accept a 4-byte value, CLR will detect and discard attempts to access the parameter as an 8-byte value. Type safety also ensures that the execution of code flows
067-090.qxd 2/24/03 10:31 AM Page 71
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
through known locations. In other words, it is not possible to create an arbitrary reference to a memory location and cause code at that location to begin execution. Together, these eliminate common programming errors. ◆ Rich debugging support. Since CLR supports multiple languages, you can create your applications with code written in a language of your choice. The .NET CLR supports debugging applications that support cross-language interoperability and integration. The runtime also provides features to easily locate bugs in the applications. ◆ Consistent error handling. In the .NET Framework, all errors are reported through exceptions. This ensures a consistent way of error reporting. Exceptions allow the developer to isolate the error-handling code from the rest of the application code. This simplifies writing, reading, and maintaining of code. ◆ Easy deployment of applications. The .NET Framework has simplified the process of installing, displaying, and uninstalling applications. Since .NET components do not have a reference in the system registry, installing most .NET-based applications requires no more than copying the files to a directory, and uninstalling an application is as easy as deleting those files. To understand CLR better, you should know the important concepts in CLR that include: ◆ CLS (Common Language Specification) ◆ CTS (Common Type System) ◆ Garbage Collection ◆ MSIL (Microsoft Intermediate Language), JIT (Just In Time), and Metadata I’ll now discuss each of these concepts of CLR.
CLS As discussed earlier, CLR enables language interoperability among applications. However, this feature of CLR does not ensure that developers using a programming language can use code you write in a different programming language. To solve this issue, CLS has been defined. CLS provides a set of language features
71
067-090.qxd 2/24/03 10:31 AM Page 72
72
Part I
.NET FRAMEWORK OVERVIEW
and rules that allow you to develop managed code that can be used by developers using different programming languages.
NOTE Managed code is code written to use the services of the runtime, such as memory management, cross-language integration, code access security, and automatic lifetime control of objects. Managed code must supply a minimum level of information called metadata to the runtime in order to use runtime’s services. You develop man-
CLS includes basic language features needed by almost all the applications. CLS helps enhance and ensure language interoperability by defining a set of features that are available in a variety of languages. CLS also establishes requirements for CLS compliance, which help you determine whether your managed code conforms to CLS. If your component uses only CLS features in code that it exposes to other components, your component is ensured to be accessible from any programming language that supports CLS. Components that adhere to CLS rules and use only the features included in the CLS are said to be CLS-compliant components.
CTS CTS is a type system implemented by CLR. It supports the types or object classes and operations used in most programming languages. CTS defines how types are declared, used, and managed in the runtime. It provides a framework to enable cross-language integration of applications, type safety, and high performance code execution. It supports implementation of multiple programming languages. It defines rules that a programming language must follow to ensure that objects written in different programming languages can interact with each other.
NOTE CLS forms a subset of CTS. This implies that all the rules that apply to CTS apply to CLS also.
067-090.qxd 2/24/03 10:31 AM Page 73
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
CTS allows a class type to contain zero or more members. The possible members in a class type are: ◆ Field. It is a data variable and is part of the object’s state. A field is identified by its name and type supported by the runtime. ◆ Method. It is a function that performs an operation on the object. A method isidentified by its name, signature, and modifier. The signature specifies the number, sequence, and types of parameters, and the type of value returned by the method. A modifier defines custom attributes of the method. For example, a modifier can be public, private, and static. ◆ Property. A property names a value or state of the type and defines methods for getting or setting the property’s value. A property behaves as a field for the class users but is implemented as a method in the class. Properties can also be used to create read-only or write-only fields. ◆ Event. An event is a notification mechanism between an object and other objects of a class. For example, a key press can be an event that an object uses to notify other objects to perform a certain operation. CTS defines certain rules for type visibility, access to the members of a type, type inheritance, virtual functions, object lifetime, and so on. While writing code by using CTS, it is important to consider the language and behavior as two different aspects. For example, you can use either Visual C++ or C++ to define your classes and members. Here, the syntax of code written will differ for the two languages. However, the behavior of the class will be identical. This is because the behavior of the class object is defined by CTS. One of the CTS rules states that all the class types that follow CTS must inherit from a predefined class type System.Object. Object is the name of a type defined in the System namespace. The object type is the root of all other class types, which ensures that every class type has a minimum predefined set of behaviors. You can compare two objects for equality and uniquely identify an object through a hash code by using System.Object. You can also get information about an object’s class type, perform a bitwise copy of an object, and obtain a string representation of the object’s current state by using System.Object.
73
067-090.qxd 2/24/03 10:31 AM Page 74
.NET FRAMEWORK OVERVIEW
Garbage Collection Garbage collection is a mechanism that allows the computer to detect an object that is no longer in use, and then release the memory used by that object. One of the advantages of CLR is automatic memory management that uses the garbage collection mechanism. CLR automatically releases objects when they are no longer accessed. This feature of CLR eliminates memory leaks and invalid memory references. The CLR’s garbage collector (GC) manages the allocation and release of memory for an application. This means that you do not have to write code to perform memory management tasks when you develop managed applications. Automatic memory management can eliminate common problems, such as forgetting to explicitly release an object and causing a memory leak, or attempting to access memory for an object that has already been released.
AM FL Y
Part I
You will now see how the GC works.
When you initialize a new process, the runtime allocates a contiguous region of address space for the process. This allocated address space is known as the managed heap. The managed heap maintains a pointer to the address of the next object in the heap. Initially, this pointer is set to the managed heap’s base address. When an application creates the first object, the GC allocates memory for it at the base address of the managed heap. When the application creates the next object, the GC allocates memory for it in the address space immediately following the first object. The GC continues to allocate space for new objects in this manner as long as the address space is available.
TE
74
Allocating memory from the managed heap is faster than other methods of memory allocation. This is because the runtime allocates memory for an object by adding a value to a pointer, which works almost as fast as allocating memory from the stack. In addition, an application can access the objects quickly because new objects are allocated contiguous address space. The GC also determines the best time to release objects depending upon the memory allocations being made. The GC determines the objects that are no longer being used by examining the application’s roots. An application’s roots include global and static object pointers, local variables and reference object parameters on a thread’s stack, and CPU registers. It then releases the memory for the objects that are no longer being used by the application.
Team-Fly®
067-090.qxd 2/24/03 10:31 AM Page 75
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
MSIL, JIT, and Metadata When you create your source code files written using the .NET Framework, the compiler generates code, called MSIL. MSIL is a set of instructions in which the .NET Framework programs are compiled. MSIL does not depend on the processor on which it is executed. MSIL includes instructions to load, store, initialize, and call methods for objects. It allows integration of applications written in different languages. MSIL provides a hardware abstraction layer, which allows an application being developed to be independent of the underlying operation system. However, MSIL instructions cannot be executed directly by CPUs. Therefore, CLR must first compile MSIL instructions into native CPU instructions. CLR does not convert all the application’s MSIL code to CPU instructions at load time; instead, it compiles the MSIL instructions as the functions are called. This is known as JIT compiling. The component of CLR that is responsible for performing JIT compiling is knows as the JIT compiler. For example, when a class type is loaded in the memory, CLR connects MSIL code to each method. When a method is called, the MSIL code directs program execution to the JIT compiler. After the JIT compiler compiles MSIL code, the code is replaced with the address of the compiled code. When this method is called in the future, the native code will execute. The JIT compiler then will not be involved in the process. This helps in improving the performance considerably. CLR provides two JIT compilers, a normal JIT compiler and an economy JIT compiler. While the normal JIT compiler examines a method’s MSIL and optimizes the resulting native code, the economy JIT compiler simply replaces each MSIL instruction with its native code counterpart. The normal JIT compiler works in a manner similar to a normal, unmanaged C/C++ compiler. The economy JIT compiler is typically used on machines where the cost of using memory and CPU cycles is high. It is much faster that the normal JIT compiler in compiling code. However, the native code produced by the economy JIT compiler is significantly less efficient. As mentioned earlier, the source code files are compiled by respective compilers; and result in a corresponding MSIL. This MSIL is a .NET compliant EXE or DLL file. In addition, the compiler embeds metadata into every EXE or DLL file, which makes it possible to convert the file into native code using JIT. In short,
75
067-090.qxd 2/24/03 10:31 AM Page 76
76
Part I
.NET FRAMEWORK OVERVIEW
.NET metadata is a collection of information that exists in the EXE or DLL file in binary form. All .NET compilers are required to provide metadata information about every class type in the compiled source code module. The metadata contains declaration for every type and its members. Metadata enables you to develop code fast and accurately.
Class Library Another component of the .NET Framework, the .NET Framework class library, consists of a collection of object-oriented and reusable classes that can be used to develop Windows and Web applications. To facilitate interoperability between languages, the .NET Framework classes conform to the CLS. Therefore, these classes can be used from any programming language whose compiler is CLS compliant. This allows third-party components to integrate with the classes in the .NET Framework. The .NET Framework classes provide the base on which .NET applications, components, and controls are built. The .NET Framework class library consists of base classes, data classes, XML classes, XML Web service classes, Web Forms classes, and Windows Forms classes. The list of classes and their corresponding functionality is displayed in Table 3-1. Table 3-1 .NET Framework Class Library Class Type
Functionality
Base classes
Provide basic or standard functionality, such as input/output, string manipulation, security management, network communications, thread management, and text management.
Data classes
Allow persistent data management, include SQL classes to manipulate persistent data stores through a standard SQL interface.
XML classes
Allow manipulation of XML data, and XML searching and translations.
XML Web service classes
Allow creation of lightweight distributed components that can work despite firewalls and network address translation (NAT) software.
Web Forms classes
Allow development of Web applications.
Windows Forms classes
Allow development of Windows applications.
067-090.qxd 2/24/03 10:31 AM Page 77
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
In addition to the main components discussed above, the .NET Framework comprisesseveral runtime hosts. The runtime host loads the CLR into a process and starts the execution of managed code. The .NET Framework supports a number of different runtime hosts, such as ASP.NET, Microsoft Internet Explorer, and Shell executables. You can also develop your own third-party runtime hosts. I’ll now discuss namespaces in the .NET context.
Namespaces A namespace is a logical naming scheme for types that have related functionality. The .NET Framework uses a hierarchical naming scheme for grouping types into logical categories of related functionality. Namespaces enable developers to easily browse and reference types in their code. For example, System is a namespace in the .NET Framework that contains all the basic types used by every application. It contains a base class, Object, from which all other classes derive. In addition, the System namespace contains classes that provide services, such as database management, network communication, security, and user interface controls for Windows and Web applications. The contents of various namespaces and example classes are listed in Table 3-2. Table 3-2 Namespaces in the .NET Framework Namespace
Contents
Example Classes
System
Contains the basic types that are commonly used by almost all the applications
Object, Buffer, Byte, Char,
Contains types that help manage collections of Objects
ArrayList, BitArray,
System.Collections
Array, Int32, Exception, GC, String
Dictionary, Hashtable, Queue, SortedList, Stack
System.Data
Contains basic types for database management
DataBinding, DataRelation, DataRow, DataSet, DataTable, DataSource
System.Globalization
Contains types that allow National Language Support (NLS), String compares, and Calendars
Calendar, CultureInfo, JulianCalendar, NumberFormatInfo, NumberStyles, RegionInfo
continues
77
067-090.qxd 2/24/03 10:31 AM Page 78
78
Part I
.NET FRAMEWORK OVERVIEW
Table 3-2 Namespaces in the .NET Framework Namespace
Contents
Example Classes
System.IO
Contains types that are used for performing I/O operations on data stream
ByteStream, File, FileStream, MemoryStream, Path, StreamReader, StreamWriter
System.Net
Contains types that enable communication in a network
WebRequest, WebResponse, TcpClient, TcpListener, UdpClient, Sockets
System.Reflection
Contains types that allow the examination of metadata
Assembly, ConstructorInfo, FieldInfo, MemberInfo, MethodInfo, Module, ParameterInfo
System.Runtime.Remoting
System.Security
Contains types that provide support for managed remote objects Contains types that provide security features
ChannelServices, RemotingServices, IMessage, ImessageSink Permissions, Policy, Principal, Util, Cryptography
System.Web.UI.Web
Controls
Contains types that provide rich user interface controls for Web-based applications
AdRotator, BorderStyle, DataGrid, HyperLink, ListBox, Panel, RadioButton, Table
System.WinForms
Contains types that provide rich user interface controls for Windows applications
Button, CheckBox, DataGrid, FileDialog, Form, ListBox, MainMenu, MonthCalendar, NewFontDialog, RichEdit, ToolBarTreeView
You can access features of any platform by using these namespaces and their defined classes. You can also customize the behavior of any of these classes by deriving your own class from the desired base class.
067-090.qxd 2/24/03 10:31 AM Page 79
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
Assemblies Assemblies form the building blocks of .NET Framework applications by way of deployment, version control, and reuse. An assembly stores all the types and resources to form a logical unit of functionality. An assembly provides CLR with the information of type implementations. An assembly includes a collection of functionality that is created and deployed as a set of files. The components of an assembly are described in a manifest. A manifest describes the name, version, and other details about an assembly. It also defines the files that exist in an assembly. In addition, you apply security permissions for accessing code in assemblies. Assemblies form a fundamental part of programming with the .NET Framework. An assembly has the following features: ◆ It contains code that CLR executes. The MSIL code is not executed if it does not have an associated assembly manifest. ◆ It is the unit at which permissions are requested and granted. Therefore, it forms a security boundary. ◆ It forms a type boundary. Every type is identified by the name of the assembly in which it resides. Types with a same name but existing in different assemblies are different. For example, a type called MyCompanyType, which exists inside the scope of an assembly, is not the same as a type called MyCompanyType, which resides in the scope of another assembly. ◆ It also forms a reference scope boundary. The assembly’s manifest contains assembly metadata that is used for resolving references to types and executing resource requests. It specifies the types and resources that are exposed outside the assembly. The manifest also enumerates other assemblies on which it depends. ◆ It is the smallest unit in CLR that can be versioned. All types and resources in an assembly are versioned as a unit. The assembly’s manifest describes the version dependencies you specify for any dependent assemblies. Therefore, an assembly forms a version boundary. ◆ It is a deployment unit. When an application starts, only the assemblies that the application initially calls must be present. Other assemblies,
79
067-090.qxd 2/24/03 10:31 AM Page 80
80
Part I
.NET FRAMEWORK OVERVIEW
such as localization resources or assemblies containing utility classes, are retrieved as they are required. This allows applications to be simple and light when they are downloaded. ◆ It also forms the unit that supports side-by-side execution. Side-by-side execution implies running multiple versions of a software component simultaneously. Assemblies can be static or dynamic. Static assemblies can include .NET Framework types (interfaces and classes), as well as resources for the assembly (bitmaps, JPEG files, resource files, and so on). Static assemblies are stored on disk. You can also use the .NET Framework to create dynamic assemblies, which are run directly from memory and are not saved to disk before execution. You can save dynamic assemblies to disk after they have executed. There are several ways to create assemblies. For example, you can use development tools, such as Visual Studio.NET to create assemblies. You can also use tools provided in the .NET Framework SDK to create assemblies. Assemblies are designed to simplify application deployment and to solve versioning problems that can occur with component-based applications. In order to simplify application development and solve versioning and other application problems, the runtime uses assemblies to perform the following tasks: ◆ Allow developers to specify version rules between different software components ◆ Provide an infrastructure that enforces versioning rules ◆ Provide an infrastructure to allow side-by-side execution of a software component Every assembly contains a collection of data in the assembly manifest that describes how the elements in the assembly relate to each other. An assembly manifest contains this metadata to specify the assembly’s version requirements and security identity, define the scope of the assembly, and resolve references to resources and classes. The assembly manifest can be stored either in a PE (portable executable) file (EXE or DLL file) with the MSIL code or in a standalone PE file that contains only assembly manifest information. Table 3-3 lists the elements contained in the assembly manifest. The first four elements, the assembly name, version number, culture, and strong name information, constitute the assembly’s identity.
067-090.qxd 2/24/03 10:31 AM Page 81
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
Table 3-3 Assembly Manifest Contents Elements
Description
Assembly name
It is a text string that specifies the assembly’s name.
Version number
It specifies a major and minor version number, and a revision and build number. The runtime uses these numbers to enforce version policy.
Culture
It stores the culture-specific or language-specific information that the assembly supports.
Strong name information
It contains the public key from the publisher if the assembly has been given a strong name.
List of all files in the assembly
It contains a hash code for each file contained in the assembly and a file name. All the files that make up the assembly must be present in the same directory as the file containing the assembly manifest.
Type reference information
It stores the information used by the runtime to map a type reference to the file that contains its declaration and implementation. This information is used for types that are exported from the assembly.
Information on referenced assemblies
It contains a list of other assemblies that are statically referenced by the assembly. Each reference includes the dependent assembly’s name, assembly metadata, and public key, if the assembly is strong named.
You can add or change some information in the assembly manifest by using assembly attributes in your code. For example, you can change version information and informational attributes, including trademark, copyright, product, company, and informational version.
Language Enhancements This section of the chapter briefly explains the various language enhancements in Visual Basic.NET and Visual C++.NET and also introduces a new language C#. These languages are supported by the .NET Framework.
81
067-090.qxd 2/24/03 10:31 AM Page 82
82
Part I
.NET FRAMEWORK OVERVIEW
Visual Basic .NET Visual Basic.NET is the result of a significant language enhancement of Visual Basic for the .NET Framework. There are a number of changes that make Visual Basic.NET easier to use and more powerful than Visual Basic 6.0, and it has the features that control the access to system resources like C++. One of the most important additions in Visual Basic.NET is that it supports implementation inheritance unlike earlier versions of Visual Basic that supported interface inheritance. In other words, the earlier versions of Visual Basic enable you to only implement interfaces. For example, when you implement an interface in Visual Basic 6.0, you need to implement all the methods of the interface. In addition, you need to rewrite the code each time you implement the interface. On the other hand, Visual Basic.NET supports implementation inheritance. This implies that in Visual Basic.NET, you can derive a class from another class, which is known as the base class. The derived class inherits all the methods and properties of the base class. In the derived class, you can either use the existing code of the base class or override the existing code. Therefore, with the help of implementation inheritance, code can be reused. Although, a class in Visual Basic.NET can implement multiple interfaces, it can inherit from only one class. The base class from which all the managed types derive is System.Object. Garbage collection is another new feature in Visual Basic.NET. The .NET Framework monitors allocated resources, such as objects and variables. In addition, the .NET Framework automatically releases memory for reuse by destroying objects that are no longer in use. In Visual Basic.NET, when an object is not referenced for a long period, it is marked for garbage collection. The garbage collector checks for the objects that are not currently in use by applications. When it comes across an object that is marked for garbage collection, it releases the memory occupied by the object. Unlike the earlier versions of Visual Basic, Visual Basic.NET supports overloading. Overloading enables you to define multiple methods with the same name but with a different set of arguments. In addition to methods, you can also use overloading for properties in a class. Consider a scenario in which you need to use method overloading. You need to create a method that displays the address of an employee. You should be able to view the address of the employee based on either the employee name or the employee code. In such a situation, you can use an overloaded method. In this case, you will create two methods. Each method will have the same name
067-090.qxd 2/24/03 10:31 AM Page 83
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
but different arguments. The first method will take the employee name as the argument, and the second will take the employee code as the argument. As mentioned earlier, the .NET Framework class library is organized into namespaces. Namespaces are used to logically group classes within an assembly. These namespaces are available in all the .NET languages, including Visual Basic.NET. You can also create your own namespaces in Visual Basic.NET besides using the available namespaces. Another new feature found in Visual Basic.NET is that it supports multithreading. An application that supports multithreading can handle multiple tasks simultaneously. You can use multithreading to decrease the time taken by an application to respond to user interactions. Visual Basic.NET also supports structured exception handling, which enables you to identify and remove errors at run time. In Visual Basic.NET, you can create robust and effective exception handlers to improve the performance of your application. Table 3-4 briefly describes a few differences between Visual Basic 6.0 and Visual Basic.NET in terms of availability of features. Table 3-4 Differences Between Visual Basic 6.0 and Visual Basic .NET Feature
Visual Basic 6.0
Visual Basic .NET
Line control
Available
Not available
OLE Container control
Available
Not available
Shape controls
Available
Not available
Dynamic Data Exchange (DDE) support
Available
Not available
Data Access Objects (DAO) data binding
Supported
Not supported
Remote Data Objects (RDO) data binding
Supported
Not supported
Available
Not available
Fixed-length strings
Supported
Not supported
Fixed-size arrays
Supported
Not supported
Use of the ReDim statement
Array declaration
Array resizing
Universal data type
Variant
Object
Option base
statement
continues
83
067-090.qxd 2/24/03 10:31 AM Page 84
Part I
.NET FRAMEWORK OVERVIEW
Table 3-4 Differences between Visual Basic 6.0 and Visual Basic .NET Feature
Visual Basic 6.0
Visual Basic .NET
Currency data type
Supported
Not supported
Data type to store date values
Double
DateTime
Supported
Not supported
DefType
statements
operator
Supported
Not supported
Imp
operator
Supported
Not supported
Default properties for objects
Supported
Not supported
Declaring structures
Type...End Type
Structure...End Structure
Scope of a variable declared in a block of code within a procedure
Procedure scope
Block scope
Values for optional arguments
Not required
Required
Supported
Not supported
Available
Not available
Default mechanism for passing arguments
ByRef
ByVal
Syntax of while loop
While...Wend
While...End While
Supported
Not supported
Supported
Not supported
Supported
Not supported
Supported
Not supported
Supported
Not supported
Supported
Not supported
AM FL Y
Eqv
TE
84
Declaring procedures as static GoSub
Null
statement
keyword
Empty
keyword
IsEmpty
function
Option Private Module Class_Initialize Class_Terminate
event
event
statement
In addition to the differences mentioned above, Visual Basic.NET does not support various applications supported by Visual Basic 6.0. For example, Visual Basic.NET does not support ActiveX documents. In addition, Visual Basic.NET does not support DHTML applications and Web classes that Visual Basic 6.0 supports. Visual Basic.NET is also incompatible with Windows Common controls and the Data-Bound Grid controls available in Visual Basic 6.0.
Team-Fly®
067-090.qxd 2/24/03 10:31 AM Page 85
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
Visual C++ .NET Visual C++.NET also includes enhanced features from Visual C++ 6.0 that have resulted in the improved performance of the language. Some of the enhanced features of Visual C++.NET are: ◆ Shared classes. In Visual C++ 6.0, while using MFC classes, you needed to add appropriate MFC dependencies. However, in Visual C++.NET, common MFC classes are shared and are no more MFC-dependant. ◆ Unified event handling. In Visual C++ 6.0, the implementation of event handling methods differed for native (C++) and COM code, whereas, Visual C++ .NET follows the same event handling method for native, COM, and managed code. ◆ Integrated debugger. Visual C++ .NET applications use the common debugger provided by the Visual Studio.NET. ◆ Class View. Class View enables you navigate to the classes, functions, and member variables in your application easily by listing them in a treelike structure. Apart from this, in the Class View, you can access wizards to add member classes and variables. Apart from these enhancements, some new features have been added to Visual C++.NET. A brief description of some of these features is provided in the following list. ◆ Managed Extensions for C++. You use managed extensions to create managed applications that can target CLR and use the services provided by CLR. This provides advanced features, such as garbage collection and language interoperability. ◆ Attributed programming. Attributed programming is a new feature supported by Visual C++.NET. An attribute is a declaration that is replaced by the appropriate code when compiled. It is designed to simplify application programming. ◆ ATL Server. Visual C++ .NET also supports ATL server, which enables you to create Web applications, XML Web services, and other server applications.
85
067-090.qxd 2/24/03 10:31 AM Page 86
86
Part I
.NET FRAMEWORK OVERVIEW
C# Microsoft’s C#, pronounced as C sharp, is an advanced version of C and C++ and is designed specially for the .NET Framework. C# is a modern, object-oriented language that enables developers to quickly develop a wide range of applications for the .NET platform. It combines the powerful features of C and C++ along with its new features to bring rapid development of the applications. C# is an ideal solution for developing high-level business applications. Using C#, you can create a wide range of client/server applications. C# includes built-in support to convert any component into a Web service that can be invoked over the Internet from any application running on any platform. The language helps improve developers’ productivity and eliminate programming errors.
Visual Studio .NET Visual Studio.NET is the latest version of the Visual Studio and has been designed to work on the .NET Framework. It provides you a development platform, IDE (Integrated Development Environment), for creating applications using languages that support the .NET Framework, such as Visual Basic.NET, Visual C++.NET, and C#. It also includes tools required to develop Windows and Web applications and services. The two most significant advantages of Visual Studio.NET are as follows: ◆ All Visual Studio.NET languages have the same IDE. This is unlike the previous version Visual Studio 6.0, in which Visual Basic and Visual C++ had an IDE different from that of the other languages. This ensures that you don’t have to switch between environments to develop, deploy, and debug your code. It results in a faster and easier development of applications. ◆ Programming in ASP.NET is made easier. ASP.NET simplifies the development of Web application and provides some advanced capabilities such as efficient database access. You can code, compile, and debug your ASP.NET application in Visual Studio.NET itself. The various components of the IDE are described in the following list. ◆ Start Page. This is the first screen that appears when you launch Visual Studio.NET as shown in Figure 3-1. This is set as the home page for
067-090.qxd 2/24/03 10:31 AM Page 87
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
Visual Studio.NET IDE. You can use this page to create new projects or to open existing ones. ◆ Solution Explorer. The Solution Explorer contains all the projects that you create and their associated files as shown in a sample in Figure 3-2. It displays the information in a hierarchical tree view, which eases the navigation. ◆ Server Explorer. The Server Explorer helps you to connect to servers and databases. The Data Connection node of the Server Explorer lists all database connections and the Servers node lists the servers that your application can use as shown in Figure 3-3. ◆ Toolbox. The toolbox contains all controls used to design an application. The controls are available in the form of groups, such as Windows Forms controls and Data controls. One significant enhancement is that you can store code snippets in the toolbox by simply selecting and dragging it to the toolbox. You can also create your own groups. ◆ Task List and Output window. The IDE provides a single window with two tabs, Task List and Output. When you click on Task List, the Task List window is activated. This window helps you to mark your application’s code with comments that are displayed in a tabular format. The
FIGURE 3-1 The Start Page
87
067-090.qxd 2/24/03 10:31 AM Page 88
88
Part I
.NET FRAMEWORK OVERVIEW
FIGURE 3-2 The Solution Explorer
FIGURE 3-3 The Server Explorer
Output window displays the errors and warnings that occur when you compile your application. ◆ Properties window. You use the Properties window to view the characteristics associated with an object, such as a text box control on a form.
067-090.qxd 2/24/03 10:31 AM Page 89
INTRODUCTION TO THE .NET FRAMEWORK
Chapter 3
◆ Class View window. The Class View window lists the classes, methods, and properties associated with a project. ◆ Code and Text Editor. Code and Text Editor allows you to enter and edit the code of your application.
Debugger Visual Studio.NET provides a common debugger for all .NET languages. It debugs applications written and compiled for the Microsoft .NET runtime. Debugging in the .NET Framework is no more language-dependent. Some of the significant features of the debugger are provided in the following list. ◆ Cross-language debugging ◆ Debugging support for both .NET applications targeted for CLR and Win32 applications ◆ Debugging support for multiple programs simultaneously ◆ Remote debugging
Summary In this chapter, you learned about the .NET Framework. First, you learned about the components available in the .NET architecture. Next, you learned the important concepts, such as CLS, CTS, Garbage Collection, MSIL, JIT, and metadata, supported by the CLR. Then, you learned about namespaces and assemblies. You also learned about the language enhancements in Visual Basic.NET, Visual C++.NET, and C#. At the end of the chapter, you learned about the Visual Studio.NET and its debugger.
89
067-090.qxd 2/24/03 10:31 AM Page 90
This page intentionally left blank
091-092.qxd 2/24/03 10:32 AM Page 91
PART
II Professional Project 1
091-092.qxd 2/24/03 10:32 AM Page 92
This page intentionally left blank
093-094.qxd 2/24/03 10:33 AM Page 93
Project 1 Database Integration with .NET
093-094.qxd 2/24/03 10:33 AM Page 94
Project 1 Overview
AM FL Y
The application created in this project can be used to allow users to modify records from a table in an SQL database. In this project, I’ll discuss how to create a Windows application that generates a report called Authors Titles that displays author names and the titles written by the authors. The application allows you to save the report data as an XML file, the structure of the report data as a file in the .xsd format, and the data and its related structure as an XML file. The application displays data used for the report and for modification from the pubs database of SQL Server 2000.
TE
The application has been built in Visual Basic.NET by using Visual Studio.NET. In this project, ADO.NET is used to retrieve data from the pubs database. In addition, you will convert the report data and its associated schema into the XML format. In the same section, I will guide you to create the previously mentioned application using C# and also give you an overview of C# basics. The rationale in recreating the same application using C# is that by doing so you will acquire the skills to work with C#, which is a new language.
Team-Fly®
095-100.qxd 2/24/03 10:35 AM Page 95
Chapter 4 Project Case Study
095-100.qxd 2/24/03 10:35 AM Page 96
rom this chapter onwards, you will create projects by using the various technologies supported by the .NET Framework. With the intention of making the projects close to real life, the projects are based on the case study of a publishing house.
F
In this chapter, you will look at the case study of a publishing house. You will also learn about the different phases involved in a project lifecycle.
TecPublishers— A Publishing Consortium TecPublishers is a consortium of publishers that publishes books on wide-ranging topics. The consortium has its head office in New York City and has branch offices in San Francisco, New Orleans, Seattle, and Montreal. Each branch office is equipped with a few computers. Each of these branch offices functions as an independent publishing unit where the entire publishing process is handled by a team of 15 people. A publishing unit is comprised of a publisher, senior editors, and typographers. In addition, each publishing unit corresponds with the authors in its respective region and maintains records of all the contracts, the publishers, the authors, and the titles written by the authors in an SQL Server 2000 database. The unit also maintains a record of the revenues generated from the sales of the books and the individual book profit margins. The database servers maintained at each publishing unit are synchronized with the publishing server located at the main office in a location specific key based horizontal partitioning model. To facilitate and centralize the management of the publishing units, the consortium is headed by a president who is aided by managers. The top management located at the head office performs semi-annual as well as annual reviews of the business conducted at each publishing unit. TecPublishers has recently formed an alliance with other publishers. As a result, many new branch offices have been opened recently. For instance, a branch office has been opened in Buenos Aires. These new branch offices have very few computers.
095-100.qxd 2/24/03 10:35 AM Page 97
PROJECT CASE STUDY
Chapter 4
In addition, to provide users information about the books published by TecPublishers, the consortium has created a Web site that provides required information. Users can access this information by registering with the company’s Web site. The subsequent section describes the different phases in a typical project cycle for developing an application.
Project Lifecycle The creation of a project is driven by the need to incorporate functionality or upgrade the existing system. The focus of the projects in the current scenario will be based on incorporating functionality. For the successful completion of a project, the project needs to undergo a well-defined lifecycle, where different aspects of the project are decided. The development lifecycle of a project involves three phases: ◆ Project initiation ◆ Project execution ◆ Project deployment The project initiation phase involves the creation of a project plan that lists the various tasks likely to be involved in the creation of the project. In addition, the team members and their specific roles are decided in this phase. The project execution phase involves the actual development of the required application. The output of this phase is the developed application. This phase is, in turn, divided into the following stages: ◆ Requirements analysis ◆ High-level design ◆ Low-level design ◆ Construction ◆ Integration and test ◆ User acceptance test These stages are covered in the sections that follow an explanation about the project deployment phase.
97
095-100.qxd 2/24/03 10:35 AM Page 98
98
Project 1
DATABASE INTEGRATION WITH .NET
The project deployment phase comprises the final phase in the lifecycle of the project. In this phase, the application is deployed at the client location. This phase also involves providing the required support to the client for a stipulated time period during which any error or problem related with the application is resolved. As stated earlier, the following sections will introduce you to the stages included in the project execution phase.
Requirements Analysis The requirements analysis stage comprises an important phase of a project lifecycle that delves into the “why” or the need aspect of the project. It is this phase that the development team utilizes to analyze the requirements of the project to meet customer requirements. Various methods are employed to arrive at the exact requirements of an application. Some of the methods employed include interviews and analyzing the existing entities. At the end of the requirements analysis stage, all the requirements are listed. Based on the output of this stage, decisions related to the other stages are made.
High-Level Design After the requirements for the project are analyzed, the team decides upon the functionality and the final output of the application. These decisions are taken in the high-level design stage. In this stage, the input and output formats for the application and the operating requirements for the application are identified. In other words, the various screens or forms in the application and the associated controls are finalized. In addition, the functionality of each control is decided. The functional specifications documentation of the interfaces for the application is approved from the client.
Low-Level Design In the low-level design phase, a detailed design of the software modules in the application is created based on the output of the high-level design. In addition, various standards, such as naming convention for variables, controls, and forms for a project, related to the application are documented. The naming conventions as decided by the team for the application project are listed in Table 4-1.
095-100.qxd 2/24/03 10:35 AM Page 99
PROJECT CASE STUDY
Chapter 4
Table 4-1 Naming Conventions Item
Convention
Project
Name of the project appended to ‘prj’ (example prjADOReports)
Solution
Name of the solution appended to ‘sln’ (example slnADOReports)
Keeping the requirements in mind, the team also decides upon the technologies to be used for the functionality of an application.
Construction In the construction stage, the actual creation of the application happens. The actual construction procedure for an application can be divided into two separate activities, creation of interface and coding for the various components or modules in the application. All the specifications identified in the low-level design are implemented in this stage. To ensure timely completion and equal distribution of the workload, responsibilities are shared between team members.
Testing After creation, the application needs to be tested to verify that the requirements as specified at the beginning of the project have been satisfactorily met. For this purpose, the application needs to be tested by a Quality Assurance (QA) team. Before the QA team begins testing the application, the development team submits all the requirements as documented during the requirements analysis phase. In addition, the functionality of the application is elaborated to the QA team. Various test cases and permutations are supplied to the QA team. After testing the application, the QA team submits a report that includes the inconsistencies with the requirements and defects in the application, if any. The development team is expected to update the application based on the report received.
User Acceptance Test The user acceptance stage involves testing the application to verify that the application meets the predefined acceptance criteria as specified by the client. Additionally, support is provided to troubleshoot the issues related to the application as reported during this stage.
99
095-100.qxd 2/24/03 10:35 AM Page 100
100
Project 1
DATABASE INTEGRATION WITH .NET
After incorporating the required changes and the acceptance, the application is put to use. Errors, if any, related to the installation and debugging of the application are handled by the development team.
Summary In this chapter, you looked at the case study of TecPublishers, a publishing consortium. You will use this case study for all the project chapters in the book. Finally, you looked at the different stages in the lifecycle of a project.
101-144.qxd 2/24/03 10:37 AM Page 101
Chapter 5 Introduction to ADO.NET
101-144.qxd 2/24/03 10:37 AM Page 102
DO.NET is a .NET Framework-compliant data access technology. This technology has been developed from the existing ActiveX Data Objects (ADO) technology to provide data access services to .NET programmers.
A
Why was there a need for enhancing ADO to ADO.NET? To answer this question, you need to consider the .NET Framework. The advent of the .NET Framework ushered in a new programming model that supports disconnected data architecture through XML. Simply stated, the .NET Framework supports a programming model where a connection to a data source need not remain open for the lifetime of an executing program. In addition, XML forms the basis of data encoding for transporting data across network connections and between tiers. To meet the demands of the new programming model ushered in by the .NET Framework, ADO.NET was built to provide a disconnected data architecture. Therefore, ADO.NET enables you to create distributed multitier and data-sharing applications. You can also use ADO.NET to access data from a relational database, an XML source, or another application. ADO.NET also implements data binding and a closely knit support and integration with XML. In fact, XML forms the crux of ADO.NET. There is inherent and implicit support for XML in ADO.NET. The collated benefits of these features of ADO.NET facilitate the creation of front-end database clients and middle-tier business objects. For instance, you can now integrate business objects with a wide spectrum of applications by exchanging data in the XML format. However, the .NET Framework retains the essence of ADO in ADO.NET through .NET COM Interop. You will learn about COM Interop later in the chapter. In this chapter, you will learn about the ADO.NET architecture and its components. You will learn how the ADO.NET architecture enables you to handle data from different data sources. Next, you will look at the concept of data binding in ADO.NET. Finally, you will look at how ADO.NET closely integrates with XML. Although ADO.NET permits the usage of programming languages ranging from Visual Basic.NET and Visual C++.NET to Visual C#, for simplicity and consis-
101-144.qxd 2/24/03 10:37 AM Page 103
INTRODUCTION TO ADO.NET
Chapter 5
tency, references to all code snippets and properties in this chapter are made with respect to Visual Basic.NET.
ADO.NET Architecture The disconnected data architecture of ADO.NET allows you to manage data in n-tier systems or distributed applications, such as e-commerce server applications, and in client applications, such as Windows Forms. To support the disconnected data architecture, ADO.NET utilizes the capabilities of XML. For this purpose, support for XML is closely knit in ADO.NET. You will learn about the integration and support for XML in ADO.NET in the section called “ADO.NET and XML” later in the chapter. The ADO.NET architecture comprises classes and objects that help you manage and work with data obtained from multiple data sources. The main components of the ADO.NET architecture are: ◆ .NET data provider ◆ Dataset While you use a .NET data provider for data access, a dataset is used for data manipulation. Figure 5-1 illustrates the components of the ADO.NET architecture. In the subsequent sections, I will discuss the components of the ADO.NET architecture.
FIGURE 5-1 Components of the ADO.NET architecture
103
101-144.qxd 2/24/03 10:37 AM Page 104
Project 1
DATABASE INTEGRATION WITH .NET
.NET Data Provider As the name suggests, .NET data provider facilitates data-related activities by providing access to data. To allow access to data, a .NET data provider connects to a database, executes commands, and retrieves the results of the commands. The data obtained can be stored in memory. This temporary storage of data in memory cache is known as dataset. Additionally, after working with the data, .NET data providers also allow you to update the data source with the modified data. Therefore, .NET data providers act as a link between a data source and an application.
AM FL Y
To provide a link between a data source and an application, a .NET data provider uses four core components that are referred to as .NET data provider objects. The .NET data provider objects are: ◆ The Connection object ◆ The Command object
◆ The DataReader object
◆ The DataAdapter object
TE
104
Using the .NET data providers facilitate interaction with different data sources, such as SQL Server databases and OLE DB databases. Keeping this in mind, the .NET Framework includes different types of .NET data providers. The three types of .NET data providers are: ◆ SQL Server .NET data provider. You use the SQL Server .NET data provider to specifically access an SQL Server 7.0 or later database. ◆ OLE DB .NET data provider. You use the OLE DB .NET data provider to access data from any OLE DB-compliant data source, such as Oracle and SQL Server. ◆ ODBC .NET data provider. You use the ODBC .NET data provider to access ODBC-compliant data sources. This .NET data provider can be downloaded from the Web site http://msdn.microsoft.com/downloads. The implementation of this .NET data provider is similar to the other two .NET data providers. Additionally, you can create and implement your own .NET data providers. Figure 5-2 illustrates the different components and types of .NET data providers. In the subsequent sections, I will discuss the .NET data provider objects. Later, you will learn about the types of .NET data providers.
Team-Fly®
101-144.qxd 2/24/03 10:37 AM Page 105
INTRODUCTION TO ADO.NET
Chapter 5
FIGURE 5-2 Components and types of .NET data providers
The Connection Object To access data from any data source, it is of prime importance that you first establish a connection with the data source. You can establish a connection with a data source by using the Open() method of the Connection object. In addition, you can specify a string with parameters, such as the data source name, user ID, and password, to connect to a data source. For instance, the following code snippet displays the use of a string with parameters to connect to an SQL Server called web-server. Dim strConnectionString As String ‘connection string to contain the necessary parameters and values required to establish a connection with an SQL Server database Dim instOleDbConnection As OleDbConnection
105
101-144.qxd 2/24/03 10:37 AM Page 106
106
Project 1
DATABASE INTEGRATION WITH .NET
strConnectionString = “Provider=SQLOLEDB.1;Data Source=web-server;USER ID=sa;pwd=;Initial Catalog=Pubs” ‘initializes strConnectionString to access the Pubs database on SQL Server called web-server instOleDbConnection = New OleDbConnection(strConnectionString) ‘establishes a connection by using strConnectionString
You will learn more about this method of establishing a connection with a data source in Chapter 6, “Creating a Windows Application in Visual Basic Using ADO.NET to Implement Database Connectivity.” After working with the data of the data source, it is essential to close the connection with the data source. To accomplish this, you can use either the Close() method or the Dispose() method of the Connection object.
The Command Object The next step after establishing a connection with a data source is to perform various data-related operations, such as updating records, on the data source. You can use the Command object to execute commands, such as SQL queries, on the data source. You can use the CommandType property of the command to specify its type. For instance, the syntax for specifying the CommandType property as StoredProcedure in a Visual Basic.NET application is: instSQLCommand.CommandType = CommandType.StoredProcedure ‘where instSQLCommand is an SqlCommand object.
Using the Command object, you can retrieve data, update data, or execute stored procedures. To create a Command object, you can use any of the listed methods. ◆ Use the constructor of the Command class. While using the constructor of the Command class, you need to specify an SQL statement and a Connection object. The syntax for using the constructor of the Command class is: Dim SQLQuery1 As String = “SELECT au_id, au_lname FROM Authors” ‘specifies a SELECT statement as a String type. Dim OLEConnection1 As New OleDbConnection(strConnectionString) ‘creates a Connection object to access an OLE DB data source. Dim OLECommand1 As New OleDbCommand(SQLQuery1, OLEConnection1) ‘creates a Command object to execute the SQLQuery1 SQL statement.
101-144.qxd 2/24/03 10:37 AM Page 107
INTRODUCTION TO ADO.NET
Chapter 5
◆ Call the CreateCommand() method of the Connection object. The syntax for invoking the CreateCommand() method of the Connection object in a Visual Basic.NET application is: Dim OleDbCmd1 As OleDbCommand OleDbCmd1 = instOleDbConnection.CreateCommand() ‘where instOleDbConnection is an OleDbConnection object. OleDbCmd1.CommandText = “select * from table1”
The DataReader Object Logically, after executing a command on the data source, the data returned by the command needs to be retrieved. The DataReader object retrieves the data returned by a command from a data source. The DataReader object is analogous to a forward-only cursor in that the DataReader object retrieves data or rows from a data source in a sequential manner. Additionally, this object returns a read-only stream of data from the data source. The listed code snippet displays the usage of the DataReader object to read the contents of the result set obtained after executing a command on a data source. Dim newRdr As SqlDataReader ‘declares an SqlDataReader object called newRdr. newRdr = newCmd.ExecuteReader() ‘where newCmd is a SqlCommand object. ‘retrieves rows from the result set by using the ExecuteReader() method.
At any point in time, the DataReader object stores only one row obtained from the data source in the memory. In other words, the entire result set retrieved from a data source is never cached in memory. As a result, the implementation of a DataReader object considerably reduces the system overhead and enhances application performance.
NOTE While a DataReader object is in use for a connection, commands cannot be executed for the particular connection simultaneously. Therefore, you will not be able to access the output parameter or return values of the Command object. To access the output parameter or return values of the Command object, you need to close the DataReader object after using the DataReader object.
107
101-144.qxd 2/24/03 10:37 AM Page 108
108
Project 1
DATABASE INTEGRATION WITH .NET
The DataAdapter Object A DataReader object enables you to access data row-wise from a data source. Alternately, you can store the data from a data source in memory for use by an application. The latter method of data access is disconnected and is implemented using the DataAdapter object. The DataAdapter object enables you to transfer data from a data source to the cache in memory and vice versa. Therefore, the DataAdapter object acts as a link between a data source and a dataset. A DataAdapter object can transfer different types of data based on the stored procedures and the SQL statements used. The DataAdapter class consists of a set of properties that facilitate loading and updating data. Table 5-1 lists some DataAdapter properties. Table 5-1 DataAdapter Properties Property
Description
SelectCommand
Returns or sets a T-SQL statement or stored procedure used to select records from a data source.
UpdateCommand
Returns or sets a T-SQL statement or stored procedure used to update records in a data source.
DeleteCommand
Returns or sets a T-SQL statement or stored procedure used to delete records from a dataset.
InsertCommand
Returns or sets a T-SQL statement or stored procedure used to insert records in a data source.
Figure 5-3 illustrates the interaction among the .NET data provider objects. You just looked at the .NET data provider core objects and their roles in disconnected data architecture. You can use .NET data provider objects to access SQL Server 7.0 or later databases or OLE DB data sources. The .NET data provider objects that access the aforementioned data sources are different from each other and are collectively known as SQL Server .NET data provider and OLE DB .NET data provider, respectively. To use either of these .NET data providers, you need to install Microsoft Data Access Components (MDAC) 2.6 or later. MDAC is installed, by default, when you install Visual Studio.NET. Additionally, you need to include the .NET data
101-144.qxd 2/24/03 10:37 AM Page 109
INTRODUCTION TO ADO.NET
Chapter 5
FIGURE 5-3 Interaction among the .NET data provider objects
provider in your application before accessing a specific data source. In the subsequent sections, I will discuss the two different types of .NET data providers.
SQL Server .NET Data Provider The SQL Server .NET data provider allows you to access an SQL Server 7.0 or later database by using the Tabular Data System (TDS) protocol. TDS is an application-level protocol used by SQL Server 2000 to communicate with client applications. The SQL Server .NET data provider does not require an OLE DB or ODBC layer to access an SQL Server database, consequently proving to be a lightweight option for optimum performance. To use the SQL Server .NET data provider in your application, you need to include the System.Data.SqlClient namespace in your application. In Chapter 3, “Introduction to the .NET Framework,” you learned that a namespace is a naming scheme designed to logically group all related types, such as classes. The System.Data.SqlClient namespace includes all the classes required by the SQL Server .NET data provider. The names of the classes stored in the
109
101-144.qxd 2/24/03 10:37 AM Page 110
110
Project 1
DATABASE INTEGRATION WITH .NET
namespace begin with “Sql”. For example, SqlCommand is a class stored in the System.Data.SqlClient namespace.
System.Data.SqlClient
The syntax to include the Basic.NET application is:
System.Data.SqlClient
namespace in a Visual
Imports System.Data.SqlClient
NOTE Namespaces that allow you to manage and work with data are referred to as datarelated namespaces. The main data-related namespace is System.Data. The System.Data namespace is largely composed of data-related classes that ADO.NET uses to enable you to access and manage data from multiple data sources. For instance, the DataSet class represents a set of data obtained from a data source. All classes that comprise the ADO.NET architecture are stored in the System.Data namespace. Therefore, before using ADO.NET in your application, you need to include the System.Data namespace in your application. The syntax for including System.Data in a Visual Basic.NET application is: Imports System.Data
The System.Data namespace, in turn, includes namespaces such as System.Data.SqlClient and System.Data.OleDb.parameter or return values of the Command object, you need to close the DataReader object after using the DataReader object.
Some of the most commonly used SQL Server .NET data provider classes are listed in Table 5-2. Table 5-2 Commonly Used SQL Server .NET Data Provider Classes Class
Description
SqlConnection
Represents an open connection with an SQL Server database.
SqlCommand
Represents a T-SQL statement or stored procedure to be executed on an SQL Server 7.0 or later database.
SqlDataReader
Reads a stream of rows from an SQL Server 7.0 or later database in a forward-only sequence.
101-144.qxd 2/24/03 10:37 AM Page 111
INTRODUCTION TO ADO.NET
Chapter 5
Class
Description
SqlDataAdapter
Represents the data commands used to transfer data from an SQL Server 7.0 or later database to a dataset and vice versa.
SqlException
Represents the exception thrown when SQL Server returns an error.
SqlError
Gathers error- or warning-related information that an SQL Server returns.
Each of the classes mentioned in Table 5-2 includes its own methods. I will discuss the methods for a few of these classes in Tables 5-3, 5-4, 5-5, and 5-6. Table 5-3 SqlConnection Methods Method
Description
ChangeDatabase
Changes the current database to use another database for an existing open SqlConnection.
Close
Closes the connection with a database.
CreateCommand
Creates and returns an SqlCommand object for a particular SqlConnection.
Table 5-4 SqlCommand Methods Method
Description
ExecuteReader
Returns a DataReader object by invoking commands by using the T-SQL sp_executesql system stored procedure.
ExecuteNonQuery
Executes commands that do not return rows, such as T-SQL INSERT, DELETE, UPDATE, and SET statements.
ExecuteScalar
Retrieves the value of the first column of the first row in the result set obtained after executing a query.
111
101-144.qxd 2/24/03 10:37 AM Page 112
112
Project 1
DATABASE INTEGRATION WITH .NET
Table 5-5 SqlDataReader Methods Method
Description
Read
Accesses the current row of the result set retrieved from a data source and moves SqlDataReader forward to the next row.
NextResult
Navigates through result sets in a sequential manner. Applicable only when DataReader consists of multiple result sets.
GetSchemaTable
Retrieves the schema-related information about the current result set in the form of a DataTable object.
GetDateTime
Returns the column value as a DateTime object.
GetInt32
Returns the column value as a 32-bit signed integer.
Close
Closes the current DataReader object.
Table 5-6 SqlDataAdapter Methods Method
Description
Fill
Populates or refreshes data in a dataset and incorporates the same data structure in the dataset as in the data source.
Update
Modifies a data source to reflect changes in the data of a dataset by using the appropriate T-SQL statements, such as INSERT, UPDATE, or DELETE, against the data source.
OLE DB .NET Data Provider You can use the OLE DB .NET data provider to access OLE DB-compliant data sources, including databases on all versions of SQL Server. You can access versions of SQL Server earlier than 7.0 by using the OLE DB .NET data provider with SQL Server OLE DB Provider (SQLOLEDB). To access data from data sources, the OLE DB .NET data provider uses OLE DB through COM Interop. You can use COM Interop to access existing COM components without modifying them. All the classes used by the OLE DB .NET data provider are stored in the System.Data.OleDb namespace. Therefore, to use the OLE DB .NET data provider, you need to include the System.Data.OleDb
101-144.qxd 2/24/03 10:37 AM Page 113
INTRODUCTION TO ADO.NET
Chapter 5
namespace in your application. The syntax for including the namespace in a Visual Basic.NET application is: Imports System.Data.OleDb
The names of the classes stored in the System.Data.OleDb namespace begin with “OleDb”. For example, OleDbCommand is a class stored in the System.Data.OleDb namespace. Some other classes used by the OLE DB .NET data provider are OleDbConnection, OleDbCommand, OleDbDataReader, and OleDbDataAdapter. The methods of these classes are similar in function to the methods available in the SQL Server .NET data provider classes discussed earlier.
NOTE The OLE DB .NET data provider does not support OLE DB 2.5 interfaces. As a result, all OLE DB providers that require or support OLE DB 2.5 interfaces, such as Microsoft OLE DB Provider for Exchange and Microsoft OLE DB Provider for Internet Publishing, will not function appropriately with the OLE DB .NET data provider. Additionally, the OLE DB .NET data provider is not compatible with the OLE DB Provider for ODBC (MSDASQL).
The nature of the application and the data source to be accessed determine the .NET data provider to be used. Table 5-7 lists .NET data providers and their recommended implementations. Table 5-7 Recommendations for Implementing .NET Data Providers .NET Data Provider
Implementation
SQL Server .NET data provider
Middle-tier applications that use SQL Server 7.0 or later. Single-tier applications using Microsoft Data engine (MSDE) or SQL Server 7.0 or later.
OLE DB .NET data provider
Middle-tier applications that use Oracle or SQL Server 6.5 or earlier. Single-tier applications using an MS Access database.
113
101-144.qxd 2/24/03 10:37 AM Page 114
Project 1
DATABASE INTEGRATION WITH .NET
You just looked at the .NET data provider component of the ADO.NET architecture. You will now look at the other core component of the ADO.NET architecture, dataset.
Dataset After a .NET data provider has accessed and read data from a data source, the data needs to be stored for use by an application. Data retrieved from a data source can be stored in a location in memory called dataset.
AM FL Y
The ADO.NET architecture supports disconnected and distributed data architecture by using datasets. You can use datasets to work with data independent of a data source. This implies that after establishing a connection with a data source, the result set returned by a command is stored in memory and can be used by any application. However, as you learned in the section “The DataReader Object,” a DataReader object stores only one row from the data source in memory and the entire result set retrieved from a data source is never cached in memory. In other words, you can choose between two methods of accessing data, viz. DataReader and dataset. How will you decide as to which method you should implement when? Consider an application that needs to combine data from multiple data sources. In this case, reading one row into memory and combining the data from data sources would be a cumbersome or a near-impossible task. A better option would be to store the required data from the data source in memory and then combine the data. Therefore, to ensure an ad-hoc access to data from multiple data sources, you will implement datasets. In other words, the functionality of an application decides the type of data access to use.
TE
114
Typically, you implement datasets when you need to: ◆ Bind data to a Windows Forms control or combine and relate data from multiple data sources. ◆ Send data between tiers or from an XML Web service. ◆ Manage data local to the application. ◆ Manage data in a disconnected architecture. ◆ Have a consistent relational programming model regardless of the data source. ◆ View relational data in a hierarchical manner.
Team-Fly®
101-144.qxd 2/24/03 10:37 AM Page 115
INTRODUCTION TO ADO.NET
Chapter 5
However, if you need to keep the utilization of memory and the performance parameter for an application in mind, you can use the DataReader object. Additionally, while you populate a dataset by using a DataAdapter object, the DataAdapter object internally uses a DataReader object to fill the contents of the dataset. A dataset is represented by the DataSet class. The data in a DataSet object is stored in the form of tables represented by DataTable objects. Each DataTable object represents one table of data located in the memory. In addition to DataTable objects, a DataSet object comprises the information related to the data in DataTable objects, such as the primary key, the foreign key, and the relationships between columns of tables. You can store additional information in a DataSet object, which could be the query used to generate the result set stored in the DataSet object. To store additional information, you use the property called ExtendedProperties. The ExtendedProperties property is available for use in DataSet, DataTable, and DataColumn objects, where a DataColumn object represents a column in a DataTable object.
NOTE At times, the need for DataSet and DataAdapter might not seem justified. For instance, when executing queries that return only one value, such as an evaluation or an aggregate function result, DataSet and DataAdapter objects might not be of much use. Similarly, for any query that does not return a result set, you will not be able to implement DataSet and DataAdapter. In such a case, you can opt for performing database operations directly by using data commands. Data commands are commands that can be executed directly on a data source.
There is much to discuss about datasets. To begin with, I will discuss the components of datasets. Next, I will talk about the two types of datasets available in ADO.NET, typed and untyped datasets. Then, you will learn how to create and populate datasets. Subsequently, in the section “Managing a Data Source by Using Datasets,” I will discuss how datasets manage data. Finally, I will discuss the concept of data binding in ADO.NET. In the subsequent sections, you will learn about the components of a object. Figure 5-4 illustrates the components of a DataSet object.
DataSet
115
101-144.qxd 2/24/03 10:37 AM Page 116
116
Project 1
DATABASE INTEGRATION WITH .NET
FIGURE 5-4 Components of a DataSet object
DataTableCollection The
object represents the set of DataTable objects in a object. You can add or remove a specific DataTable object from the DataTableCollection class by using the Add() and Remove() methods, respectively. The following code snippet adds a DataTable object to the DataTableCollection object. DataTableCollection
DataSet
Dim dSet As DataSet Dim dt As DataTable
101-144.qxd 2/24/03 10:37 AM Page 117
INTRODUCTION TO ADO.NET
Chapter 5
dt = dSet.Tables.Add(“newTable”) ‘adds a new table called newTable.
You can remove all the DataTable objects stored in the DataTableCollection object by using the Clear() method. The Contains() method returns a Boolean value that determines whether a table exists in the DataTableCollection object. Each DataTable object derives data from a single data source. You can use Dataeither as an independent object or from within a DataSet object. A DataTable object can also be used from within other .NET Framework objects, such as DataView. While creating a DataTable object, you must first define the schema or structure of the table. The schema of a DataTable object is defined by the columns and foreign key and unique constraints in the table. Therefore, to define the schema of a table, you need to add columns and foreign key and unique constraints to the table. Table
NOTE DataView is a .NET Framework object that enables you to create different views of the data stored in a DataTable object. You will learn more about the DataView object in the section called “Managing a Data Source by Using Datasets.”
Just like an ordinary table, a DataTable object consists of rows and columns of data. Table 5-8 depicts the contents and difference between the components of a DataTable object. Table 5-8 Difference between the Components of a DataTable Object Component
Rows
Description
Contain the actual data in a DataTable object. Rows are represented by the class.
DataRow
Columns
Can contain data as available in the columns of a data source, calculated values, automatically incremental values, or Primary key values. Columns are represented by the DataColumn class.
The rows and columns present in a DataTable object are identical to those present in the original data source. In addition, the data in a DataTable object retains all relations within the table as in the data source.
117
101-144.qxd 2/24/03 10:37 AM Page 118
118
Project 1
DATABASE INTEGRATION WITH .NET
You can obtain information about a DataTable object by using the properties and methods available in DataTable and DataSet classes. For instance, you can access the entire set of columns in a DataTable object by using the Columns property of the DataTable class. In addition, you can access the collection of DataTable objects in a DataSet object by using the Tables property of the DataSet class. In a collection of DataTable objects, the names of DataTable objects are case- sensitive when multiple instances of the same name exist. When you search for a specific table in the DataTableCollection object, the search might return unexpected results based on the name of the DataTable object specified. Consider a case where the names of two DataTable objects, Table1 and table1, are the same, yet differ in the letter casing applied. In such a case, the search will return the results based on the actual search string and the matching letter casing. Therefore, a search in these cases is case-sensitive. However, when only one instance of a DataTable object name exists in a collection of DataTable objects, a search is not case-sensitive.
DataRowCollection The collection of all rows in a DataTable object constitutes the DataRowCollection object. Each row in a DataTable object is represented by a DataRow object. You can add a maximum of 16,777,216 rows to a DataTable object. You can add a row to the DataTable object by using the NewRow() method. This method returns a DataRow object that conforms to the schema of the DataTable object as defined in DataColumnCollection or collection of columns in a table. An important characteristic of a DataRow object is that the object tracks the changes made to its data. To track changes, DataRow maintains two versions of data, namely, the current version and the original version. You can determine if changes have been made to the data in DataTable by using data-related events supported by the DataTable class. Some of these events are listed in Table 5-9. Table 5-9 Events Supported by the DataTable Class Event
Description
RowChanged
Generated after a DataRow object has been successfully changed.
RowChanging
Generated when the data in a DataRow object is changing.
RowDeleting
Generated when a DataRow object is about to be deleted.
RowDeleted
Generated after a DataRow object has been deleted.
101-144.qxd 2/24/03 10:37 AM Page 119
INTRODUCTION TO ADO.NET
Chapter 5
A DataRow object can be used by the DataSet and DataView objects. An important property of the DataRow class is the RowState property. The RowState property displays information about how data in a row has been modified. The property can include values, such as Deleted, Modified, New, and Unchanged. The DataRow class provides methods that you can use to retrieve, calculate, and manipulate data in a row. The DataRowCollection class provides methods such as Add() and Remove() that you can use to add and remove a DataRow object from the collection of DataRow objects, respectively. The following code snippet in Visual Basic.NET adds a DataRow object. Dim rowcoll As DataRowCollection Dim newrow As DataRow Dim values(3) As Object ‘creates an array of four objects. rowcoll = newTable.Rows ‘where newTable is an existing table in a dataset. values(0) = “1048” ‘specifies data for the fields of the new row. values(1) = “Anita” values(2) = “2” values(3) = “5” newrow = rowcoll.Add(values) ‘adds the new row to the row collection.
The Contains() method of the DataRowCollection class allows you to search for words or phrases in character-based data. You can also locate a DataRow object with specific values in the primary key column by using the Find() method.
DataColumnCollection The DataColumnCollection class consists of a collection of DataColumn objects. An object of the DataColumnCollection class defines the structure of a DataTable object and determines the type of data in each column of a table. You can use properties of the DataColumnCollection class to obtain information about the DataColumnCollection object. Some properties of the DataColumnCollection class are listed in Table 5-10.
119
101-144.qxd 2/24/03 10:37 AM Page 120
120
Project 1
DATABASE INTEGRATION WITH .NET
Table 5-10 DataColumnCollection Class Properties Property
Description
Count
Determines the number of DataColumn objects in a DataColumnCollection object.
Item
Retrieves a specified DataColumn object from the collection of columns.
IsReadOnly
Determines whether the collection of DataColumn objects is read only.
In addition, you can add or remove DataColumn objects from the DataColumnColobject by using the Add() and Remove() methods, respectively. The following code snippet adds a column called column to a DataColumnCollection object.
lection
Dim column As DataColumn Dim columns As DataColumnCollection columns = instDataSet.Tables(“Titles”).Columns ‘obtains the column collection from the Titles table in instDataSet where instDataSet is a DataSet object. column = columns.Add() With column .DataType = System.Type.GetType(“System.String”) ‘where the GetType() method returns the type of the string specified. .ColumnName = “FullName” .Expression = “au_lname + au_fname” .ReadOnly = True .Unique = False End With
You can also determine whether a column belongs to a collection by using the Contains() method.
DataRelationCollection Relations between columns of DataTable objects in a DataSet object are stored in the DataRelationCollection object. Each relationship between DataTable objects is represented by a DataRelation object. The purpose of a DataRelation object is similar to that of a relation in a relational database, where relationships
101-144.qxd 2/24/03 10:37 AM Page 121
INTRODUCTION TO ADO.NET
Chapter 5
are created to help locate matching rows between two tables and other purposes, such as referential integrity. You can create parent-child relations between tables by using one or more related columns in the tables. In a parent-child relationship, for each column data in the parent table, there exists data in the child table. In other words, for each related column value in the parent table, there is a matching column value in the child table. In fact, the very first step in the creation of a relation is the verification that matching columns exist. If matching columns exist in the two DataTable objects, the relation is created between a parent and a child DataTable object. During the creation of relations, if the data in the parent or child rows is modified, an exception might be raised when the change in the data makes the relationship invalid. Later, the relationship is added to the DataRelationCollection object. After a parent-child relation is created, the DataRelationCollection object does not allow any changes to the data, which might invalidate the relationship. To do this, the DataRelationCollection object might create the ForeignKeyConstraint and UniqueKeyConstraint objects. These objects ensure data integrity by determining the action that will occur when a value in a parent table is deleted or updated. The DataRelationCollection class includes methods that you can use to manipulate the contents of the DataRelationCollection object. For instance, you can add and remove DataRelation objects from the collection by using the Add() and Remove() methods, respectively. The following code snippet displays the use of the Add() method to add a child relation called AuthorsRelation to the AuthorsTitle table. Dim AuthorsTitle As New DataTable() Dim author_name As DataColumn = AuthorsTitle.Columns.Add(“Column1”) Dim titlename As DataColumn = AuthorsTitle.Columns.Add(“Column2”) AuthorsTitle.ChildRelations.Add(“AuthorsRelation”, author_name, titlename)
You can also remove all the Clear() method.
DataRelation
objects in the collection by using the
Certain properties of the DataTable class can be used to obtain information about relations between DataTable objects. For instance, you can use the ChildRelations property to view the set of child relations for a particular DataTable object.
121
101-144.qxd 2/24/03 10:37 AM Page 122
122
Project 1
DATABASE INTEGRATION WITH .NET
You can view the list of parent relations for a particular DataTable object by using the ParentRelations property.
ConstraintCollection In a dataset, all the constraints on data are stored in the ConstraintCollection object. Constraints comprise of the UniqueConstraint and ForeignKeyConstraint objects. These objects are created automatically when a DataRelation object is added to the DataRelationCollection object. The UniqueConstraint and ForeignKeyConstraint objects ensure the integrity of data in a dataset. In other words, these objects ensure that changes to related columns do not invalidate a relationship between DataTable objects. A UniqueConstraint object validates the uniqueness of new values added to a column in a table. ForeignKeyConstraint determines the repercussions of any change to the primary key value in the parent table on the related child tables. The following code snippet displays the addition of a constraint to the authors table of the instDataSet object. instDataSet.Tables(“authors”).Constraints.Add(“primKeyConstraint”, instDataSet.Tables(“authors”).Columns(“au_id”), True) ‘adds a constraint named primKeyConstraint on the au_id column of the authors table. The True parameter indicates that the column is a primary key column.
You just looked at the components of the DataSet class. You will now learn about the two types of DataSet objects, typed and untyped.
Typed Datasets Typed datasets are classes that inherit from the DataSet class but are created using the information stored in XML Schema at design time. An XML Schema (.xsd file) is a document that defines and validates the content and structure of the XML data in a dataset. Therefore, whenever the .xsd file for a dataset is modified, the changes are reflected in the typed datasets as well. You will learn more about XML Schemas in Chapter 9, “Overview of XML.” A typed dataset inherits all the methods, events, and properties of the existing dataset class from which it derives. In addition, typed datasets incorporate table and column names into IntelliSense in Visual Studio Code Editor. This allows
101-144.qxd 2/24/03 10:37 AM Page 123
INTRODUCTION TO ADO.NET
Chapter 5
you to access specific tables and columns in the dataset by name. Additionally, the access to tables and columns in a typed dataset is determined at compile time. For instance, while working with a typed dataset, you can access a column by using the listed Visual Basic.NET code snippet. Dim stringdata As String stringdata = DatasetCustomersOrders1.Customers(0).CustomerID
The last line of the code snippet accesses the column called CustomerID from the first row of the Customers table of the DatasetCustomersOrders1 dataset. Using typed datasets reduces the time taken to access a column or a table. In addition, it facilitates programming by minimizing type mismatch errors and ensures easy readability of the code. You use the typed dataset to perform data manipulation and data binding.
Untyped Datasets Consider a scenario where the XML Schema for a DataSet object is unavailable, unknown, or dynamic. In such a scenario, the created datasets are referred to as untyped datasets. Untyped datasets do not have a corresponding XML Schema. In other words, an untyped dataset does not have an inherent structure. Further, an untyped dataset is not a class that you create using a schema, yet, untyped datasets provide you with the functionality of a dataset. Untyped datasets are generated by creating an instance of the DataSet class in a form or a component. At design time, an untyped dataset does not contain any data or XML Schema. However, at run time, when the dataset is populated with data, XML Schema can be generated for the untyped dataset. You can create the schema for an untyped dataset by using the Properties window. It is also possible to use the structure of an untyped dataset by exporting the structure to a schema file by using the WriteXmlSchema() method. An interesting aspect of untyped datasets is that the components of the dataset are available as collections. Therefore, in an untyped dataset, there exist collections, such as collections of DataTable objects and DataColumn objects. This also means that to access a specific dataset component, you need to iterate through the collection of the dataset component or refer to an item by name or index. For instance, to access the value of the column called au_id from the first row of the
123
101-144.qxd 2/24/03 10:37 AM Page 124
Project 1
DATABASE INTEGRATION WITH .NET
authors
table in the instDataSet untyped dataset in Visual Basic.NET, the code
is: Dim stringdata As String stringdata = instDataSet.Tables(“authors”).Rows(0).Item(“au_id”) ‘retrieves the value for au_id from the first row of the authors table.
You can access the collection of DataTable and DataColumn objects in an untyped dataset by using the Tables and Columns properties of the dataset, respectively.
AM FL Y
Now that you are familiar with the types of datasets, I will discuss the methods of creating datasets.
Creating Datasets
Visual Studio.NET provides a number of tools to create datasets. You can create datasets by using any of the listed methods. ◆ Component Designer. You use Component Designer to drag elements on a form or a component from the Toolbox or Server Explorer. You can create the components of a dataset, including the schema, by using Component Designer. This tool allows you to create both typed and untyped datasets.
TE
124
◆ XML Designer. You can use the XML Designer to create a schema. Later, you can use the schema to generate a typed dataset. You can also use this tool to edit XML Schema files. ◆ Creation through code. You can also create datasets dynamically through code. In such a case, the datasets created are of the untyped category. Now that you know about the methods of creating datasets, you will create an untyped dataset. An untyped dataset is always added to a form or a component. Listed below is the procedure to create an untyped dataset, called EmpDataset, by using the Component Designer while editing a form or a component. 1. Click on the Data tab of the Toolbox. Figure 5-5 displays the Visual Studio.NET window with the Data tab of the Toolbox clicked.
Team-Fly®
101-144.qxd 2/24/03 10:37 AM Page 125
INTRODUCTION TO ADO.NET
Chapter 5
FIGURE 5-5 The Visual Studio.NET window with the Data tab of the Toolbox clicked
2. Drag the DataSet control from the Toolbox onto the form. The Add Dataset dialog box is displayed. Figure 5-6 displays the Add Dataset dialog box.
FIGURE 5-6 The Add Dataset dialog box
125
101-144.qxd 2/24/03 10:37 AM Page 126
126
Project 1
DATABASE INTEGRATION WITH .NET
3. To create an untyped dataset, select Untyped dataset, and then click on the OK button. Figure 5-7 displays the Add Dataset dialog box with the Untyped dataset option selected. 4. A dataset is added to the form. To name the new dataset as EmpDataset, select the dataset and then double-click on the (Name) property in the Properties window. Figure 5-8 displays the Properties window with the (Name) property selected. 5. Type EmpDataset in the (Name) property in the Properties window, as shown in Figure 5-9.
FIGURE 5-7 The Add Dataset dialog box with the Untyped dataset option selected
FIGURE 5-8 The Properties window with the (Name) property selected
101-144.qxd 2/24/03 10:37 AM Page 127
INTRODUCTION TO ADO.NET
Chapter 5
FIGURE 5-9 The Properties window with the (Name) property modified
6. To avoid problems such as name duplicity or case sensitivity when the dataset is exported to an XML document, type EmpDataset in the DataSetName property. Figure 5-10 displays the Properties window with the modified DataSetName property.
FIGURE 5-10
The Properties window with the DataSetName property modified
After creating a dataset, you need to populate the dataset with data. You can use the following listed methods either in combination or independently to populate a dataset with data. ◆ Create the DataTable, DataRelation, and Constraint objects within the DataSet and fill DataTable objects with data. You can create DataRow objects and add them to the DataRowCollection object of the table.
127
101-144.qxd 2/24/03 10:37 AM Page 128
128
Project 1
DATABASE INTEGRATION WITH .NET ◆ Add tables from an existing RDBMS by using the Fill() method of a DataAdapter object. The following code snippet displays the use of the Fill() method to fill a DataSet object called instDataSet. Dim instOleDBDataAdapter as OleDbDataAdapter instOleDBDataAdapter = New OleDbDataAdapter(“select * from authors”, instOleDBConnection) ‘initializes instOleDBDataAdapter, where instOleDBConnection 'represents an open connection. instOleDBDataAdapter.Fill(instDataSet, “authors”) ‘populates instDataSet with data, where instDataSet is a 'DataSet object. The data added to the 'DataSet object is named authors.
◆ Add or persist data in the XML format by using an XML document or an XML stream. You will learn about the method to add data to a DataSet object in the XML format in the section “ADO.NET and XML.” ◆ Merge contents of another dataset. To merge a dataset to an existing dataset, you use the Merge() method. Typically, you use this method to merge changes from the data source with a DataSet object. The following code snippet displays the usage of the Merge() method to add the contents of newds to an existing dataset called ds. ds.Merge(newds, True) ‘merges the data from the newds with data in the ds object. 'The True parameter indicates that the 'changes made to ds should be retained.
Managing a Data Source by Using Datasets After a dataset is populated with data, the data can be viewed and modified. Later, the changes can be updated in the data source. You will now get an in-depth view of the actual process of data source management in a multitier system.
101-144.qxd 2/24/03 10:37 AM Page 129
INTRODUCTION TO ADO.NET
Chapter 5
Figure 5-11 displays a flowchart depicting the entire procedure of data source management in a multitier system. The explanation following the flowchart elaborates the procedure.
FIGURE 5-11
Flowchart depicting data source management in a multitier system
129
101-144.qxd 2/24/03 10:37 AM Page 130
130
Project 1
DATABASE INTEGRATION WITH .NET
As the first step, DataTable objects are created in the dataset. Subsequently, the DataTable objects are populated with data from the data source by using an SqlDataAdapter object or an OleDbDataAdapter object depending on the data source type. After filling a dataset, you can view the data stored in the dataset in the required form or order. For instance, you can sort the data available in a dataset based on either the columns in the table or a specified sorting expression. The sorting expression can consist of a column name or a value. To sort or filter the data in a dataset, you can use either of the listed methods: ◆ The Select() method of the DataTable class. This method displays a result set that consists of records extracted from the dataset fulfilling the criteria you specified. The Select() method retrieves a set of DataRow objects. Dim rows As DataRow() ‘declares an array of DataRow. rows = instDataSet.Tables(“authors”).Select(“city=’Oakland’”) ‘selects row(s) from the authors table to retrieve records 'of authors living in Oakland.
NOTE is an enumeration used to retrieve a specific data version from a object. You can also use the enumeration to determine the versions of data that exist in a DataRow object. DataViewRowState DataRow
◆ The DataView class. You can use the DataView class to create a customized view of the records in DataSet tables. A DataView object is analogous to views available in a database for viewing records in different ways. By default, a data view is always available for each table in a DataSet object. To access the default view for a table, you can use its DefaultView property. However, the default view is available only at run time. You can also set the properties for the DataView object at run time. In addition, you can create DataView objects at design time. Later, you can assign names to each data view and store the collection of the DataView objects in a DataViewManager object. You can also use the Row-
101-144.qxd 2/24/03 10:37 AM Page 131
INTRODUCTION TO ADO.NET
Chapter 5
property of DataView to filter the records in a table by specifying a filtering expression.
Filter
NOTE A DataViewManager object stores a collection of all the DataView objects in a DataSet object. The DataViewManager object provides a useful means of sorting records from related tables. For example, a DataSet object consists of two related tables, namely, Authors and Titles. On each of these tables, data views have been created. However, these data views will not display related records in a sorted order. To achieve sorted and filtered child records, you can use a DataViewManager object.
A filter expression is evaluated to gather records from the data stored in a dataset. Whenever the expression returns True for a record, the record is included in the result set. The following code snippet creates a DataView and sets the RowFilter property. Dim dvAuthorsInOakland As DataView = New DataView(instDataSet.Tables(“authors”)) dvAuthorsInOakland.RowFilter = “city = ‘Oakland’” dvAuthorsInOakland.Sort = “zip, address” ‘where the Sort property is used to sort the columns by zip and address. dvAuthorsInOakland.RowStateFilter = DataViewRowState.CurrentRows ‘where the RowStateFilter property filters the rows in the DataView based on the 'RowState values.
Earlier, I had discussed that each row maintains two versions of data, the original and the current data. You can filter data stored in a dataset based on the current or original records. You can also create a filter to return specific versions or states of the record(s). The data in each DataTable object can then be modified as required. During this modification, DataRow objects might be added, deleted, or updated. All these changes in the data are stored in a new DataSet object. Next, you perform an error check on the new DataSet object by examining the property of the DataSet object. The HasErrors property of DataSet reports an error in any row of any table of a DataSet object. The HasErrors property returns a Boolean value. The following code line indicates the usage of the HasErrors property. HasErrors
131
101-144.qxd 2/24/03 10:37 AM Page 132
132
Project 1
DATABASE INTEGRATION WITH .NET
If instDataSet.HasErrors then ‘where instDataSet is a DataSet object. ‘You can add code to trace the erroneous row. End If
If the DataSet reports an error, you need to examine the HasErrors property for each DataTable object. To detect the problem, you need to capture the DataRow objects with errors. For this purpose, you need to invoke the GetErrors() method of the DataTable object with errors. For instance, consider the use of the method as displayed in the following code snippet. Dim ErrorRows() As DataRow ErrorRows = dsTable.GetErrors() ‘where dsTable is a DataTable object.
The next step is to examine the error and rectify it. You can examine the error by using the RowError property. The following function accepts the dataset under observation as a parameter and writes the details of each error to the console. Private Sub prcPrintAllErrors(ByVal instDataSet As DataSet) Dim arrRowsHavingError() As DataRow Dim table As DataTable Dim intCtr As Integer Dim curCol As DataColumn For Each table In instDataSet.Tables ‘Test if the table has errors. If not, skip the table. If table.HasErrors Then ‘Get an array of all rows with errors. arrRowsHavingError = table.GetErrors() Console.WriteLine(“Report for table: “ & table.TableName) ‘Print the error of each column in each row. For intCtr = 0 To arrRowsHavingError.GetUpperBound(0) ‘Iterate through each column of current row. For Each curCol In table.Columns Console.WriteLine(curCol.ColumnName & arrRowsHavingError(intCtr).GetColumnError(curCol)) Next ‘Clear the row errors. arrRowsHavingError(intCtr).ClearErrors() Next intCtr
101-144.qxd 2/24/03 10:37 AM Page 133
INTRODUCTION TO ADO.NET
Chapter 5
End If Next End Sub
You can merge the contents of the new dataset with the original DataSet object. Next, you can use the original DataSet to update the changes in the data source. To update the data source, you invoke the Update() method of the DataAdapter, which might be SqlDataAdapter or OleDbDataAdapter depending upon the type of data source accessed. While updating the data source with the modified dataset, you need to pass the updated DataSet as an argument. To reflect the changes in the data source, you need to invoke the AcceptChanges() method on the data source. Optionally, you can reject the changes by using the RejectChanges() method.
Data Binding You can access and update data from a data source in real time by binding the controls in applications to data sources. ADO.NET allows you to bind controls on Windows Forms applications or Web Forms pages to data sources. In the subsequent sections, you will learn about data binding in Windows Forms and Web Forms.
Data Binding in Windows Forms Data binding of Windows Forms controls is employed for data presentation or manipulation. For instance, you use data binding to display and summarize your data in a printed document. Windows Forms allows you to access data not only from databases but also from other data sources, such as arrays and collections. For instance, you can bind controls in Windows Forms to an array of values that you calculate at run time or read from a file. The data source to which you bind Windows Forms controls must implement the IList interface or an interface that derives from IList, such as IBindingList. The IList interface allows you to access a homogeneous list of items by index. Some of the data sources that implement the IList interface and therefore qualify as a source for use in data binding to Windows Forms controls are discussed in the following list. ◆
Array or Collection.
An array or a collection that implements the IList interface can be used as a source for data binding.
133
101-144.qxd 2/24/03 10:37 AM Page 134
Project 1
DATABASE INTEGRATION WITH .NET ◆
You can bind controls to the data stored in a DataSet object. When you bind a control to a DataSet object, the control binds to the default DataViewManager object of the DataSet.
◆
DataTable object. You can bind a control, such as a DataGrid control, to a DataTable object. When you bind a control to a DataTable object, you bind to the default view of the table.
◆
DataColumn object.
You can bind a control, such as a TextBox control, to a column in a DataTable object.
◆
DataView object.
◆
DataViewManager object. You use a DataViewManager object to obtain a customized view of the data and relations in a DataSet object.
DataSet object.
AM FL Y
You can bind controls to the data in the DataView object. However, DataView only provides a snapshot of the original table. Therefore, any change made to the data source will not be automatically reflected by the DataView object at run time.
Data binding of controls in Windows Forms is of two types.
TE
134
◆ Simple binding. In simple binding, a control on a Windows Forms page binds to a single data element, such as a column value in a DataSet table. This type of binding is typically used for controls, such as TextBox or Label, which display only a single value. In addition, you can bind a property of a control to a column in a database. This means that you can set any run-time accessible property for a control through data binding. The following code snippet from a Visual Basic.NET application displays simple data binding of a TextBox control to a column in a DataTable object. Dim dtAuthors As DataTable dtAuthors = instDataSet.Tables(“authors”) ‘where instDataSet is a DataSet object. txtAuthorID.DataBindings.Add(“Text”, dtAuthors, “au_id”)
The last line of the code invokes the Add() method of the DataBindings class to bind data from the table to the TextBox control. ◆ Complex binding. In complex binding, a control can bind to more than one data element. Typically, in complex binding, controls bind to a dataset. For instance, a control on the Windows Forms page can bind to more than one record from a database or any other data element. Some Windows Forms controls that you can use for complex binding are Data-
Team-Fly®
101-144.qxd 2/24/03 10:37 AM Page 135
INTRODUCTION TO ADO.NET
Chapter 5
Grid, ComboBox, and ListBox. The following Visual Basic.NET application code snippet displays complex data binding of a ComboBox control to a column in a DataTable object. Dim dtAuthors As DataTable dtAuthors = instDataSet.Tables(“authors”) ‘where instDataSet is a DataSet object. ComboBox1.DataSource = dtAuthors ‘sets the data source of ComboBox1 as the dtAuthors table. ComboBox1.DisplayMember = “au_lname” ‘specifies that data from the au_lname column is to be 'displayed.
Data Binding in Web Forms Pages You can bind controls on Web Forms pages to any type of data source to display information. For instance, you can bind controls in Web Forms to the data in an XML document or the data stored in a database. The collection of all the data bindings for a control is represented by the ControlBindingsCollection class. The majority of Web Forms pages are used to display data from data sources. There are very few instances when a Web application is actually used to update a data source. For instance, a Web page that displays scores from a football match presents read-only data and does not update the data source. Therefore, to update the data source, you need to provide and implement the logic by using Web Forms pages. In Web Forms pages, you can bind any property of any control to the data in a data source. Therefore, you can bind a CheckBox control to a Boolean value and set the color, font, or size of the controls to single values. Data binding of Web Forms controls is of two types. The two types of data binding supported by Web Forms pages are: ◆ Single-value binding. This type of data binding occurs when you implement data binding for Web Forms controls that return a single value. Such controls are called single-value controls. Some examples of singlevalue controls are TextBox and Label. In single-value binding, you need to select the property to bind and specify the data value that is to act as the data source. For each individual property of a control in the Web Forms page, you can assign a single data value. For instance, you can
135
101-144.qxd 2/24/03 10:37 AM Page 136
136
Project 1
DATABASE INTEGRATION WITH .NET
bind the BackColor property of the DataList control to a single data value. You can also bind the Text property of a TextBox control to a data value. Similarly, you can bind a TextBox control to a value in a row returned by a data view. ◆ Multi-record binding. This type of data binding occurs when you bind multi-record controls to a data source. Multi-record controls display more than one data record at one instance. Some examples of multi-record Web Forms controls are Repeater, DataList, and DataGrid Web server controls. To bind multi-record controls, you specify the location from where the controls should pick data to be displayed. Therefore, you need to specify the data source, typically a dataset or a data member, such as a table or a column. To implement multi-record data binding, you need to bind a multi-record control to a data source that consists of multiple records. For instance, you can perform multi-record binding for a DataTable or collection object. In addition, to qualify as a data source for multi-record binding, the data source should implement the IEnumerable interface. Some structures that implement the IEnumerable interface are the DataView, DataRow, and DataTable objects. The implementation of the IEnumerable interface ensures that after binding a control with a data source, the data-bound control iterates through each item in the data source. The data-bound control can then perform the related action depending upon the nature of the control. While binding a control to the data in a dataset, tables, and data views, you can specify data binding properties for the controls at design time. For instance, at design time, you can use tools to bind a DataGrid control to a table in a dataset. At design time, you can bind the property of a control to a data value by using a data binding expression. A data-binding expression can reference a row in a table or in a data view or reference a property of another control. The expression contains information about the data that you want to bind to. The expression is resolved at run time and the resulting value is assigned to the property. The databinding expression is enclosed within the characters. For instance, to bind the TextBox control’s Text property to a DataTable object that contains a single record, the code in the HTML view would be:
101-144.qxd 2/24/03 10:37 AM Page 137
INTRODUCTION TO ADO.NET
Chapter 5
The preceding code snippet retrieves the “au_lname” column from the dataset called Authordataset and displays the content in the TextBox control called newTextBox. Alternatively, you can use the Properties window to create data-binding expressions. You can also create them on your own and enter them in the HTML view of the Web Forms designer. A data-binding expression can be resolved at run time by calling the DataBind() method. This method can be called for individual controls or for all the controls in a particular page. You can invoke the method when the page runs for the first time after the data source is populated or after the records in the data source are updated. You can also use the DataBinder class for binding. The DataBinder class allows you to bind controls with a table in a dataset or a data view that contains the record of your choice. The class is called by invoking the Eval() method of the class. The following code snippet displays the usage of the Eval() method of the DataBinder class.
In the preceding code snippet, the Eval() method takes two parameters. These are the data source and a reference to the value to be used. In design-time data binding, an instance of the data source, such as an instance of a dataset, exists on the Web Forms page. However, in certain cases, data binding at design time might not be possible. In other words, for data sources that instantiate only at run time, data binding also occurs at run time. For example, if an instance of the data source to which you want to bind a control is not available on the Web Forms page at design time, data binding is not feasible at design time. Such scenarios occur when you try binding controls to objects that are not instantiated until run time or when you bind controls to data that is returned by executing an SQL statement or a stored procedure in a database. In such cases, you need to bind data controls at run time. In the previous sections, you looked at data binding in Windows Forms and Web Forms and how data binding is used to display data from a data source. All data
137
101-144.qxd 2/24/03 10:37 AM Page 138
138
Project 1
DATABASE INTEGRATION WITH .NET
exchange during data binding is performed in the XML format. I will now discuss the built-in support for XML in ADO.NET.
ADO.NET and XML ADO.NET implements disconnected data architecture by using XML. But why XML? To understand what makes XML the preferred format, you need to know the advantages of using it. An important advantage of XML is that it is an industry standard format. XML facilitates data exchange between components of one application with any other data component of another application. In addition, XML is a text-based format. This implies that XML can be sent through any protocol, such as HTTP. Additionally, the exclusion of any binary information in XML also facilitates easy communication across networks by bypassing firewalls. Keeping the advantages of XML in mind, extensive support for XML has been built in ADO.NET. For instance, the two-way exchange of data between a dataset and a data source is performed using XML. Similarly, data exchange between the components of the ADO.NET architecture occurs through XML. To facilitate data exchange between the components of the ADO.NET architecture, the contents of DataSet are converted to XML files or streams by data APIs. This XML format is then sent to another component where data APIs can be used to convert the XML format to a DataSet object. You can populate a dataset with data from an XML source, such as an XML file or an XML stream of data.
NOTE The related conversion of the data in the XML format to and from a DataSet object is performed by Web services and ADO.NET. The transmission of data in the XML format allows non-ADO.NET clients access to the same services accessed by ADO.NET clients.
To populate a DataSet object with data from an XML source, you use the Readmethod of the DataSet object. The ReadXml() method takes two parameters. These are the source of the XML and the ReadMode parameter. The ReadMode
Xml()
101-144.qxd 2/24/03 10:37 AM Page 139
INTRODUCTION TO ADO.NET
Chapter 5
139
parameter is optional. The parameter reads the schema and loads the data and schema of a DataSet object. You specify a member of the XmlReadMode enumerator as a value for the parameter. XmlReadMode is an enumeration that specifies how XML data and a relational schema are read into a DataSet object. Some members of the enumerator are XmlReadMode.Auto and XmlReadMode.DiffGram. ReadXml(“source of XML”, ReadMode argument)
The following code snippet of a Visual Basic.NET application displays the usage of the ReadXml() method to load a dataset from an XML file called input.xml.
ENUMERATION An enumeration is a value type that provides alternate names for underlying values. Each enumeration type has a name, type, and a set of fields.
Dim newDS As DataSet = New DataSet ‘DataSet object is declared. newDS.ReadXml(“input.xml”, XmlReadMode.ReadSchema) ‘ReadXml is invoked for the DataSet object.
I will now discuss the parameters specified in the code snippet of the Visual Basic.NET application. In the code snippet, “input.xml” is the name of the XML file from which the DataSet object called newDS will be populated. A DataSet object can also be populated by an XmlReader object. XmlReader is a class that allows you to access XML data in a forward-only sequence. The class also facilitates a noncached access to the XML data. “XmlReadMode.ReadSchema”
is the ReadMode parameter.
As discussed earlier, a dataset comprises data and schema. An XML document or an XML stream can act as the source of data or schema information or both. The information from an XML document or stream can also be combined with the existing data or schema information of a DataSet object. However, when combining data with an existing DataSet from an XML source, any row information with matching primary key values will not be added to the existing DataSet. When you load a DataSet object by using XML, the schema of the DataSet object can be predefined, or created either explicitly or through inference, from the XML being loaded. When the schema of a DataSet object is created from XML, the preferred method of creation is to explicitly specify the schema by using either the XML Schema Definition (XSD) language or XML-Data Reduced (XDR). In the absence of an XML Schema or XDR schema in XML, the schema of the DataSet
101-144.qxd 2/24/03 10:37 AM Page 140
140
Project 1
DATABASE INTEGRATION WITH .NET
object can be inferred from the structure of the XML elements and attributes in the XML source. Additionally, it is possible to write the data of a dataset as World Wide Web Consortium (W3C)-compliant XML and the DataSet schema as XSD Schema. Irrespective of the data source, you can write datasets in W3C-compliant XML. When a dataset is written as XML, only the current version of the rows is used. You can write both the current and the original version of the row data by using the DiffGram format.
NOTE DiffGram is an XML format that is used to read and write the contents of a DataSet object. You can also use the DiffGram format to identify the current and the original versions of data elements. This format also serializes dataset contents to enable transfer of data across network connections. The DiffGram format can also be implemented by other platforms to facilitate the exchange of information with a .NET Framework application. This format is used implicitly when a DataSet object needs to be sent or retrieved from an XML Web service. DiffGram is used by datasets to load and persist its contents. To accurately recreate a dataset, the dataset writes DiffGrams with all the necessary information, including the current and original column values, the row error information, and row order. You can also read or write the contents of a dataset in the DiffGram format when loading the contents from XML by using the ReadXml method or when writing the contents by using the WriteXml method.
You can represent a DataSet object in the XML format with or without the schema. If the schema is written as XML, it is written using XSD. The data and the schema are read and written by a DataSet object as XML documents. You can write the XML representation of a DataSet object to a file, a stream, an XmlWriter, or a string. Similarly, you can write an XML Schema to a file, a stream, an XmlWriter, or a string. The XML Schema saved in these formats can be used to create a strongly typed DataSet. This ability to write data and dataset schema as XML allows a dataset to be transported across HTTP for use by other applications or the XML-enabled platform. Additionally, the serialization format of XML for datasets facilitates the transfer of data in a dataset between tiers of an application. This capability also facilitates the exchange of data and schema context to and from an XML Web service.
101-144.qxd 2/24/03 10:37 AM Page 141
INTRODUCTION TO ADO.NET
Chapter 5
NOTE The XmlWriter class is used to generate XML streams or files. The class writes XML data as streams or files by implementing a noncached and forward-only sequence.
You can transport a DataSet schema with or without data in an XML document. To exclusively transport the schema of a dataset, you can use an .xsd file. To ensure deeper XML integration with a dataset, the DataSet class includes methods that facilitate working with XML. Table 5-11 lists some of the XMLrelated DataSet methods. Table 5-11 XML-Related DataSet Methods Method
Description
WriteXmlSchema
Saves the DataSet schema as an XML Schema in a file, a stream, or XmlWriter.
WriteXml
Saves data and optionally the schema of a DataSet object as an XML file, an XML stream, or XmlWriter.
ReadXmlSchema
Loads or infers schema information from the document containing the XSD Schema or an XML document with inline XML Schema. Does not load data.
ReadXml
Creates a schema from an XML document to read an XML document that includes both the schema and the data.
InferXmlSchema
Infers the schema from the XML document while ignoring the specified XML namespaces. You need to specify the namespaces to be ignored while calling the method.
The following code snippet from a Visual Basic.NET application displays the usage of the ReadXmlSchema() method to load the schema information from the document “schema.xsd”. Dim newDS As DataSet = New DataSet newDS.ReadXmlSchema(“schema.xsd”)
141
101-144.qxd 2/24/03 10:37 AM Page 142
142
Project 1
DATABASE INTEGRATION WITH .NET
Similarly, to write the data and schema of a DataSet object to an XML file called “Customers.xml”, the code snippet is as follows: newDS.WriteXml(“Customers.xml”, XmlWriteMode.WriteSchema) ‘XmlWriteMode.WriteSchema is the XmlWriteMode parameter.
The XmlWriteMode enumeration specifies how data and schema should be written from a DataSet object. The entire structure of a DataSet object is defined using an XML Schema. This structure defines the tables, columns, data types, and constraints in the DataSet object. The structure of a DataSet object can be loaded and serialized as XSD Schema. XSD Schemas are generated and updated by Visual Studio.NET automatically. However, you can create or edit schemas manually. In such cases, it might be necessary to map the schema elements to the structure of the source database. Datasets provide you with a relational representation of data. The XML classes available in the .NET Framework provide you with hierarchical data access. You can access both these data representations synchronously and in real time through the DataSet object and the XmlDataDocument object, respectively. The XmlDataDocument class facilitates the storage, retrieval, and manipulation of structured data through a dataset. The XmlDataDocument class unites ADO.NET and XML by representing relational data from a DataSet object and synchronizing the data with the XML document model. You can provide both relational as well as hierarchical access to data in real time by synchronizing a DataSet object with an XMLDataDocument object. In such a situation, both DataSet and XMLDataDocument objects use a single set of data. In other words, whenever the DataSet object is changed, the change will be reflected in the XmlDataDocument object and vice versa. A synchronized relationship between DataSet and XmlDataDocument objects facilitates a single application to access the suite of XML services and all the services built using DataSet. To synchronize a DataSet object with an XmlDataDocument, you can populate a DataSet object with schema and data and then synchronize the DataSet object with a new XmlDataDocument. This provides you with a hierarchical view of the relational data. Consider the following code: Dim Doc As XmlDataDocument = New XmlDataDocument(newDataSet) ‘where newDataSet is a DataSet object.
101-144.qxd 2/24/03 10:37 AM Page 143
INTRODUCTION TO ADO.NET
Chapter 5
In the code, Doc is declared as XmlDataDocument. The XmlDataDocument constructor uses newDataSet, which is a DataSet object, to initialize the XmlDataDocument object called Doc. In the hierarchical data representation, the parent-child relationships are represented by parent elements that contain nested child elements. When a DataSet object is synchronized with an XmlDataDocument object or written as XML data by using WriteXml(), you can set the Nested property of the DataRelation class to True to facilitate nesting of child objects. The Nested property nests all the child rows of a parent-child relationship within the related parent column when a DataSet is written as XML data or synchronized with an XmlDataDocument.
Summary In this chapter, you learned that ADO.NET is a .NET Framework-compliant technology that provides data access services to .NET programmers. ADO.NET supports a disconnected data architecture that allows you to manage data in n-tier systems or distributed applications and in client applications, such as Windows Forms. The main components of the ADO.NET architecture are: ◆ .NET data provider. You use .NET data provider to access data. ◆ Dataset. You use datasets to manipulate data. To provide a link between a data source and an application, .NET data provider uses four core components. These are: ◆ The Connection object ◆ The Command object ◆ The DataReader object ◆ The DataAdapter object .NET data providers facilitate interaction with different data sources, such as SQL Server databases and OLE DB databases. To accomplish this, the .NET Framework includes three different types of .NET data providers. These are: ◆ SQL Server .NET data provider. You use the SQL Server .NET data provider to access an SQL Server 7.0 or later database. ◆ OLE DB .NET data provider. You use the OLE DB .NET data provider to access OLE DB data sources.
143
101-144.qxd 2/24/03 10:37 AM Page 144
Project 1
DATABASE INTEGRATION WITH .NET ◆ ODBC .NET data provider. You can use the ODBC .NET data provider to access ODBC-compliant data sources.
A DataSet object comprises components such as DataTableCollection, DataRowCollection, DataColumnCollection, and DataRelationCollection. In addition, the .NET Framework provides two different types of datasets. These are: ◆ Typed datasets. Typed datasets are classes that inherit from the DataSet class but are created using the information stored in XML Schema.
AM FL Y
◆ Untyped datasets. Untyped datasets are datasets that do not have a corresponding predefined XML Schema. ADO.NET allows you to bind controls in Windows Forms applications or Web Forms pages to data sources to allow data access and any associated manipulation. A data source to which you can bind Windows Forms controls must implement the IList interface or an interface that derives from IList, such as IBindingList. Similarly, to qualify as a data source for a multi-record Web Forms control, the data source should implement the IEnumerable interface.
TE
144
Finally, you learned that ADO.NET supports XML extensively through datasets. The close integration of XML with ADO.NET allows datasets to be transported across HTTP for use by another application or the XML-enabled platform.
Team-Fly®
145-222.qxd 2/24/03 10:45 AM Page 145
Chapter 6 Creating a Windows Application in Visual Basic Using ADO.NET to Implement Database Connectivity
145-222.qxd 2/24/03 10:45 AM Page 146
n Chapter 5, “Introduction to ADO.NET,” you examined the components of the ADO.NET architecture. You also looked at the concept of data binding and the support for XML in ADO.NET. In this chapter, you will use the concepts learned in Chapter 5 to create an application that establishes connectivity with a database by using ADO.NET. The application will also allow users to modify records from a table in an SQL database. In addition, the application will generate a report and XML files from the report data.
I
In this chapter, you will look at the case study and the different phases in the lifecycle of the application to generate report and update records. In addition, you will learn about the steps to create the required application in detail.
Project Case Study You might recollect from the case study that the management at TecPublishers performs semiannual as well as annual reviews of the business conducted at each branch office. Apart from the profits generated by each branch office, the management reviews the titles published and the sales per title. Each branch office is required to generate reports and send the data to the head office. Some of the reports include publications per business year, titles published, and titles written by each author. You might also recollect from Chapter 4 that the branch offices maintain records related to entities such as publishers, titles, and authors. There is a frequent requirement to update the records related to these entities to reflect changes in the details of the entities. To meet such a requirement, the management has identified the need for a module that allows the employees at each branch office to update the details when required. The modifications done at various offices need to be reflected in all database servers located at other branch offices, including the head office. Therefore, to synchronize the data exchange between branch offices and the head office, techniques such as database publishing and horizontal database partitioning of SQL Servers at various locations are used.
145-222.qxd 2/24/03 10:45 AM Page 147
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
To accomplish the tasks of displaying data in a report format and allowing data modification, a group of programmers has been hired. As part of the project development team, you will create an application to generate a report for TecPublishers called the Authors and Titles report and update the records in an SQL database. However, before you begin, you need to look at each phase of the lifecycle of the project as decided by the team of programmers. The subsequent sections discuss the different phases of the project lifecycle.
Project Lifecycle The project lifecycle for the application to generate a report and update records comprises the following phases: ◆ Requirements analysis ◆ Design ◆ Construction ◆ Testing While the testing phase of this project is similar to the testing phase of the remaining projects in the book, the rest of the phases vary. I will discuss only the phases that vary with respect to the application to be developed in this project.
Requirements Analysis In the requirements analysis phase, the programmers interviewed the publishers of the various branch offices and the officials at the head office. In addition, the programmers analyzed a few sample reports from other branch offices to extrapolate the exact requirements of the project. The programmers also analyzed the various entities to be maintained and the ways in which data needs to be modified. From its discussions and analysis, the team identified that a report needs to be generated to display data from the database that stores the relevant data. The team also identified that each branch office needs to maintain and update data related to publishers, authors, discounts, sales, stores, and titles. Another important conclusion that the team arrived at was that the modification of author details is the most frequently performed task. As a result, this functionality needs to be created and rolled out on a priority basis.
147
145-222.qxd 2/24/03 10:45 AM Page 148
148
Project 1
DATABASE INTEGRATION WITH .NET
Additionally, the team concluded from its interview with the publisher that only the publisher views the report. This implied that the report need not be shared with the remaining employees at the branch office. In addition, the application will be implemented by the branch offices locally. Therefore, the functionality provided by the application need not be incorporated in the Web site of TecPublishers. At the end of its analysis, the team documented the list of requirements for the project as follows: ◆ The data to be displayed and modified needs to be accessed from the Pubs database of the SQL Server at a branch office. ◆ The user should be able to select the author from a list. The corresponding author ID should be shown to the user to confirm that the details are being modified for the intended author only. ◆ The user should be able to view and modify the details of an existing author. ◆ The report is to be created as a Windows application. ◆ The report is to display authors’ names and book titles in a tabular format. ◆ The report is to be sent to the head office. The team also identified that not all branch offices use SQL Server 7 or later versions. Some branch offices use earlier versions of SQL Server. Therefore, SQL Server .NET data provider will not be used. Instead, OLEDB .NET data provider will be used to ensure that the application works in all offices.
NOTE Although each branch office needs to generate a number of reports, the focus of the current project is a report that displays the authors’ names and the titles written by the authors. Reports that display other types of data can be created on similar lines. In addition, for the sake of simplicity, emphasis on an elaborate and complex format or data retrieval has been overlooked. Similarly, each branch office maintains and updates the details of many entities. However, the focus of the current project is to create an application that allows the modification of author details only. Forms that allow the modification of other types of entities can be created on similar lines.
145-222.qxd 2/24/03 10:45 AM Page 149
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Design After the requirements for the project had been analyzed, the team decided upon the functionality and the final output of the application. In addition, different aspects of the application to be developed, such as interface, were also decided. Based on the decisions reached, the following functional implementations were decided: ◆ The Entity Details Maintenance form ◆ The Titles Authored by Each Author form ◆ The Author Details Modification form In the subsequent sections, I will discuss the forms in the application.
The Entity Details Maintenance Form The Entity Details Maintenance form is the main Multiple-Document Interface (MDI) form. This is the first form to be displayed when the application is invoked. The Entity Details Maintenance form consists of the Modify, Reports, and Exit menu. When a user clicks on the Modify menu, two menu commands are displayed, as shown in Figure 6-1. In the current context, the details related to authors only are discussed. You might require additional forms with similar functionality to modify details of other entities, such as sales data, and publishers. Keeping this consideration in mind, the more command has been added to the Modify menu of the Entity Details Maintenance form.
FIGURE 6-1 The menu commands on the Modify menu
149
145-222.qxd 2/24/03 10:45 AM Page 150
150
Project 1
DATABASE INTEGRATION WITH .NET
The Reports menu enables you to view reports. The Reports menu lists the reports available for users to select. When a user clicks on the Reports menu, two commands as shown in Figure 6-2 are displayed. The Title IDs by Author command of the Reports menu can be selected by the user for the report on authors and their titles. The More reports command can be used to add additional reports to the module. When a user selects the Title IDs by Author command, a set of commands as displayed in Figure 6-3 is shown. All menu commands except the Show Report command are disabled. I will now discuss the functionality of each of these commands. ◆ The Show Report command. The Show Report command displays the data for the Author and Titles report from the tables in the Pubs database of the SQL Server. When the Show Report command is selected, the remaining commands on the Title IDs by Author menu are enabled. ◆ The Write XML command. The Write XML command saves the report data as an XML file. ◆ The Write XML Schema command. The Write XML Schema command saves the structure of the report data as a file in the .xsd format. ◆ The Write XML with Schema command. The Write XML with Schema command saves the data and its related structure as an XML file. The Exit menu is used to close the application.
FIGURE 6-2 The menu commands on the Reports menu
145-222.qxd 2/24/03 10:45 AM Page 151
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
FIGURE 6-3 The menu commands on the Reports menu
The Author Details Modification Form When the Author Details command is selected from the Modify menu on the Entity Details Maintenance form, the Author Details Modification form as shown in Figure 6-4 is displayed.
FIGURE 6-4 The Author Details Modification form
151
145-222.qxd 2/24/03 10:45 AM Page 152
152
Project 1
DATABASE INTEGRATION WITH .NET
The Author Details Modification form displays a list of all authors associated with TecPublishers and their associated details. Users can modify the details of an author by selecting the author from the displayed list. As displayed in Figure 6-4, the form consists of controls that allow a user to edit the details of an author. To edit the details of an author, the user needs to select the author name from the drop-down list and then click on the Modify button. On clicking on the Modify button, all editable fields are enabled. Figure 6-5 displays the Author Details Modification form after the ton is clicked on. You can save the changes made by clicking the cancel the changes.
Save
Modify
but-
button. Optionally, you can
The development team also identified the fields to be displayed and the fields that can be modified. For instance, a user can view the author ID, but cannot modify the value displayed in the ID field. Therefore, it becomes essential to differentiate between the two sets of fields, namely, editable fields and non-editable fields. The following list displays the editable as well as the non-editable fields on the Author Details Modification form.
FIGURE 6-5 The Author Details Modification form after clicking on the Modify button
145-222.qxd 2/24/03 10:45 AM Page 153
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
153
◆ ID (non-editable) ◆ Last Name ◆ First Name ◆ Phone ◆ Address ◆ City ◆ State ◆ Zip ◆ Contract When the Author Details Modification form is displayed, the Author Details command of the Modify menu is disabled. Figure 6-6 displays the disabled Author Details command when the Author Details Modification form is displayed.
The Titles Authored by Each Author Form The Titles Authored by Each Author form of the application is displayed when a user selects the Show Report command from the Title IDs by Author menu. The
FIGURE 6-6 Disabled Author Details command when the Author Details Modification form is displayed
145-222.qxd 2/24/03 10:45 AM Page 154
Project 1
DATABASE INTEGRATION WITH .NET
Titles Authored by Each Author form displays the data of the report. As this project focuses on the report on titles written by authors, the development team decided upon the following fields to be displayed on the main form: ◆ Author ID ◆ Author Name ◆ Title ID ◆ Title Name
AM FL Y
Figure 6-7 displays the Titles Authored by Each Author form. While the Titles Authored by Each Author form is displayed, the Show Report menu is disabled. The remaining commands on the Title IDs by Author menu are enabled. Figure 6-8 shows the disabled Show Report menu when the Titles Authored by Each Author form is displayed. When a user selects the Title IDs by Author menu, the Author Details menu on the Modify menu might be disabled. The Author Details menu is disabled when a user chooses to display the Author Details Modification form before viewing a report. However, when the user selects the Show Report menu before viewing the Author Details Modification form, the Author Details menu is enabled.
TE
154
FIGURE 6-7 The Titles Authored by Each Author form
Team-Fly®
145-222.qxd 2/24/03 10:45 AM Page 155
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
FIGURE 6-8 The disabled Show Report menu in the Titles Authored by Each Author form
As the next step, a detailed design for the application was created. Keeping the requirements in mind, the team decided upon the technologies to be used for each functionality of the application. Table 6-1 lists the functionality and its corresponding technological implementation. Table 6-1 Technological Implementation of Functionalities Functionality
Technological Implementation
Data source
SQL Server 2000
Tool to create application
Visual Studio.NET
.NET language for coding
Visual Basic.NET
Data access
ADO.NET
Data updating
Parameterized SQL command
Report data storage
XML
155
145-222.qxd 2/24/03 10:45 AM Page 156
156
Project 1
DATABASE INTEGRATION WITH .NET
In addition, the team determined all programming-related conventions and specifications related to the names of the objects, functions, variables to be used, and other such details about the application. The naming conventions as decided by the team for use in the construction of the report module are listed in Table 6-2. Table 6-2 Naming Conventions Item
Instances of control
Convention
First three letters to indicate the type of control, example indicates a menu item
mnuTIDbyAuth
Class
First three letters to indicate the type of class, example indicates a Form class
frmReports
Class instances
inst followed by the name of the class; example indicates an instance of the OleDBConnection class instOleDBConnection
XML file with data
XMLData
XML file with data and schema
XMLData_with_Schema
XML file with schema
XMLSchema
Now that you are familiar with the design of the application to be created, I will proceed with the steps to create the application.
Construction Based on the blueprint created in the design phase, the team of programmers began creating the application. The steps to create the application are: 1. Create new project 2. Create the Titles Authored by Each Author form 3. Create the Author Details Modification form 4. Create the Entity Details Maintenance form 5. Set the Startup Object property for the project You will now learn about each step in detail.
145-222.qxd 2/24/03 10:45 AM Page 157
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Create New Project Before I begin discussing the creation of the project, it is important to understand the difference between the concepts of a project and a solution in Visual Studio.NET. You were briefly introduced to the concepts of a project and a solution in Chapter 2, “The .NET Family.” While developing an application in Visual Studio.NET, you require multiple components such as data connection, folders, and files. You can manage and store all related components by using the containers provided by Visual Studio.NET. The two containers available in Visual Studio.NET are: ◆ Projects. Projects allow you to organize, create, and debug the components of an application. A project might simply consist of components such as a single form or HTML document, classes, and a project file. Additionally, components such as database scripts, stored procedures, and a reference to an existing Web service might also be stored in a project. Typically, the output of a project is an .exe file, a .dll file, or a module. ◆ Solutions. Solutions comprise multiple projects. A solution includes all the components that are not dependent on any specific project, but are referenced by multiple projects. Apart from providing a common location for all related components of an application, Visual Studio.NET containers also allow you to perform common tasks on the components, such as applying common settings. The following list provides some benefits of using Visual Studio.NET containers. ◆ Easy management of related components. A single location for all related components allows you to manage and apply the same settings for an entire group of components. For instance, you can manage the settings for individual projects within a solution. Additionally, certain components might be required by a set of projects in the solution or the entire solution as such. You can add such components to the solution or projects without referencing the components in each project. ◆ Centralized file management. The file management in containers is handled by the Solution Explorer. The Solution Explorer allows you to view and manage containers and the associated components of containers. Figure 6-9 displays the Solution Explorer listing the components of an application called prjUntypedDatasetApplication.
157
145-222.qxd 2/24/03 10:45 AM Page 158
158
Project 1
DATABASE INTEGRATION WITH .NET
FIGURE 6-9 The Solution Explorer window
NOTE You can store all the components and files, such as project design documents, that are relevant and applicable to a solution in the Solution Items folder of the Solution Explorer. The files or components of an application that are not contained in a project or solution are known as miscellaneous files. Miscellaneous files are stored outside a container in a Miscellaneous File folder.
Now that you are familiar with the difference between a project and solution, I will discuss the steps to create a new project. As per requirements stated earlier, you need to create the report by using the Windows application template. You can create a Windows application by using any .NET language ranging from Visual Basic.NET and Visual C++.NET to Visual C#. In keeping with Chapter 5, “Introduction to ADO.NET,” that discusses code and property references with respect to Visual Basic.NET, I will discuss the steps to create a Windows application in Visual Basic.NET. To create a new Windows application project in Visual Basic.NET called prjDBConnect, you need to perform the following steps.
145-222.qxd 2/24/03 10:45 AM Page 159
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
As per the requirements stated earlier, the application needs to be created as a Windows application. To create a new Windows application project, you need to perform the following steps: 1. Click on the File menu and choose New, then Project to create a new project. Figure 6-10 displays the selected Project command. 2. Figure 6-11 displays the New Project dialog box obtained after clicking the required menu commands.
FIGURE 6-10
Selected Project command on the File menu
FIGURE 6-11
The New Project dialog box
159
145-222.qxd 2/24/03 10:45 AM Page 160
160
Project 1
DATABASE INTEGRATION WITH .NET
TIP An alternate way to access the New Project dialog box is to click on the Ctrl, Shift, and N keys simultaneously. You can also access the New Project dialog box by clicking on the New Project button that appears on the Start Page.
3. To create a project in Visual Basic.NET, you need to select the Visual Basic Projects option from the Project Types pane. By default, this option is selected. 4. The Templates pane displays the list of project templates available for Visual Basic Projects. To create a Windows-based application in Visual Basic.NET, you need to select the Windows Application option from the Templates pane, as shown in Figure 6-12. 5. To name the project, type prjDBConnect in the Name text box. 6. Next, to accept the default location for saving the project, click on the OK button. By default, the new project will be created in the following location: C:\Documents and Settings\admin\My Documents\Visual Studio Projects. Figure 6-13 displays the dialog box with the name prjDBConnect for the application to be stored in the default location.
FIGURE 6-12
The selected Windows Application option from the Templates pane
145-222.qxd 2/24/03 10:45 AM Page 161
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
FIGURE 6-13
Chapter 6
The New Project dialog box displaying the name and default location for creating the project called prjDBConnect
Upon clicking on the OK button, the Visual Studio.NET window displays a new project with a blank form in design mode. Figure 6-14 displays the Visual Studio.NET window after the project prjDBConnect is created.
FIGURE 6-14
The Visual Studio.NET window after the project prjDBConnect is created
161
145-222.qxd 2/24/03 10:45 AM Page 162
162
Project 1
DATABASE INTEGRATION WITH .NET
Visual Studio.NET creates a Windows form that you can customize based on your requirements. The new project provides the basic functionality, such as an empty Windows form, required to create a Windows application in Visual Basic.NET. You can now use the project to create the user interface for the report application. The title bar of the Visual Studio.NET window displays the name of the project and the default name of the form. By default, the name of the form is Form1. In addition, a solution is created automatically when you create the new project. The corresponding solution for the project called slnDBConnect is created automatically. Now, you need to create the forms in your application.
Create the Titles Authored by Each Author Form As decided in the requirements phase, the Titles Authored by Each Author form will consist of a tabular format. The steps to be performed to create the Titles Authored by Each Author form are listed. 1. Rename the form as frmTitleByAuthor by modifying the Name property. 2. Change the Text property of the form to Titles Authored by Each Author. Figure 6-15 displays the Properties window with the modified values of the Name and Text properties. 3. Increase the display area of the form to ensure that all the columns with the required data are displayed in the Authors and Titles report. 4. After resizing the form to the desired width and height, you need to place controls on the form. To display data in a tabular format, you need
FIGURE 6-15
The Properties window with modified Name and Text properties
145-222.qxd 2/24/03 10:45 AM Page 163
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
to add a ListView control and rename it as lvReport. The ListView control includes grid lines to display data in rows and columns. Next, you need to resize the lvReport control to cover a large area of the form in the background and display report data with ease. By default, as displayed in Figure 6-16, the lvReport control does not display any rows or columns. Therefore, to display rows and columns in the lvReport control, you need to set the GridLines property of the control to True. To accomplish this task, you can double-click on the GridLines property in the Properties window. Figure 6-17 displays the GridLines property set to True.
FIGURE 6-16
The default display of the lvReport control
FIGURE 6-17
Properties window displaying the GridLines property as True
163
145-222.qxd 2/24/03 10:45 AM Page 164
Project 1
DATABASE INTEGRATION WITH .NET
TIP Alternately, you can click on the GridLines property, and then select the True option from the drop-down list.
Next, you need to add headers to the columns. To add column headers to the lvReport control, you need to perform the following steps:
AM FL Y
1. Click on the Columns property in the Properties window. Figure 6-18 displays the Columns property. 2. Select the Columns property, and then click on the Ellipsis button. 3. The ColumnHeader Collection Editor dialog box is displayed. You use this dialog box to add or remove columns to a ListView control and view or modify the properties of the columns. Figure 6-19 displays the dialog box. 4. To add a column to the lvReport control, click on the Add button. By default, the name of the column header is ColumnHeader1. The properties of the newly added column header are displayed in the adjoining pane.
TE
164
5. You need to specify the text that is displayed as the column header in the Authors and Titles report. To change the display name of the column header to Author ID, you need to double-click on the Text property under the Misc set of properties. Figure 6-20 displays the dialog box with the modified Text property.
FIGURE 6-18
Properties window displaying the Columns property
Team-Fly®
145-222.qxd 2/24/03 10:45 AM Page 165
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
FIGURE 6-19
The ColumnHeader Collection Editor dialog box
FIGURE 6-20
The ColumnHeader Collection Editor dialog box with the modified Text property
165
145-222.qxd 2/24/03 10:45 AM Page 166
166
Project 1
DATABASE INTEGRATION WITH .NET
6. Similarly, you can add multiple columns to the ListView control and name the columns appropriately, as decided in the requirements phase, by repeating Steps 4 and 5. After adding the required columns, you need to click on the OK button. 7. Next, you need to set the View property to Details. Figure 6-21 displays the Properties window with the View property set to Details. After the grid lines and the columns are added to the Windows form, the form will be displayed as shown in Figure 6-22. After the required controls are added to the main form and appropriately named, you need to specify the code for the appropriate events of the controls. The Windows Forms Designer generates the basic skeleton of the procedures related to the default events of the controls placed on the form. You will now look at the code that you need to specify in addition to the code that is generated by default. To learn more about the code that is generated by default by the Windows Forms Designer, refer to Appendix F, “Windows Forms Designer Generated Code.” The procedures for which you need to specify code for the Titles Authored by Each Author form are listed. ◆
prcTIDbyAuthShow
◆
prcTIDbyAuthWriteXML
◆
prcTIDbyAuthWriteXMLSchema
◆
prcTIDbyAuthWriteXMLWithSchema
◆
frmTitleByAuthor_Load
I will now discuss the procedures to be created for the form.
FIGURE 6-21
The Properties window with the View property set to Details
145-222.qxd 2/24/03 10:45 AM Page 167
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
FIGURE 6-22
Chapter 6
Windows form after the columns and their respective headers are added
The prcTIDbyAuthShow Procedure This prcTIDbyAuthShow procedure displays the Authors and Titles report by displaying data from the Pubs database located on the SQL Server called webserver. Therefore, the first task to be performed is the creation of a connection with the SQL Server database. To establish the connection with the Pubs database on web-server, you need to specify the following code: strConnectionString = “Provider=SQLOLEDB.1;Data Source=web-server;USER ID=sa;pwd=;Initial Catalog=Pubs” instOleDBConnection = New OleDbConnection(strConnectionString)
This code uses a string to establish a connection with the SQL Server called webstring contains the required parameters, such as the type of provider, name of the SQL Server, user name, password, and the name of the database to use. You will need to change the server name to the name of the SQL Server that you are using.
server. The
Next, you need to populate the DataSet object with the required data from the Pubs database. For this purpose, you use the DataAdapter object. The Authors and Titles report displays data from the authors, titles, and titleauthor tables of the Pubs database. Therefore, you need to add data from the respective tables to the
167
145-222.qxd 2/24/03 10:45 AM Page 168
168
Project 1
DATABASE INTEGRATION WITH .NET
DataAdapter object by executing the relevant SELECT statements. Since one author can write either none or more titles, you also need to establish a parentchild relationship that is represented by parent elements that contain nested child elements.
The following code displays the transfer of data from the required tables to the DataAdapter object and the nesting of child elements. You will set the Nested property of the relation to True to ensure that all the child rows of a parent-child relationship are nested within the related parent column when instDataSet is written as XML data. ‘ the OleDbDataAdapter is instantiated with System.Data.OleDb.OleDbCommand, which is an SQL query, and the second parameter is system.data.oledbconnection which is the connection object instantiated above. instOleDBDataAdapter = New OleDbDataAdapter(“select * from authors”, instOleDBConnection)
‘ following code starts in a try block to trap any errors while accessing data. Try ‘ start filling desired data into dataset. Here instDataSet is the dataset which will hold the result set. “authors” is the name given to the result set data in the Dataset. we can choose any name for the table within the dataset. this can be any name that you want to use as a reference for this resultset instOleDBDataAdapter.Fill(instDataSet, “authors”) ‘ load a new CommandText into instOleDBDataAdapter for the title author table instOleDBDataAdapter.SelectCommand.CommandText = “select distinct titleauthor.au_id,titles.title_id,titles.title from titleauthor,titles where titleauthor.title_id=titles.title_id” instOleDBDataAdapter.Fill(instDataSet, “titleauthor”)
‘ add relations ‘ here we are adding a relation to the dataset. This will establish a relation between two tables in the
145-222.qxd 2/24/03 10:45 AM Page 169
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
dataset somewhat like a join would do. This relation virtually arranges the two tables in a hierarchical manner based on the common field chosen ‘ Definition of parameters: ‘ first parameter is the name with which we want to refer to this relation. ‘ second parameter is the parent datacolumn ‘ third parameter is the child DataColumn instDataSet.Relations.Add(“author_titleauthor”, instDataSet.Tables(“authors”).Columns(“au_id”), instDataSet.Tables(“titleauthor”).Columns(“au_id”)).Nested = True
After filling the DataSet object, you need to display the data in the lvReport control. To do this, you use the Items.Add() method. The following code displays the usage of the method. lvReport.Items.Add(New ListViewItem(strArrAuthorDetails)) ‘where strArrAuthorDetails contains the data in a row of the authors table stored in the DataSet object
Since, you are using the DataSet object, you do not require the connection to the database while the application is executing. Therefore, you can close the connection after the required data has been filled into the DataSet object. To accomplish this, you specify the following code snippet: instOleDBConnection.Close() ‘where instOleDBConnection is the OleDbConnection object
The code for the prcTIDbyAuthShow procedure is displayed in Listing 6-1. Listing 6-1 The prcTIDbyAuthShow Procedure Public Sub prcTIDbyAuthShow()
‘ The connection string will hold the necessary parameters and values to be used while establishing a connection with the SQL database Dim strConnectionString As String
‘Declare the necessary variables Dim instOleDBConnection As OleDbConnection
169
145-222.qxd 2/24/03 10:45 AM Page 170
170
Project 1
DATABASE INTEGRATION WITH .NET
Dim instOleDBDataAdapter As OleDbDataAdapter Dim rowPicker1 As DataRow Dim rowPicker2 As DataRow Dim intTitleCtr As Int32
‘ Clear any existing items in the ListView lvReport.Items.Clear()
‘ Initialize connection string strConnectionString = “Provider=SQLOLEDB.1;Data Source=web-server;USER ID=sa;pwd=;Initial Catalog=Pubs” ‘ Instantiate objects for data access instDataSet = New DataSet() ‘ Use the connection string to establish a connection with the database instOleDBConnection = New OleDbConnection(strConnectionString)
‘ The OleDbDataAdapter is instantiated with System.Data.OleDb.OleDbCommand as the first parameter, which is an SQL query, and the second parameter is System.Data.OleDbConnection, which is the OleDBConnection object instantiated above. instOleDBDataAdapter = New OleDbDataAdapter(“select * from authors”, instOleDBConnection)
‘ Following code starts in a try block to trap any errors while accessing data. Try ‘ Start filling desired data into instDataSet. ‘ Here “authors” is the name given to the result set data in the Dataset. ‘ You can choose any name for the table within the dataset, which you want to use ‘ as a reference for this resultset instOleDBDataAdapter.Fill(instDataSet, “authors”) ‘ Load a new CommandText into instOleDBDataAdapter for the title author table instOleDBDataAdapter.SelectCommand.CommandText = “select distinct titleauthor.au_id,titles.title_id,titles.title from titleauthor,titles where titleauthor.title_id=titles.title_id”
145-222.qxd 2/24/03 10:45 AM Page 171
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
instOleDBDataAdapter.Fill(instDataSet, “titleauthor”)
‘ Add relations : ‘ This will establish a relation between two tables in the dataset somewhat like a join would do. ‘ This relation virtually aranges the two tables in a hierarchical manner based on the common field chosen ‘ Definition of parameters: ‘ first parameter: is the name with which we want to refer to this relation. ‘ second parameter: is the parent DataColumn ‘ third parameter: is the child DataColumn instDataSet.Relations.Add(“author_titleauthor”, instDataSet.Tables(“authors”).Columns(“au_id”), instDataSet.Tables(“titleauthor”).Columns(“au_id”)).Nested = True
‘ Iterate through rows of authors table and pick all authors one by one, using the rowPicker1 object. For Each rowPicker1 In instDataSet.Tables(“authors”).Rows ‘ Add author details into the text box Dim strArrAuthorDetails As String() = {rowPicker1(“au_ID”), rowPicker1(“au_fname”) & “, “ & rowPicker1(“au_lname”)} lvReport.Items.Add(New ListViewItem(strArrAuthorDetails)) ‘ Iterate through child rows(in the related table) to get title information for the current author ‘ To display all titles written by author and their advance. For Each rowPicker2 In rowPicker1.GetChildRows(instDataSet.Relations(“author_titleauthor”)) Dim strArrTitleAuthorDetails As String() = {“”, “”, rowPicker2(“title_ID”), rowPicker2(“title”)} lvReport.Items.Add(New ListViewItem(strArrTitleAuthorDetails)) Next Next
‘ Catch and display the error, if encountered Catch runException As Exception MsgBox(“Error Occured:” & vbLf & runException.ToString)
171
145-222.qxd 2/24/03 10:45 AM Page 172
172
Project 1
DATABASE INTEGRATION WITH .NET
End Try instOleDBConnection.Close() instOleDBDataAdapter.Dispose() ‘ Close the connection and also marked the data adapter for removal from memory by the GC. ‘ However, the dataset still remains active and contains data, which you will use in other functions ‘ while generating XML data and schema files ‘ You will write code to dispose the DataSet in “Protected Overloads Overrides Sub Dispose” method ‘ in the IDE generated region
End Sub
The prcTIDbyAuthWriteXML Procedure The prcTIDbyAuthWriteXML procedure calls the WriteXml() method to write data from the DataSet object to an XML file. The XML file is stored in the same folder where the project executable file is stored. The following code stores the report data in a file called XMLData.XML. instDataSet.WriteXml(Application.StartupPath & “\XMLData.XML”, XmlWritemode.IgnoreSchema)
Listing 6-2 provides the code for the prcTIDbyAuthWriteXML procedure. Listing 6-2 The prcTIDbyAuthWriteXML Procedure Public Sub prcTIDbyAuthWriteXML() ‘ Check if DataSet has been instantiated If Not (instDataSet Is Nothing) Then ‘ Use the WriteXml method of the dataset object to persist the data contained in the dataset into an XML file in application path instDataSet.WriteXml(Application.StartupPath & “\XMLData.XML”, XmlWritemode.IgnoreSchema) End If
End Sub
145-222.qxd 2/24/03 10:45 AM Page 173
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
The prcTIDbyAuthWriteXMLSchema Procedure The prcTIDbyAuthWriteXMLSchema procedure uses the WriteXmlSchema() method to save the schema of the report data in a file called XMLSchema.XML. This file is stored in the same folder where the project executable file is stored. The following code stores the schema related to the report data in a file called XMLSchema.XML. instDataSet.WriteXmlSchema(Application.StartupPath & “\XMLSchema.XML”)
Listing 6-3 provides the code for the prcTIDbyAuthWriteXMLSchema procedure. Listing 6-3 The prcTIDbyAuthWriteXMLSchema Procedure Public Sub prcTIDbyAuthWriteXMLSchema() ‘ Check if DataSet has been instantiated If Not (instDataSet Is Nothing) Then ‘ Use the the WriteXmlSchema method of the DataSet object to persist the XML schema corresponding to the data contents of the DataSet, ‘ into an XML file in application path instDataSet.WriteXmlSchema(Application.StartupPath & “\XMLSchema.XML”) End If ‘ You could have either put this as an XSD file or as an XML(not containing data) End Sub
The prcTIDbyAuthWriteXMLWithSchema Procedure The prcTIDbyAuthWriteXMLWithSchema procedure uses the WriteXml() method to save the data and the schema of the report in a file called XMLData_with_ Schema.XML. This file is stored in the same folder where the project executable file is stored. The following code stores the report data and schema in a file called XMLData_with_Schema.XML. instDataSet.WriteXml(Application.StartupPath & “\XMLData_with_Schema.XML”, XmlWritemode.WriteSchema)
Listing 6-4 provides the code for the procedure.
prcTIDbyAuthWriteXMLWithSchema
173
145-222.qxd 2/24/03 10:45 AM Page 174
Project 1
DATABASE INTEGRATION WITH .NET
Listing 6-4 The prcTIDbyAuthWriteXMLWithSchema Procedure Public Sub prcTIDbyAuthWriteXMLWithSchema() ‘ Check if DataSet has been instantiated If Not (instDataSet Is Nothing) Then ‘ Use the WriteXml method of the DataSet object to persist the data contained in the dataset in XML format,along with corresponding schema instDataSet.WriteXml(Application.StartupPath &
AM FL Y
“\XMLData_with_Schema.XML”, XmlWritemode.WriteSchema) End If End Sub
The frmTitleByAuthor_Load Procedure
The frmTitleByAuthor_Load procedure is called when the frmTitleByAuthor is loaded. This procedure is used to call the prcTIDbyAuthShow procedure.
TE
174
Listing 6-5 provides the code for the procedure. Listing 6-5 The frmTitleByAuthor_Load Procedure Private Sub frmTitleByAuthor_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Call prcTIDbyAuthShow() End Sub
Apart from the aforementioned procedures, the most important piece of code for your form is the code related to the inclusion of namespaces. The inclusion of namespaces is done in the form class file. You include the namespaces that contain the classes that will be used in the code of the application. From Chapter 5, you might recollect that all classes related to the ADO.NET architecture are located in the System.Data namespace. In addition, to use the OLE DB .NET data provider, you need to include the System.Data.OleDb namespace. The following code snippet lists the inclusion of the two namespaces discussed earlier.
Team-Fly®
145-222.qxd 2/24/03 10:45 AM Page 175
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Imports System.Data Imports System.Data.OleDb
Listing 6-6 provides the code for the frmTitleByAuthor.vb form. Listing 6-6 frmTitleByAuthor.vb ‘ import system.Data namespace Imports System.Data ‘ import system.Data.OleDb namespace Imports System.Data.OleDb
Public Class frmTitleByAuthor Inherits System.Windows.Forms.Form
‘ Declare DataSet at form class level so that it can be used across methods Dim instDataSet As DataSet ‘ This is an untyped DataSet. ‘ The OleDbConnection OleDbDataAdapter have not been declared at the form class level because we intend to use the DataSet in a Disconnected mode after filling it once. ‘ Even after disconnecting the connection with the database, the DataSet still holds the tables and relations it was filled with.
#Region “ Windows Form Designer generated code “
Public Sub New() MyBase.New()
‘This call is required by the Windows Form Designer. InitializeComponent()
‘Add any initialization after the InitializeComponent() call
End Sub
175
145-222.qxd 2/24/03 10:45 AM Page 176
176
Project 1
DATABASE INTEGRATION WITH .NET
‘Form overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then ‘NOTE: we have to mark this object for removal from memory ‘ I have added the following If construct to mark instDataSet for removal. If Not (instDataSet Is Nothing) Then instDataSet.Dispose() End If
If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub Friend WithEvents ColumnHeader1 As System.Windows.Forms.ColumnHeader Friend WithEvents ColumnHeader2 As System.Windows.Forms.ColumnHeader Friend WithEvents ColumnHeader3 As System.Windows.Forms.ColumnHeader Friend WithEvents ColumnHeader4 As System.Windows.Forms.ColumnHeader Friend WithEvents lvReport As System.Windows.Forms.ListView
‘Required by the Windows Form Designer Private components As System.ComponentModel.IContainer
‘NOTE: The following procedure is required by the Windows Form Designer ‘It can be modified using the Windows Form Designer. ‘Do not modify it using the code editor. Private Sub InitializeComponent() Me.lvReport = New System.Windows.Forms.ListView() Me.ColumnHeader1 = New System.Windows.Forms.ColumnHeader() Me.ColumnHeader2 = New System.Windows.Forms.ColumnHeader() Me.ColumnHeader3 = New System.Windows.Forms.ColumnHeader() Me.ColumnHeader4 = New System.Windows.Forms.ColumnHeader() Me.SuspendLayout() ‘ ‘lvReport ‘
145-222.qxd 2/24/03 10:45 AM Page 177
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Me.lvReport.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.ColumnHeader1, Me.ColumnHeader2, Me.ColumnHeader3, Me.ColumnHeader4}) Me.lvReport.GridLines = True Me.lvReport.Name = “lvReport” Me.lvReport.Size = New System.Drawing.Size(504, 424) Me.lvReport.TabIndex = 2 Me.lvReport.View = System.Windows.Forms.View.Details ‘ ‘ColumnHeader1 ‘ Me.ColumnHeader1.Text = “Author ID” Me.ColumnHeader1.Width = 68 ‘ ‘ColumnHeader2 ‘ Me.ColumnHeader2.Text = “Author Name” Me.ColumnHeader2.Width = 95 ‘ ‘ColumnHeader3 ‘ Me.ColumnHeader3.Text = “Title ID” Me.ColumnHeader3.Width = 76 ‘ ‘ColumnHeader4 ‘ Me.ColumnHeader4.Text = “Title Name” Me.ColumnHeader4.Width = 251 ‘ ‘frmTitleByAuthor ‘ Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(504, 423) Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.lvReport}) Me.Name = “frmTitleByAuthor” Me.Text = “Titles Authored by Each Author” Me.ResumeLayout(False)
End Sub
177
145-222.qxd 2/24/03 10:45 AM Page 178
178
Project 1
DATABASE INTEGRATION WITH .NET
#End Region
Public Sub prcTIDbyAuthShow()
‘ The connection string will hold the necessary parameters and values to be used while establishing a connection with the SQL database Dim strConnectionString As String
‘Declare the necessary variables Dim instOleDBConnection As OleDbConnection Dim instOleDBDataAdapter As OleDbDataAdapter Dim rowPicker1 As DataRow Dim rowPicker2 As DataRow Dim intTitleCtr As Int32
‘ Clear any existing items in the ListView lvReport.Items.Clear()
‘ Initialize connection string strConnectionString = “Provider=SQLOLEDB.1;Data Source=web-server;USER ID=sa;pwd=;Initial Catalog=Pubs” ‘ Instantiate objects for data access instDataSet = New DataSet() ‘ Use the connection string to establish a connection with the database instOleDBConnection = New OleDbConnection(strConnectionString)
‘ The OleDbDataAdapter is instantiated with System.Data.OleDb.OleDbCommand as the first parameter, which is an SQL query, and the second parameter is System.Data.OleDbConnection, which is the OleDBConnection object instantiated above. instOleDBDataAdapter = New OleDbDataAdapter(“select * from authors”, instOleDBConnection)
‘ Following code starts in a try block to trap any errors while accessing data. Try ‘ Start filling desired data into instDataSet.
145-222.qxd 2/24/03 10:45 AM Page 179
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
‘ Here “authors” is the name given to the result set data in the Dataset. ‘ You can choose any name for the table within the dataset, which you want to use ‘ as a reference for this resultset instOleDBDataAdapter.Fill(instDataSet, “authors”) ‘ Load a new CommandText into instOleDBDataAdapter for the title author table instOleDBDataAdapter.SelectCommand.CommandText = “select distinct titleauthor.au_id,titles.title_id,titles.title from titleauthor,titles where titleauthor.title_id=titles.title_id” instOleDBDataAdapter.Fill(instDataSet, “titleauthor”)
‘ Add relations : ‘ This will establish a relation between two tables in the dataset somewhat like a join would do. ‘ This relation virtually arranges the two tables in a hierarchical manner based on the common field chosen ‘ Definition of parameters: ‘ first parameter: is the name with which we want to refer to this relation. ‘ second parameter: is the parent DataColumn ‘ third parameter: is the child DataColumn instDataSet.Relations.Add(“author_titleauthor”, instDataSet.Tables(“authors”).Columns(“au_id”), instDataSet.Tables(“titleauthor”).Columns(“au_id”)).Nested = True
‘ Iterate through rows of authors table and pick all authors one by one, using the rowPicker1 object. For Each rowPicker1 In instDataSet.Tables(“authors”).Rows ‘ Add author details into the text box Dim strArrAuthorDetails As String() = {rowPicker1(“au_ID”), rowPicker1(“au_fname”) & “, “ & rowPicker1(“au_lname”)} lvReport.Items.Add(New ListViewItem(strArrAuthorDetails)) ‘ Iterate through child rows(in the related table) to get title information for the current author ‘ To display all titles written by author and their advance.
179
145-222.qxd 2/24/03 10:45 AM Page 180
180
Project 1
DATABASE INTEGRATION WITH .NET
For Each rowPicker2 In rowPicker1.GetChildRows(instDataSet.Relations(“author_titleauthor”)) Dim strArrTitleAuthorDetails As String() = {“”, “”, rowPicker2(“title_ID”), rowPicker2(“title”)} lvReport.Items.Add(New ListViewItem(strArrTitleAuthorDetails)) Next Next
‘ Catch and display the error, if encountered Catch runException As Exception MsgBox(“Error Occured:” & vbLf & runException.ToString) End Try instOleDBConnection.Close() instOleDBDataAdapter.Dispose() ‘ Close the connection and also marked the data adapter for removal from memory by the GC. ‘ However, the dataset still remains active and contains data, which you will use in other functions ‘ while generating XML data and schema files ‘ You will write code to dispose the DataSet in “Protected Overloads Overrides Sub Dispose” method ‘ in the IDE generated region
End Sub
Public Sub prcTIDbyAuthWriteXML() ‘ Check if DataSet has been instantiated If Not (instDataSet Is Nothing) Then ‘ Use the WriteXml method of the dataset object to persist the data contained in the dataset into an XML file in application path instDataSet.WriteXml(Application.StartupPath & “\XMLData.XML”, XmlWritemode.IgnoreSchema) End If
End Sub
Public Sub prcTIDbyAuthWriteXMLSchema() ‘ Check if DataSet has been instantiated
145-222.qxd 2/24/03 10:45 AM Page 181
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
If Not (instDataSet Is Nothing) Then ‘ Use the WriteXmlSchema method of the DataSet object to persist the XML schema corresponding to the data contents of the DataSet, ‘ into an XML file in application path instDataSet.WriteXmlSchema(Application.StartupPath & “\XMLSchema.XML”) End If ‘ You could have either put this as an XSD file or as an XML(not containing data) End Sub
Public Sub prcTIDbyAuthWriteXMLWithSchema() ‘ Check if DataSet has been instantiated If Not (instDataSet Is Nothing) Then ‘ Use the WriteXml method of the DataSet object to persist the data contained in the dataset in XML format along with corresponding schema instDataSet.WriteXml(Application.StartupPath & “\XMLData_with_Schema.XML”, XmlWritemode.WriteSchema) End If End Sub
Private Sub frmTitleByAuthor_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Call prcTIDbyAuthShow() End Sub
Private Sub lvReport_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvReport.SelectedIndexChanged
End Sub End Class
Create Author Details Modification Form You now need to create the Author Details Modification form and add the associated controls on the form. To add a form to the application, perform the following steps: 1. Click the Add New Item from the File menu.
181
145-222.qxd 2/24/03 10:45 AM Page 182
182
Project 1
DATABASE INTEGRATION WITH .NET
2. The Add New Item dialog box is displayed. Figure 6-23 displays the dialog box.
TIP Alternately, you can display the Add New Item dialog box by clicking the Ctrl, Shift, and A keys simultaneously.
3. To add a form, select the Windows Form option from the Templates pane. 4. Specify the name of the new form as frmAuthorModify.vb in the Name text box. Figure 6-24 displays the Add New Item dialog box with the modified name value. 5. Click the Open button to create a new form. A new form as displayed in Figure 6-25 is displayed. Next, you need to add controls on the form. You can refer to Figure 6-4 for the controls to be added to the form. As seen in the figure, the form consists of a drop-down list that displays the authors associated with TecPublishers. It also displays the details of the selected
FIGURE 6-23
The Add New Item dialog box
145-222.qxd 2/24/03 10:45 AM Page 183
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
FIGURE 6-24
Chapter 6
The Add New Item dialog box with the modified form name
author in a non-editable state. The form also has options to modify, save or to cancel a modifying operation. You will add the controls as listed in the Table 6-3.
FIGURE 6-25
The new form frmAuthorModify.vb added to the application
183
145-222.qxd 2/24/03 10:45 AM Page 184
Project 1
DATABASE INTEGRATION WITH .NET
Table 6-3 Controls to be Added to frmAuthorModify Control Type
Functionality
cmbAuthors
System.Windows.Forms.ComboBox
List all authors
grpDetails
System.Windows.Forms.GroupBox
Group and collectively manage all controls for author details
txtID
System.Windows.Forms.TextBox
Display author ID
txtLname
System.Windows.Forms.TextBox
Display author last name
txtFname
System.Windows.Forms.TextBox
Display author first name
txtPhone
System.Windows.Forms.TextBox
Display author phone number
txtAddress
System.Windows.Forms.TextBox
Display author address
txtCity
System.Windows.Forms.TextBox
Display author city
txtState
System.Windows.Forms.TextBox
Display author state
txtZip
System.Windows.Forms.TextBox
Display author zip
System.Windows.Forms.TextBox
Display author contract type
System.Windows.Forms.Label
Label various controls
btnModify
System.Windows.Forms.Button
Allow modification of author details
btnSave
System.Windows.Forms.Button
Save the modified author details
btnCancel
System.Windows.Forms.Button
Cancel any changes made
txtContract Label1-Label10
AM FL Y
Control Name
TE
184
NOTE After adding controls, you will notice that in the code generated by the Windows Form Designer, all controls are declared using the WithEvents keyword. This means that the declared object variable for the control refers to a class and that it can raise events, which can subsequently be handled through event handler functions corresponding to the control class.
After adding the required controls to the form, you need to set the property of the controls. For instance, you need to set the Text property of all the various controls
Team-Fly®
145-222.qxd 2/24/03 10:45 AM Page 185
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
on the form. In addition, you need to change the Enabled property for grpDetails, btnModify, BtnSave, and BtnCancel to False.
txtID,
Next, you need to add code for the frmAuthorModify form. To do this, you need to include the relevant namespaces in your form class file. You need to include the following namespaces in the project: ◆ System.Data ◆ System.Data.OleDb In the next step, you need to write code to declare objects that will be used for data access and manipulation. There are certain objects such as the DataSet and Connection objects that you would use across functions in the form class. You need to declare these at form class level. The following code snippet displays the declaration at the form class level. Dim instDataSet As DataSet
‘ connection string will hold the necessary parameters and values ‘to be used while establishing a connection with the SQL database Dim strConnectionString As String Dim instOleDBConnection As OleDbConnection Dim instOleDBDataAdapter As OleDbDataAdapter
‘ A string variable strArrAuthID will be used to hold the ‘ Author ID of the currently selected Author Dim strArrAuthID As String()
Next, you need to write a function initializeDataSetAndCombo that will initialize the dataset named instDataSet and fill the ComboBox control cmbAuthors. Simultaneously, while cmbAuthors is filled with author names, you need to populate an array called strArrAuthID. The strArrAuthID array will hold the author IDs corresponding to the author names displayed in cmbAuthors. The elements of this array will be used to retrieve details of the author selected by the user. As the number of author names displayed by the cmbAuthors might vary, you need to resize the array depending on the number of authors. For this purpose, you can use the Redim statement.
185
145-222.qxd 2/24/03 10:45 AM Page 186
186
Project 1
DATABASE INTEGRATION WITH .NET
NOTE The Redim statement can only be used at the procedure level and not at the class or module level. Although you can use the Redim statement to set or change the size of a particular dimension of an array, you cannot change the rank, i.e., the number of dimensions of the array. In other words, the Redim statement creates a new array of the same rank while releasing the existing array. To ensure that Visual Basic.NET copies the content from the existing array to the new array, you use the Preserve keyword. However, when you use the Preserve keyword with a multi-dimensional array, only the last dimension of the array can be resized. Without the Preserve keyword, the Redim statement initializes the elements of the new array to the default value of their data type.
Next, you will write the following code for the initializeDataSetAndCombo sub procedure. The following code snippet displays the code for the initializeDataSetAndCombo sub procedure. Private Sub initializeDataSetAndCombo()
‘ declare a DataRow object Dim rowPicker1 As DataRow ‘ an integer variable for temporary usage Dim intTMP As Int32
‘ initialize the connection string variable with desired parameters strConnectionString = “Provider=SQLOLEDB.1;Data Source=web-server;USER ID=sa;pwd=;Initial Catalog=Pubs” ‘ instantiate the DataSet, connection and DataAdapter objects instDataSet = New DataSet() instOleDBConnection = New OleDbConnection(strConnectionString) instOleDBDataAdapter = New OleDbDataAdapter(“select * from authors”, instOleDBConnection)
‘ begin the try block to trap errors encountered while accessing data, if any Try ‘ start filling desired data into dataset. ‘ Here instDataSet is the dataset which will hold the result set. ‘ “authors” is the name given to the result set data in the Dataset.
145-222.qxd 2/24/03 10:45 AM Page 187
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
‘ We can choose any name for the table within the dataset. ‘ This can be any name that you want to use as a reference for this resultset instOleDBDataAdapter.Fill(instDataSet, “authors”)
‘ Calculate the number of authors available ‘ and resize the strArrAuthID array accordingly intTMP = instDataSet.Tables(“authors”).Rows.Count() ReDim strArrAuthID(intTMP)
‘ clear the combobox from any existing elements cmbAuthors.Items.Clear() ‘ populate the ComboBox with items, using data from Authors table For Each rowPicker1 In instDataSet.Tables(“authors”).Rows strArrAuthID(cmbAuthors.Items.Add(rowPicker1(“au_fname”) & “ “ & rowPicker1(“au_lname”))) = rowPicker1(“au_id”) Next
‘we could have used data reader here, but since we also have the data in the dataset, we will not create a datareader. cmbAuthors.SelectedIndex = 0
Catch runException As Exception ‘ In case of an error display error description MsgBox(“Error Occured:” & vbLf & runException.ToString) End Try
End Sub
NOTE The .NET Framework also provides the MessageBox class as an alternative to MsgBox. MessageBox is a predefined dialog box similar to MsgBox in functionality. You use the Show() method of the MessageBox class to display the dialog box. The Show() method accepts parameters such as buttons to be displayed, icon, and default button.
187
145-222.qxd 2/24/03 10:45 AM Page 188
188
Project 1
DATABASE INTEGRATION WITH .NET
In the preceding code, the For loop iterates through the authors table, and adds Author name in the form of an item to the cmbAuthors.Items collection by using the Add() method of the cmbAuthors.Items collection. The Add() method returns the index location of the newly added item. This number is used as an index to write the corresponding author ID to strArrAuthID.
NOTE Whenever an item is selected from the cmbAuthors, the details corresponding to the selected author should be displayed. In addition, you want to avoid trips to the database each time details need to be fetched for a particular author. In this case, you can implement disconnected data architecture where you can store the required data from the authors table in the DataSet object. However, if the authors table consists of thousands of records, implementing a object would not be a good choice. This is because the transfer of such large amount of data will result in memory and data transfer overhead. In such a case, you can implement a design model that uses a DataReader object to populate the cmbAuthors and retrieve details corresponding to a selected author from the data source as required. DataSet
You could have used data reader while populating cmbAuthors. But since we already have the same data in the dataset, usage of DataReader will not add memory efficiency to the project. Alternatively you could also have used data binding to get author names in cmbAuthors from the DataSet object.
In the next step, you need to call initializeDataSetAndCombo sub procedure from the Load event handler sub procedure of the form called frmAuthorModify_Load. This will ensure that the form will display all necessary data when the form loads for the first time. Next, you need to specify code for the thors as follows:
SelectedIndexChanged
event of
cmbAu-
Private Sub cmbAuthors_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbAuthors.SelectedIndexChanged
Dim strAUID As String ‘ to hold ID of Currently selected author Dim foundRows As DataRow() ‘ to hold row containing author details
‘ Get the ID from strArrAuthID for the currently selected author
145-222.qxd 2/24/03 10:45 AM Page 189
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
strAUID = strArrAuthID(cmbAuthors.SelectedIndex)
‘ Use the select method of DataTable object to ‘ retrieve the record for currently selected author foundRows = instDataSet.Tables(“authors”).Select(“au_id=’” & strAUID & “‘“)
‘ Check if relevant record was returned. ‘ Then update the controls on the form with data corresponding to current author If Not (foundRows Is Nothing) Then txtID.Text = strAUID txtLname.Text = foundRows(0).Item(“au_lname”) txtFname.Text = foundRows(0).Item(“au_fname”) txtPhone.Text = foundRows(0).Item(“phone”) txtAddress.Text = foundRows(0).Item(“address”) txtCity.Text = foundRows(0).Item(“city”) txtState.Text = foundRows(0).Item(“state”) txtZip.Text = foundRows(0).Item(“zip”) txtContract.Text = foundRows(0).Item(“contract”) End If End Sub
Next, you need to add code for the click events of the Modify, Save, and Cancel buttons, respectively. The following code snippet lists the code for the Click event of the Modify button. Private Sub btnModify_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnModify.Click ‘ Enable the GroupBox that contains the controls for author details grpDetails.Enabled = True ‘ Enable the Save and Cancel button btnSave.Enabled = True btnCancel.Enabled = True
‘ Disable the Modify button btnModify.Enabled = False ‘ Disable cmbAuthors because you do not want ‘ the user to change the author while editing details of another author cmbAuthors.Enabled = False End Sub
189
145-222.qxd 2/24/03 10:45 AM Page 190
190
Project 1
DATABASE INTEGRATION WITH .NET
The following code snippet lists the code for the Click event of the Save button. Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
‘ validation code: none of the fields should be empty If Trim(txtFname.Text) = “” Or _ Trim(txtLname.Text) = “” Or _ Trim(txtPhone.Text) = “” Or _ Trim(txtAddress.Text) = “” Or _ Trim(txtCity.Text) = “” Or _ Trim(txtState.Text) = “” Or _ Trim(txtZip.Text) = “” Or _ Trim(txtContract.Text) = “” Then MsgBox(“Data validation failed. Please enter data for all fields in required format!”) Exit Sub
End If
‘ code to update records
‘ create SQL string with parameters Dim strSQL As String = “update authors set “ & _ “au_lname = ? ,” & _ “au_fname = ? ,” & _ “phone = ? ,” & _ “address = ? ,” & _ “city = ? ,” & _ “state = ? ,” & _ “zip= ? ,” & _ “contract = ? “ & _ “where au_id= ?” Try
‘ check for connection state, and open if required
145-222.qxd 2/24/03 10:45 AM Page 191
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
If instOleDBConnection.State ConnectionState.Open Then instOleDBConnection.Open() End If
‘ declare and initialize command object Dim objCmd As New OleDbCommand(strSQL, instOleDBConnection) ‘ Declare a variable that will store the number of rows affected by the command Dim intRowsAffected As Int32
‘ Populate the Parameters collection of the OleDbCommand object. ‘ The parameters are added in the form of name-value pairs. objCmd.Parameters.Add(“au_lname”, txtLname.Text) objCmd.Parameters.Add(“au_fname”, txtFname.Text) objCmd.Parameters.Add(“phone”, txtPhone.Text) objCmd.Parameters.Add(“address”, txtAddress.Text) objCmd.Parameters.Add(“city”, txtCity.Text) objCmd.Parameters.Add(“state”, txtState.Text) objCmd.Parameters.Add(“zip”, txtZip.Text) objCmd.Parameters.Add(“contract”, CBool(txtContract.Text)) objCmd.Parameters.Add(“au_ID”, txtID.Text)
‘ execute the command on the Data Source intRowsAffected = objCmd.ExecuteNonQuery()
Catch runException As Exception MsgBox(“Error Occurred:” & vbLf & runException.ToString) End Try
MsgBox(“Record updated for Author ID: “ & txtID.Text)
‘ Update the dataset and combobox because currently the DataSet and ComboBox contain old Values. Call initializeDataSetAndCombo()
‘ update enabled status of controls btnSave.Enabled = False btnModify.Enabled = True
191
145-222.qxd 2/24/03 10:45 AM Page 192
192
Project 1
DATABASE INTEGRATION WITH .NET
grpDetails.Enabled = False cmbAuthors.Enabled = True btnCancel.Enabled = False
End Sub
The preceding code uses a parameterized SQL statement to update the record for an author. In the statement, you create a string that contains an SQL query along with embedded placeholders for parameters. The embedded placeholders are marked using the question mark sign. You use this string with a Connection object to initialize a Command object. Next, you can add parameters to the Command object as items of the Parameters collection in the Command object. While adding parameters to the collection, it is critical to add them in the same sequence as the corresponding placeholders in the parameterized query string. It is also a good idea to add parameters in the form of name-value pairs. This helps in easy reference of these items through code. You can access these members through the index numbers also, but accessing by name proves to be a comparatively less error prone and more understandable implementation
NOTE An alternate method to perform the same update operation is to modify the record in the dataset and then call the Update() method for the corresponding DataAdapter. When you call the Update() method, the DataAdapter object analyzes the changes made to the DataSet. Subsequently, based on the difference between the data in the DataSet and the data source, the DataAdapter object executes the relevant commands such as insert, update, and delete on the data source to reflect the changes in the data source. You can also use corresponding error handling techniques. For example, you could set the ContinueUpdateOnError property of DataAdapter to true before calling Update() method. The update process will continue even if it encounters certain errors. You can later analyze the errors if any, by, referring to the RowError property of a particular row.
The following code snippet lists the code for the button.
Click
event of the
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click ‘ update enabled status of controls btnSave.Enabled = False
Cancel
145-222.qxd 2/24/03 10:45 AM Page 193
Chapter 6
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
btnModify.Enabled = True grpDetails.Enabled = False cmbAuthors.Enabled = True btnCancel.Enabled = False End Sub
Listing 6-7 displays the entire code for the you add the preceding lines of code.
frmAuthorModify.vb
form file after
Listing 6-7 frmAuthorModify.vb Imports System.Data Imports System.Data.OleDb
Public Class frmAuthorModify Inherits System.Windows.Forms.Form
Dim instDataSet As DataSet ‘ connection string will hold the necessary parameters and values ‘to be used while establishing a connection with the SQL database Dim strConnectionString As String Dim instOleDBConnection As OleDbConnection Dim instOleDBDataAdapter As OleDbDataAdapter ‘ A string variable strArrAuthID will be used to hold the ‘ Author ID of the currently selected Author Dim strArrAuthID As String()
Friend WithEvents Label1 As System.Windows.Forms.Label Friend WithEvents btnModify As System.Windows.Forms.Button Friend WithEvents btnSave As System.Windows.Forms.Button Friend WithEvents btnCancel As System.Windows.Forms.Button Friend WithEvents grpDetails As System.Windows.Forms.GroupBox Friend WithEvents Label2 As System.Windows.Forms.Label Friend WithEvents Label3 As System.Windows.Forms.Label Friend WithEvents Label4 As System.Windows.Forms.Label Friend WithEvents Label5 As System.Windows.Forms.Label Friend WithEvents Label6 As System.Windows.Forms.Label Friend WithEvents Label7 As System.Windows.Forms.Label
193
145-222.qxd 2/24/03 10:45 AM Page 194
Project 1
DATABASE INTEGRATION WITH .NET
Friend WithEvents Label8 As System.Windows.Forms.Label Friend WithEvents Label9 As System.Windows.Forms.Label Friend WithEvents Label10 As System.Windows.Forms.Label Friend WithEvents txtID As System.Windows.Forms.TextBox Friend WithEvents txtLname As System.Windows.Forms.TextBox Friend WithEvents txtFname As System.Windows.Forms.TextBox Friend WithEvents txtPhone As System.Windows.Forms.TextBox Friend WithEvents txtAddress As System.Windows.Forms.TextBox Friend WithEvents txtCity As System.Windows.Forms.TextBox
AM FL Y
Friend WithEvents txtState As System.Windows.Forms.TextBox Friend WithEvents txtZip As System.Windows.Forms.TextBox Friend WithEvents txtContract As System.Windows.Forms.TextBox Friend WithEvents cmbAuthors As System.Windows.Forms.ComboBox
TE
194
#Region “ Windows Form Designer generated code “
Public Sub New() MyBase.New()
‘This call is required by the Windows Form Designer. InitializeComponent()
‘Add any initialization after the InitializeComponent() call
End Sub
‘Form overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing)
Team-Fly®
145-222.qxd 2/24/03 10:45 AM Page 195
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
End Sub
‘Required by the Windows Form Designer Private components As System.ComponentModel.Container
‘NOTE: The following procedure is required by the Windows Form Designer ‘It can be modified using the Windows Form Designer. ‘Do not modify it using the code editor. Private Sub InitializeComponent() Me.Label1 = New System.Windows.Forms.Label() Me.btnCancel = New System.Windows.Forms.Button() Me.btnSave = New System.Windows.Forms.Button() Me.cmbAuthors = New System.Windows.Forms.ComboBox() Me.btnModify = New System.Windows.Forms.Button() Me.grpDetails = New System.Windows.Forms.GroupBox() Me.txtContract = New System.Windows.Forms.TextBox() Me.txtZip = New System.Windows.Forms.TextBox() Me.txtState = New System.Windows.Forms.TextBox() Me.txtCity = New System.Windows.Forms.TextBox() Me.txtAddress = New System.Windows.Forms.TextBox() Me.txtPhone = New System.Windows.Forms.TextBox() Me.txtFname = New System.Windows.Forms.TextBox() Me.txtLname = New System.Windows.Forms.TextBox() Me.txtID = New System.Windows.Forms.TextBox() Me.Label10 = New System.Windows.Forms.Label() Me.Label9 = New System.Windows.Forms.Label() Me.Label8 = New System.Windows.Forms.Label() Me.Label7 = New System.Windows.Forms.Label() Me.Label6 = New System.Windows.Forms.Label() Me.Label5 = New System.Windows.Forms.Label() Me.Label4 = New System.Windows.Forms.Label() Me.Label3 = New System.Windows.Forms.Label() Me.Label2 = New System.Windows.Forms.Label() Me.grpDetails.SuspendLayout() Me.SuspendLayout() ‘ ‘Label1 ‘
195
145-222.qxd 2/24/03 10:45 AM Page 196
196
Project 1
DATABASE INTEGRATION WITH .NET
Me.Label1.Location = New System.Drawing.Point(24, 32) Me.Label1.Name = “Label1” Me.Label1.Size = New System.Drawing.Size(152, 16) Me.Label1.TabIndex = 3 Me.Label1.Text = “Choose Author name” ‘ ‘btnCancel ‘ Me.btnCancel.Enabled = False Me.btnCancel.Location = New System.Drawing.Point(288, 344) Me.btnCancel.Name = “btnCancel” Me.btnCancel.Size = New System.Drawing.Size(88, 24) Me.btnCancel.TabIndex = 5 Me.btnCancel.Text = “Cancel” ‘ ‘btnSave ‘ Me.btnSave.Enabled = False Me.btnSave.Location = New System.Drawing.Point(168, 344) Me.btnSave.Name = “btnSave” Me.btnSave.Size = New System.Drawing.Size(96, 24) Me.btnSave.TabIndex = 4 Me.btnSave.Text = “Save” ‘ ‘cmbAuthors ‘ Me.cmbAuthors.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList Me.cmbAuthors.DropDownWidth = 152 Me.cmbAuthors.Location = New System.Drawing.Point(184, 32) Me.cmbAuthors.Name = “cmbAuthors” Me.cmbAuthors.Size = New System.Drawing.Size(224, 21) Me.cmbAuthors.TabIndex = 0 ‘ ‘btnModify ‘ Me.btnModify.Location = New System.Drawing.Point(48, 344) Me.btnModify.Name = “btnModify”
145-222.qxd 2/24/03 10:45 AM Page 197
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Me.btnModify.Size = New System.Drawing.Size(96, 24) Me.btnModify.TabIndex = 4 Me.btnModify.Text = “Modify” ‘ ‘grpDetails ‘ Me.grpDetails.Controls.AddRange(New System.Windows.Forms.Control() {Me.txtContract, Me.txtZip, Me.txtState, Me.txtCity, Me.txtAddress, Me.txtPhone, Me.txtFname, Me.txtLname, Me.txtID, Me.Label10, Me.Label9, Me.Label8, Me.Label7, Me.Label6, Me.Label5, Me.Label4, Me.Label3, Me.Label2}) Me.grpDetails.Enabled = False Me.grpDetails.Location = New System.Drawing.Point(16, 64) Me.grpDetails.Name = “grpDetails” Me.grpDetails.Size = New System.Drawing.Size(400, 272) Me.grpDetails.TabIndex = 6 Me.grpDetails.TabStop = False Me.grpDetails.Text = “Author Details” ‘ ‘txtContract ‘ Me.txtContract.Location = New System.Drawing.Point(168, 240) Me.txtContract.Name = “txtContract” Me.txtContract.Size = New System.Drawing.Size(200, 20) Me.txtContract.TabIndex = 17 Me.txtContract.Text = “TextBox9” ‘ ‘txtZip ‘ Me.txtZip.Location = New System.Drawing.Point(168, 212) Me.txtZip.Name = “txtZip” Me.txtZip.Size = New System.Drawing.Size(200, 20) Me.txtZip.TabIndex = 16 Me.txtZip.Text = “TextBox8” ‘ ‘txtState ‘ Me.txtState.Location = New System.Drawing.Point(168, 184) Me.txtState.Name = “txtState”
197
145-222.qxd 2/24/03 10:45 AM Page 198
198
Project 1
DATABASE INTEGRATION WITH .NET
Me.txtState.Size = New System.Drawing.Size(200, 20) Me.txtState.TabIndex = 15 Me.txtState.Text = “TextBox7” ‘ ‘txtCity ‘ Me.txtCity.Location = New System.Drawing.Point(168, 156) Me.txtCity.Name = “txtCity” Me.txtCity.Size = New System.Drawing.Size(200, 20) Me.txtCity.TabIndex = 14 Me.txtCity.Text = “TextBox6” ‘ ‘txtAddress ‘ Me.txtAddress.Location = New System.Drawing.Point(168, 128) Me.txtAddress.Name = “txtAddress” Me.txtAddress.Size = New System.Drawing.Size(200, 20) Me.txtAddress.TabIndex = 13 Me.txtAddress.Text = “TextBox5” ‘ ‘txtPhone ‘ Me.txtPhone.Location = New System.Drawing.Point(168, 100) Me.txtPhone.Name = “txtPhone” Me.txtPhone.Size = New System.Drawing.Size(200, 20) Me.txtPhone.TabIndex = 12 Me.txtPhone.Text = “TextBox4” ‘ ‘txtFname ‘ Me.txtFname.Location = New System.Drawing.Point(168, 72) Me.txtFname.Name = “txtFname” Me.txtFname.Size = New System.Drawing.Size(200, 20) Me.txtFname.TabIndex = 11 Me.txtFname.Text = “TextBox3” ‘ ‘txtLname ‘
145-222.qxd 2/24/03 10:45 AM Page 199
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Me.txtLname.Location = New System.Drawing.Point(168, 44) Me.txtLname.Name = “txtLname” Me.txtLname.Size = New System.Drawing.Size(200, 20) Me.txtLname.TabIndex = 10 Me.txtLname.Text = “TextBox2” ‘ ‘txtID ‘ Me.txtID.Enabled = False Me.txtID.Location = New System.Drawing.Point(168, 16) Me.txtID.Name = “txtID” Me.txtID.Size = New System.Drawing.Size(200, 20) Me.txtID.TabIndex = 9 Me.txtID.Text = “TextBox1” ‘ ‘Label10 ‘ Me.Label10.Location = New System.Drawing.Point(40, 240) Me.Label10.Name = “Label10” Me.Label10.Size = New System.Drawing.Size(88, 16) Me.Label10.TabIndex = 8 Me.Label10.Text = “Contract” ‘ ‘Label9 ‘ Me.Label9.Location = New System.Drawing.Point(40, 213) Me.Label9.Name = “Label9” Me.Label9.Size = New System.Drawing.Size(88, 16) Me.Label9.TabIndex = 7 Me.Label9.Text = “Zip” ‘ ‘Label8 ‘ Me.Label8.Location = New System.Drawing.Point(40, 186) Me.Label8.Name = “Label8” Me.Label8.Size = New System.Drawing.Size(88, 16) Me.Label8.TabIndex = 6 Me.Label8.Text = “State”
Chapter 6
199
145-222.qxd 2/24/03 10:45 AM Page 200
200
Project 1
DATABASE INTEGRATION WITH .NET
‘ ‘Label7 ‘ Me.Label7.Location = New System.Drawing.Point(40, 159) Me.Label7.Name = “Label7” Me.Label7.Size = New System.Drawing.Size(88, 16) Me.Label7.TabIndex = 5 Me.Label7.Text = “City” ‘ ‘Label6 ‘ Me.Label6.Location = New System.Drawing.Point(40, 132) Me.Label6.Name = “Label6” Me.Label6.Size = New System.Drawing.Size(88, 16) Me.Label6.TabIndex = 4 Me.Label6.Text = “Address” ‘ ‘Label5 ‘ Me.Label5.Location = New System.Drawing.Point(40, 105) Me.Label5.Name = “Label5” Me.Label5.Size = New System.Drawing.Size(88, 16) Me.Label5.TabIndex = 3 Me.Label5.Text = “Phone” ‘ ‘Label4 ‘ Me.Label4.Location = New System.Drawing.Point(40, 78) Me.Label4.Name = “Label4” Me.Label4.Size = New System.Drawing.Size(88, 16) Me.Label4.TabIndex = 2 Me.Label4.Text = “First Name” ‘ ‘Label3 ‘ Me.Label3.Location = New System.Drawing.Point(40, 51) Me.Label3.Name = “Label3” Me.Label3.Size = New System.Drawing.Size(88, 16)
145-222.qxd 2/24/03 10:45 AM Page 201
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Me.Label3.TabIndex = 1 Me.Label3.Text = “Last Name” ‘ ‘Label2 ‘ Me.Label2.Location = New System.Drawing.Point(40, 24) Me.Label2.Name = “Label2” Me.Label2.Size = New System.Drawing.Size(88, 16) Me.Label2.TabIndex = 0 Me.Label2.Text = “ID” ‘ ‘frmAuthorModify ‘ Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(432, 381) Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.grpDetails, Me.btnCancel, Me.btnSave, Me.btnModify, Me.Label1, Me.cmbAuthors}) Me.Name = “frmAuthorModify” Me.Text = “Author Details Modification” Me.grpDetails.ResumeLayout(False) Me.ResumeLayout(False)
End Sub
#End Region
Private Sub frmAuthorModify_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call initializeDataSetAndCombo()
End Sub
Private Sub cmbAuthors_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbAuthors.SelectedIndexChanged
Dim strAUID As String ‘ to hold ID of Currently selected author Dim foundRows As DataRow() ‘ to hold row containing author details
201
145-222.qxd 2/24/03 10:45 AM Page 202
202
Project 1
DATABASE INTEGRATION WITH .NET
‘ Get the ID from strArrAuthID for the currently selected author strAUID = strArrAuthID(cmbAuthors.SelectedIndex)
‘ Use the select method of DataTable object to ‘ retrieve the record for currently selected author foundRows = instDataSet.Tables(“authors”).Select(“au_id=’” & strAUID & “‘“)
‘ Check if relevant record was returned. ‘ Then update the controls on the form with data corresponding to current author If Not (foundRows Is Nothing) Then txtID.Text = strAUID txtLname.Text = foundRows(0).Item(“au_lname”) txtFname.Text = foundRows(0).Item(“au_fname”) txtPhone.Text = foundRows(0).Item(“phone”) txtAddress.Text = foundRows(0).Item(“address”) txtCity.Text = foundRows(0).Item(“city”) txtState.Text = foundRows(0).Item(“state”) txtZip.Text = foundRows(0).Item(“zip”) txtContract.Text = foundRows(0).Item(“contract”) End If End Sub
Private Sub btnModify_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnModify.Click ‘ Enable the GroupBox that contains the controls for author details grpDetails.Enabled = True ‘ Enable the Save and Cancel button btnSave.Enabled = True btnCancel.Enabled = True
‘ Disable the Modify button btnModify.Enabled = False ‘ Disable cmbAuthors because you do not want ‘ the user to change the author while editing details of another author cmbAuthors.Enabled = False End Sub
145-222.qxd 2/24/03 10:45 AM Page 203
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
‘ validation code: none of the fields should be empty If Trim(txtFname.Text) = “” Or _ Trim(txtLname.Text) = “” Or _ Trim(txtPhone.Text) = “” Or _ Trim(txtAddress.Text) = “” Or _ Trim(txtCity.Text) = “” Or _ Trim(txtState.Text) = “” Or _ Trim(txtZip.Text) = “” Or _ Trim(txtContract.Text) = “” Then MsgBox(“Data validation failed. Please enter data for all fields in required format!”) Exit Sub
End If
‘ updation code
‘ create SQL string with parameters Dim strSQL As String = “update authors set “ & _ “au_lname = ? ,” & _ “au_fname = ? ,” & _ “phone = ? ,” & _ “address = ? ,” & _ “city = ? ,” & _ “state = ? ,” & _ “zip= ? ,” & _ “contract = ? “ & _ “where au_id= ?” Try
‘ check for connection state, and open if required If instOleDBConnection.State ConnectionState.Open Then
203
145-222.qxd 2/24/03 10:45 AM Page 204
Project 1
DATABASE INTEGRATION WITH .NET
instOleDBConnection.Open() End If
‘ declare and initialize command object Dim objCmd As New OleDbCommand(strSQL, instOleDBConnection) ‘ Declare a variable that will store the number of rows affected by the command Dim intRowsAffected As Int32
AM FL Y
‘ Populate the Parameters collection of the OleDbCommand object. ‘ The parameters are added in the form of name-value pairs. objCmd.Parameters.Add(“au_lname”, txtLname.Text) objCmd.Parameters.Add(“au_fname”, txtFname.Text) objCmd.Parameters.Add(“phone”, txtPhone.Text) objCmd.Parameters.Add(“address”, txtAddress.Text) objCmd.Parameters.Add(“city”, txtCity.Text) objCmd.Parameters.Add(“state”, txtState.Text)
TE
204
objCmd.Parameters.Add(“zip”, txtZip.Text) objCmd.Parameters.Add(“contract”, CBool(txtContract.Text)) objCmd.Parameters.Add(“au_ID”, txtID.Text)
‘ execute the command on the Data Source intRowsAffected = objCmd.ExecuteNonQuery()
Catch runException As Exception MsgBox(“Error Occurred:” & vbLf & runException.ToString) End Try
MsgBox(“Record updated for Author ID: “ & txtID.Text)
‘ Update the dataset and combobox. Call initializeDataSetAndCombo()
‘ update enabled status of controls btnSave.Enabled = False btnModify.Enabled = True grpDetails.Enabled = False cmbAuthors.Enabled = True
Team-Fly®
145-222.qxd 2/24/03 10:45 AM Page 205
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
btnCancel.Enabled = False
End Sub
Private Sub initializeDataSetAndCombo()
‘ declare a DataRow object Dim rowPicker1 As DataRow ‘ an integer variable for temporary usage Dim intTMP As Int32
‘ initialize the connection string variable with desired parameters strConnectionString = “Provider=SQLOLEDB.1;Data Source=web-server;USER ID=sa;pwd=;Initial Catalog=Pubs” ‘ instantiate the DataSet, connection and DataAdapter objects instDataSet = New DataSet() instOleDBConnection = New OleDbConnection(strConnectionString) instOleDBDataAdapter = New OleDbDataAdapter(“select * from authors”, instOleDBConnection)
‘ begin the try block to trap errors encountered while accessing data, if any Try ‘ start filling desired data into dataset. ‘ Here instDataSet is the dataset which will hold the result set. ‘ “authors” is the name given to the result set data in the Dataset. ‘ We can choose any name for the table within the dataset. ‘ This can be any name that you want to use as a reference for this ' resultset instOleDBDataAdapter.Fill(instDataSet, “authors”)
‘ Calculate the number of authors available ‘ and resize the strArrAuthID array accordingly intTMP = instDataSet.Tables(“authors”).Rows.Count() ReDim strArrAuthID(intTMP)
‘ clear the combobox from any existing elements cmbAuthors.Items.Clear()
205
145-222.qxd 2/24/03 10:45 AM Page 206
206
Project 1
DATABASE INTEGRATION WITH .NET
‘ populate the ComboBox with items, using data from Authors table For Each rowPicker1 In instDataSet.Tables(“authors”).Rows strArrAuthID(cmbAuthors.Items.Add(rowPicker1(“au_fname”) & “ “ & rowPicker1(“au_lname”))) = rowPicker1(“au_id”) Next
‘we could have used data reader here, but since we also have the data in the dataset, we will not create a datareader. cmbAuthors.SelectedIndex = 0
Catch runException As Exception ‘ In case of an error display error description MsgBox(“Error Occured:” & vbLf & runException.ToString) End Try
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click ‘ Call the function cmbAuthors_SelectedIndexChanged to restore the original details Call cmbAuthors_SelectedIndexChanged(sender, e) ‘ update enabled status of controls btnSave.Enabled = False btnModify.Enabled = True grpDetails.Enabled = False cmbAuthors.Enabled = True btnCancel.Enabled = False End Sub End Class
Create the Entity Details Maintenance Form In the next step, you need to create the Entity Details Maintenance form. As the first step, you need to add a new form by using the steps listing in the section “Create the Author Details Modification Form.”
145-222.qxd 2/24/03 10:45 AM Page 207
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
You need to name the form as frmMDIMain and specify the text property for the form as Entity Details Maintenance. Next, you need to add the required controls on the form. The controls and the corresponding control names identified for the form are listed in Table 6-4. Table 6-4 Controls in Report Module Control Type
Control Name
Functionality
ListView
lvReport
Display data in rows and columns
MenuItem
mnuMore
Display the More reports command on the Reports menu
MenuItem
mnuTIDbyAuth
Display the Title IDs by Author command on the Reports menu
MenuItem
mnuTIDbyAuthShow
Display the Show Report command on the Reports menu
MenuItem
mnuTIDbyAuthWriteXML
Display the Write XML command on the Reports menu
MenuItem
mnuTIDbyAuthWriteXMLSchema
Display the Write XML Schema command on the Reports menu
MenuItem
mnuTIDbyAuthWriteXMLWithSchema
Display the Write XML with Schema command on the Reports menu
To add the menu control to the form, you need to perform the following steps: 1. Add a MainMenu control to the form by dragging the control from the Toolbox to the form. Rename this as mnuEntityModify. 2. Double-click the IsMdiContainer property in the Properties dialog box to change it to True. Figure 6-26 displays the Properties window with the modified IsMdiContainer property. 3. Double-click the Menu property in the Properties window to display the added menu on the form. Figure 6-27 displays the Properties window with the modified Menu property.
207
145-222.qxd 2/24/03 10:45 AM Page 208
208
Project 1
DATABASE INTEGRATION WITH .NET
FIGURE 6-26
The Properties window with the modified IsMdiContainer property
FIGURE 6-27
The Properties window with the modified Menu property
4. Next, you need to add the required menus to the form. To add the Modify menu, click in the form at the left most corner of the form. To display the menu as Modify, type &Modify in the Text property value. Specify the Name property of the menu as mnuModify 5. Name the menu options as mnuModify, mnuModAuthorDetails, and mnuMore, respectively 6. Set the Enabled property of mnuMore to False. Similarly, create the remaining menus on the form. Set the Enabled property of mnuMoreReports to False.
145-222.qxd 2/24/03 10:45 AM Page 209
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
You can now specify code for the events of the controls on the form. The following list specifies the procedures for which you need to write code. ◆
mnuModAuthorDetails_Click
◆
mnuTIDbyAuthShow_Click
◆
mnuTIDbyAuthWriteXML_Click
◆
mnuTIDbyAuthWriteXMLSchema_Click
◆
mnuTIDbyAuthWriteXMLWithSchema_Click
◆
mnuExit_Click
◆
instfrmTidByAuthor_Closed
◆
instfrmAuthorModify_Closed
The subsequent sections discuss the procedures.
The mnuModAuthorDetails_Click Procedure This procedure is invoked when the Author Details menu command is clicked. This procedure displays the Author Details Modification Form and resizes the existing form. The code for the click event handler is specified in Listing 6-8. Listing 6-8 Code for the Click Event Handler of mnuModAuthorDetails_Click Private Sub mnuModAuthorDetails_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuModAuthorDetails.Click instfrmAuthorModify = New frmAuthorModify() ‘ set the parent MdiParent property of frmAuthorModify to ‘ associate it as an MDI child form to the frmMDIMain form ‘ You use the Me object to refer to the current instance of frmMDIMain instfrmAuthorModify.MdiParent = Me ‘ Call the Show method of the object of frmAuthorModify to show it instfrmAuthorModify.Show() ‘ Set the width and height of MDI form Me.Width = 447 Me.Height = 427 ‘ set the window state property of instfrmAuthorModify to ' FormWindowState.Maximized instfrmAuthorModify.WindowState = FormWindowState.Maximized ‘ Disable the mnuModAuthorDetails menu option, as the form is already
209
145-222.qxd 2/24/03 10:45 AM Page 210
210
Project 1
DATABASE INTEGRATION WITH .NET
active now. Me.mnuModAuthorDetails.Enabled = False
End Sub
The mnuTIDbyAuthShow_Click Procedure This procedure is invoked when the Show Report menu command is clicked. This procedure displays the Authors and Titles report. In addition, this procedure disables the Show Report command while enabling the remaining commands on the Title IDs by author menu. The code for the click event handler of the mnuTIDbyAuthShow command is specified in Listing 6-9. Listing 6-9 Code for the Click Event Handler of mnuTIDbyAuthShow_Click Private Sub mnuTIDbyAuthShow_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTIDbyAuthShow.Click instfrmTidByAuthor = New frmTitleByAuthor() instfrmTidByAuthor.MdiParent = Me instfrmTidByAuthor.Show()
‘ Enable-disable the relevant menu options mnuTIDbyAuthShow.Enabled = False mnuTIDbyAuthWriteXML.Enabled = True mnuTIDbyAuthWriteXMLSchema.Enabled = True mnuTIDbyAuthWriteXMLWithSchema.Enabled = True
‘ Set the width and height of MDI form Me.Width = 516 Me.Height = 474
instfrmTidByAuthor.WindowState = FormWindowState.Maximized
End Sub
145-222.qxd 2/24/03 10:45 AM Page 211
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
The mnuTIDbyAuthWriteXML_Click Procedure This procedure is invoked when the Write XML menu command is clicked. This procedure calls the prcTIDbyAuthWriteXML(). The prcTIDbyAuthWriteXML() procedure is covered in the “The prcTIDbyAuthWriteXML Procedure.” The code for the click event handler of the Write XML command is specified in Listing 6-10. Listing 6-10 Code for the Click Event Handler of mnuTIDbyAuthWriteXML_Click Private Sub mnuTIDbyAuthWriteXML_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTIDbyAuthWriteXML.Click Call instfrmTidByAuthor.prcTIDbyAuthWriteXML() End Sub
The mnuTIDbyAuthWriteXMLSchema_Click Procedure This procedure is invoked when the Write XML Schema menu command is clicked. This procedure calls prcTIDbyAuthWriteXMLSchema. The prcTIDbyAuthWriteXMLSchema procedure is covered in the “The prcTIDbyAuthWriteXMLSchema Procedure.” The code for the click event handler of the Write XML Schema command is specified in Listing 6-11. Listing 6-11 The Click Event Handler of mnuTIDbyAuthWriteXMLSchema_Click Private Sub mnuTIDbyAuthWriteXMLSchema_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTIDbyAuthWriteXMLSchema.Click Call instfrmTidByAuthor.prcTIDbyAuthWriteXMLSchema() End Sub
The mnuTIDbyAuthWriteXMLWithSchema_Click Procedure This procedure is invoked when the Write XML with Schema menu command is clicked. This procedure calls prcTIDbyAuthWriteXMLWithSchema. The prcTIDbyAuthWriteXMLWithSchema procedure is covered in the “The prcTIDbyAuthWriteXMLWithSchema Procedure.” The code for the click event handler of the Write XML with Schema command is specified in Listing 6-12.
211
145-222.qxd 2/24/03 10:45 AM Page 212
212
Project 1
DATABASE INTEGRATION WITH .NET
Listing 6-12 The Click Event Handler of mnuTIDbyAuthWriteXMLWithSchema_Click Private Sub mnuTIDbyAuthWriteXMLWithSchema_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTIDbyAuthWriteXMLWithSchema.Click Call instfrmTidByAuthor.prcTIDbyAuthWriteXMLWithSchema() End Sub
The mnuExit_Click Procedure This procedure is invoked when the Exit menu command is clicked. This procedure calls Close() method for the current form. The code for the click event handler of the Exit menu is specified in Listing 6-13. Listing 6-13 Code for the Click Event Handler of mnuExit_Click Private Sub mnuExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuExit.Click ‘ Call the Close() function for the current instance of the form frmMDIMain Me.Close() End Sub
As the last step, you need to specify code for the events when the Titles Authored by Each Author and the Author Details Modification forms are closed.
The instfrmTidByAuthor_Closed Procedure The instfrmTidByAuthor_Closed procedure is invoked when the Titles Authored by Each Author form is closed. This procedure disables the Write XML, Write XML Schema, and the Write XML with Schema commands on the Title IDs by Author menu. In addition, the Show Report command is enabled. The code for the Closed event handler of the instfrmTidByAuthor form is specified in Listing 6-14.
145-222.qxd 2/24/03 10:45 AM Page 213
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Listing 6-14 Code for the Closed Event Handler of instfrmTidByAuthor_Closed Private Sub instfrmTidByAuthor_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles instfrmTidByAuthor.Closed ‘ Enable or disable the relevant menu options mnuTIDbyAuthShow.Enabled = True mnuTIDbyAuthWriteXML.Enabled = False mnuTIDbyAuthWriteXMLSchema.Enabled = False mnuTIDbyAuthWriteXMLWithSchema.Enabled = False End Sub
The instfrmAuthorModify_Closed Procedure The instfrmAuthorModify_Closed procedure is invoked when the Author Details Modification form is closed. This procedure enables the Author Details command on the Modify menu. The code for the Closed event of the instfrmAuthorModify form object is specified in Listing 6-15. Listing 6-15 Code for the Closed Event Handler of instfrmAuthorModify_Closed Private Sub instfrmAuthorModify_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles instfrmAuthorModify.Closed ‘ Enable-disable the relevant menu options Me.mnuModAuthorDetails.Enabled = True End Sub
Listing 6-16 displays the entire code for the frmMDIMain.vb form file, after adding the preceding lines of code. Listing 6-16 frmMDIMain.vb Public Class frmMDIMain Inherits System.Windows.Forms.Form
‘ declare the objects for the two kinds of forms. ‘ you will instantiate these as and when the user chooses to view these forms using the menu options
213
145-222.qxd 2/24/03 10:45 AM Page 214
Project 1
DATABASE INTEGRATION WITH .NET
‘ you will use the WithEvents keyword so that you can trap the close event of the forms and update menu options accordingly Dim WithEvents instfrmTidByAuthor As frmTitleByAuthor Dim WithEvents instfrmAuthorModify As frmAuthorModify
#Region “ Windows Form Designer generated code “
Public Sub New()
AM FL Y
MyBase.New()
‘This call is required by the Windows Form Designer. InitializeComponent()
‘Add any initialization after the InitializeComponent() call
End Sub
TE
214
‘Form overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub Friend WithEvents mnuModify As System.Windows.Forms.MenuItem Friend WithEvents mnuModAuthorDetails As System.Windows.Forms.MenuItem Friend WithEvents mnuMore As System.Windows.Forms.MenuItem Friend WithEvents mnuEntityModify As System.Windows.Forms.MainMenu Friend WithEvents mnuReports As System.Windows.Forms.MenuItem Friend WithEvents mnuTIDbyAuth As System.Windows.Forms.MenuItem Friend WithEvents mnuMoreReports As System.Windows.Forms.MenuItem Friend WithEvents mnuTIDbyAuthShow As System.Windows.Forms.MenuItem Friend WithEvents mnuTIDbyAuthWriteXML As System.Windows.Forms.MenuItem Friend WithEvents mnuTIDbyAuthWriteXMLSchema As System.Windows.Forms.MenuItem Friend WithEvents mnuTIDbyAuthWriteXMLWithSchema As System.Windows.Forms.MenuItem
Team-Fly®
145-222.qxd 2/24/03 10:45 AM Page 215
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
Friend WithEvents mnuExit As System.Windows.Forms.MenuItem ‘Required by the Windows Form Designer Private components As System.ComponentModel.IContainer
‘NOTE: The following procedure is required by the Windows Form Designer ‘It can be modified using the Windows Form Designer. ‘Do not modify it using the code editor. Private Sub InitializeComponent() Me.mnuEntityModify = New System.Windows.Forms.MainMenu() Me.mnuModify = New System.Windows.Forms.MenuItem() Me.mnuModAuthorDetails = New System.Windows.Forms.MenuItem() Me.mnuMore = New System.Windows.Forms.MenuItem() Me.mnuReports = New System.Windows.Forms.MenuItem() Me.mnuTIDbyAuth = New System.Windows.Forms.MenuItem() Me.mnuTIDbyAuthShow = New System.Windows.Forms.MenuItem() Me.mnuTIDbyAuthWriteXML = New System.Windows.Forms.MenuItem() Me.mnuTIDbyAuthWriteXMLSchema = New System.Windows.Forms.MenuItem() Me.mnuTIDbyAuthWriteXMLWithSchema = New System.Windows.Forms.MenuItem() Me.mnuMoreReports = New System.Windows.Forms.MenuItem() Me.mnuExit = New System.Windows.Forms.MenuItem() ‘ ‘mnuEntityModify ‘ Me.mnuEntityModify.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuModify, Me.mnuReports, Me.mnuExit}) ‘ ‘mnuModify ‘ Me.mnuModify.Index = 0 Me.mnuModify.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuModAuthorDetails, Me.mnuMore}) Me.mnuModify.Text = “&Modify” ‘ ‘mnuModAuthorDetails ‘ Me.mnuModAuthorDetails.Index = 0 Me.mnuModAuthorDetails.Text = “Author Details” ‘
215
145-222.qxd 2/24/03 10:45 AM Page 216
216
Project 1
DATABASE INTEGRATION WITH .NET
‘mnuMore ‘ Me.mnuMore.Enabled = False Me.mnuMore.Index = 1 Me.mnuMore.Text = “more...” ‘ ‘mnuReports ‘ Me.mnuReports.Index = 1 Me.mnuReports.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuTIDbyAuth, Me.mnuMoreReports}) Me.mnuReports.Text = “&Reports” ‘ ‘mnuTIDbyAuth ‘ Me.mnuTIDbyAuth.Index = 0 Me.mnuTIDbyAuth.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuTIDbyAuthShow, Me.mnuTIDbyAuthWriteXML, Me.mnuTIDbyAuthWriteXMLSchema, Me.mnuTIDbyAuthWriteXMLWithSchema}) Me.mnuTIDbyAuth.Text = “Title IDs by Author” ‘ ‘mnuTIDbyAuthShow ‘ Me.mnuTIDbyAuthShow.Index = 0 Me.mnuTIDbyAuthShow.Text = “Show Report” ‘ ‘mnuTIDbyAuthWriteXML ‘ Me.mnuTIDbyAuthWriteXML.Enabled = False Me.mnuTIDbyAuthWriteXML.Index = 1 Me.mnuTIDbyAuthWriteXML.Text = “Write XML” ‘ ‘mnuTIDbyAuthWriteXMLSchema ‘ Me.mnuTIDbyAuthWriteXMLSchema.Enabled = False Me.mnuTIDbyAuthWriteXMLSchema.Index = 2 Me.mnuTIDbyAuthWriteXMLSchema.Text = “Write XML Schema” ‘
145-222.qxd 2/24/03 10:45 AM Page 217
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
‘mnuTIDbyAuthWriteXMLWithSchema ‘ Me.mnuTIDbyAuthWriteXMLWithSchema.Enabled = False Me.mnuTIDbyAuthWriteXMLWithSchema.Index = 3 Me.mnuTIDbyAuthWriteXMLWithSchema.Text = “Write XML with Schema” ‘ ‘mnuMoreReports ‘ Me.mnuMoreReports.Enabled = False Me.mnuMoreReports.Index = 1 Me.mnuMoreReports.Text = “More reports...” ‘ ‘mnuExit ‘ Me.mnuExit.Index = 2 Me.mnuExit.Text = “E&xit” ‘ ‘frmMDIMain ‘ Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(292, 278) Me.IsMdiContainer = True Me.Menu = Me.mnuEntityModify Me.Name = “frmMDIMain” Me.Text = “Entity Details Maintenance”
End Sub
#End Region
Private Sub mnuModAuthorDetails_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuModAuthorDetails.Click instfrmAuthorModify = New frmAuthorModify() ‘ set the parent MdiParent property of frmAuthorModify to ‘ associate it as an MDI child form to the frmMDIMain form ‘ You use the Me opbject to refer to the current instance of frmMDIMain instfrmAuthorModify.MdiParent = Me ‘ Call the Show method of the object of frmAuthorModify to show it
217
145-222.qxd 2/24/03 10:45 AM Page 218
218
Project 1
DATABASE INTEGRATION WITH .NET
instfrmAuthorModify.Show() ‘ Set the width and height of MDI form Me.Width = 447 Me.Height = 427 ‘ set the window state property of instfrmAuthorModify to FormWindowState.Maximized instfrmAuthorModify.WindowState = FormWindowState.Maximized ‘ Disable the mnuModAuthorDetails menu option, as the form is already active now. Me.mnuModAuthorDetails.Enabled = False
End Sub
Private Sub mnuExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuExit.Click ‘ Call the Close() function for the current instance of the form frmMDIMain Me.Close() End Sub
Private Sub mnuTIDbyAuthShow_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTIDbyAuthShow.Click instfrmTidByAuthor = New frmTitleByAuthor() instfrmTidByAuthor.MdiParent = Me instfrmTidByAuthor.Show()
‘ Enable-disable the relevant menu options mnuTIDbyAuthShow.Enabled = False mnuTIDbyAuthWriteXML.Enabled = True mnuTIDbyAuthWriteXMLSchema.Enabled = True mnuTIDbyAuthWriteXMLWithSchema.Enabled = True
‘ Set the width and height of MDI form Me.Width = 516 Me.Height = 474
instfrmTidByAuthor.WindowState = FormWindowState.Maximized
145-222.qxd 2/24/03 10:45 AM Page 219
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
Chapter 6
End Sub
Private Sub mnuTIDbyAuthWriteXML_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTIDbyAuthWriteXML.Click Call instfrmTidByAuthor.prcTIDbyAuthWriteXML() End Sub
Private Sub mnuTIDbyAuthWriteXMLSchema_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTIDbyAuthWriteXMLSchema.Click Call instfrmTidByAuthor.prcTIDbyAuthWriteXMLSchema() End Sub
Private Sub mnuTIDbyAuthWriteXMLWithSchema_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuTIDbyAuthWriteXMLWithSchema.Click Call instfrmTidByAuthor.prcTIDbyAuthWriteXMLWithSchema() End Sub
Private Sub instfrmTidByAuthor_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles instfrmTidByAuthor.Closed ‘ Enable-disable the relevant menu options mnuTIDbyAuthShow.Enabled = True mnuTIDbyAuthWriteXML.Enabled = False mnuTIDbyAuthWriteXMLSchema.Enabled = False mnuTIDbyAuthWriteXMLWithSchema.Enabled = False End Sub
Private Sub instfrmAuthorModify_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles instfrmAuthorModify.Closed ‘ Enable-disable the relevant menu options Me.mnuModAuthorDetails.Enabled = True End Sub
Private Sub frmMDIMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub End Class
219
145-222.qxd 2/24/03 10:45 AM Page 220
220
Project 1
DATABASE INTEGRATION WITH .NET
Set the Startup Object Property for the Project After specifying the code for the forms, you need to specify the order in which the forms should be displayed when the prjDBConnect application is run. It is essential to specify the order in which the forms are displayed because you want to display the frmMDIMain form as the first form of the application. The remaining forms in the application can be displayed as and when the appropriate menu commands are clicked. To accomplish this task, you need to set the startup property for the application by using the Startup object property. To set the Startup object property, you need to perform the following steps: 1. Right click on the project in the Solution Explorer, then select Properties. 2. The prjDBConnect Property Pages dialog box is displayed. The left pane of the dialog box displays a list of property types. Select General from the Common Properties folder. This option is selected by default. Figure 6-28 displays the General option selected from the Common Properties folder. 3. To ensure that the frmMDIMain form is the first form to be displayed when the prjDBConnect application is run, you need to select frmMDIMain from the Startup object drop-down list. Figure 6-29 displays the prjDBConnect Property Pages dialog box with the startup form specified as frmMDIMain.
FIGURE 6-28
The General option selected from the Common Properties folder
145-222.qxd 2/24/03 10:45 AM Page 221
CREATING A WINDOWS APPLICATION IN VISUAL BASIC
FIGURE 6-29
Chapter 6
221
The prjDBConnect Property Pages dialog box with the startup form specified as frmMDIMain
Summary In this chapter, you learned how to design the forms for an application to display report data and update records. You also learned about the requirements and the design of the application. Next, you learned about the working of the application and the code attached to the various controls of the different forms. In addition, you learned to use a combination of DataSet, OleDbDataAdapter, OleDbConnection, and OleDbCommand objects to retrieve and manipulate the data located in an SQL database. In addition, you learned to convert the report data and its associated schema into the XML format. Finally, you used parameterized queries with the OleDbCommand object to modify data by executing a non-query SQL statement.
145-222.qxd 2/24/03 10:45 AM Page 222
This page intentionally left blank
223-304.qxd 2/24/03 10:46 AM Page 223
Chapter 7 Creating a Windows Application in C# Using ADO.NET
223-304.qxd 2/24/03 10:46 AM Page 224
n Chapter 6, you learned to create a Windows application in Visual Basic.NET that was database-centric. To implement the database related features, you had used ADO.NET as the data access technology. In this chapter, you will recreate the same application in C#, which is a new language introduced as part of the .NET language family.
AM FL Y
I
C# Basics
TE
C#, a part of the Visual Studio.NET suite, is an improved version of C++ integrated with the best features of Visual Basic. The combination of the best features of C++ and Visual Basic has arguably made C# the finest programming language available today. You must be really excited to know which new features Microsoft has added. To mention everything in one sentence, C# integrates the power of C++ and the RAD of Visual Basic with a series of features like synchronizing threads, versioning, and garbage collection. You will read about these in detail later in this chapter. All said and done, C# is definitely a leap in the field of programming languages. It allows developers to create a wide range of applications—from high-level business applications to low-level system applications. C# also allows you to make these applications available on the Web by converting the components of the application to XML Web services. Before you create the project in C#, let me discuss the features of C# and its syntax.
Evolution of C# C# evolved because of a giant gap that existed between different programming languages. Although programming languages such as Visual Basic offer RAD environment, they are not flexible enough for low-level programming. C++ and C, the two languages that have ruled the programming world for the past two decades, are powerful enough for low-level programming but development time is high. If you take cost into consideration, they are not productive. If you com-
Team-Fly®
223-304.qxd 2/24/03 10:46 AM Page 225
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
pare the time taken for developing a Visual Basic application and an equivalent C/C++ application, you will find that, more often than not, you can create the Visual Basic application in much less time than it takes to create the equivalent C/C++ application. Many enterprises whose core business was developing applications longed for a better balance between power and cost of development. Many companies introduced languages that bridged the gap to some extent, but then there were gaps in terms of the flexibility and low-level control that C and C++ offered and the applications did not easily interoperate with pre-existing systems. Moreover, Web applications created in such languages did not work efficiently. Java is good for developing Web applications, but Visual Basic and C++ are not the preferred choice for the same. During this period, if you ever asked developers how would they define an ideal programming language, they would say a language that is as powerful as C and C++, provides low-level control, has RAD environment, is in step with the emerging Web standards, and integrates with existing applications. Realizing the above-discussed issues, Microsoft came up with C# to bridge all the gaps among different languages and provide an application development environment that is complete in itself. Before you go any further, you should know what C# has to offer.
Promise of C# In the previous section, you read that C# is a great choice for creating a wide range of applications—from high-level business applications to low-level system applications—and that C# allows you to make these applications available on the Web by converting the components of an application to XML Web services. This is mainly because of its great object-oriented design. In addition, you can convert the applications and their components into XML Web services by using simple C# language constructs. This makes it possible to invoke these applications across the Internet from any language running on any platform. Moreover, shrugging away from original C and C++ development environment, C# has integrated rapid development environment without sacrificing the power and control of C and C++. And because C# has its roots in C and C++, developers familiar with C or C++ will hardly have any hassle creating applications in C#. The next section gives an overview of the salient features of C#.
225
223-304.qxd 2/24/03 10:46 AM Page 226
226
Project 1
DATABASE INTEGRATION WITH .NET
Cross-platform Deployment The compiled code of C# is in byte-stream format and is therefore platform-independent. In other words, compiled code of C# can be understood by any application irrespective of the hardware and software platform. Therefore, for a developer, it implies that a C# application can be easily deployed across platforms without any extra effort.
Productive In this age of fierce competition, developing applications faster and at lower cost is the key to survival. Developers are required to shorten development cycle time and create applications that can be easily upgraded and deployed across platforms. C# is designed with these considerations in mind. The developers can now develop applications with fewer lines of code and thus fewer errors to debug. Moreover, applications are ready to be deployed across platforms.
In Step with the Emerging Web Standards A few years ago, development tools did not cater to the Web requirements because the Web was still in its infancy. However, in this age of the Internet, the application development models require applications to conform to the emerging Web standards, such as XML and SOAP. C# comes with built-in support that allows developers to make applications available on the Web by converting the components of the application to XML Web services, therefore, allowing applications to be invoked over the Internet from any application running on any platform. There are also some features of C# that are very important for efficient Internet programming.
Mechanism for Eliminating Programming Errors In C++, programmers often made the simplest of programming errors, such as not initializing a variable or releasing a variable when it is not required any longer. And when a program behaves unexpectedly because of such simple errors and a programmer spends hours trying to figure out the cause of the problem, it is really unnerving. C# has been designed with mechanisms that virtually eliminate most common programming errors. For instance, C# ships with the garbage collector that checks for objects that an application is not using and deletes them from memory. More-
223-304.qxd 2/24/03 10:46 AM Page 227
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
over, C# automatically initializes the variables on declaration. Unlike C, C# is also type safe, which means that C# ensures that the operations that can be performed on a data type are those allowed by the type of the data. All these mechanisms promise to make C# a far easier programming language for developers to write and maintain applications.
Built-in Versioning Support If you ask any experienced developer about his or her experience on updating applications and their components, more often than not, a lengthy story will unfold and you will see pain in his or her eyes. This is because making revisions to application components is an error-prone task and a developer can unintentionally change the semantics of the application. Microsoft survey teams probably read the pain in the eyes of the developers and passed on the feedback to its C# development team. Good for all developers, C# comes with built-in versioning support. For example, unlike C++, method overriding must be explicit. This helps in preserving versions and avoiding coding errors. C# also supports interfaces and interface inheritance. Together, these features make the process of developing successive versions less costly and overall versioning more forceful.
Interoperability For most applications, managed and type-safe environment is appropriate. However, you would agree that in the real world some applications require native code, either for performance reasons or to interoperate with existing application programming interfaces (APIs). C++ comes in handy in such situations, though it is not that cost effective. C# has a solution for this too. It provides: ◆ Native support for the COM and Windows-based APIs
NOTE With C#, every object is automatically a COM object. C# applications can also natively use existing COM objects, no matter what language was used to develop
◆ Restricted use of native pointers
227
223-304.qxd 2/24/03 10:46 AM Page 228
228
Project 1
DATABASE INTEGRATION WITH .NET
By providing these two features, C# provides the developer with the necessary power and control without leaving the C# environment. The next section introduces variables in C#.
Data Types in C# Now, you must be eager to know the data types that C# offers because this is the first thing a developer looks for in a programming language. Most of the data types in C# are from C and C++. Table 7-1 lists each of these. Table 7-1 Data Types in C# Data Type
Description
bool
Stores Boolean values, TRUE and FALSE
string
Stores a sequence of Unicode characters
char
Stores a 16-bit Unicode character
int
Stores 32-bit signed integers
short
Stores 16-bit signed integers
sbyte
Stores 8-bit signed integers
long
Stores 64-bit signed integers
byte
Stores 8-bit unsigned integers
ushort
Stores 16-bit unsigned integers
uint
Stores 32-bit unsigned integers
ulong
Stores 64-bit unsigned integers
float
Stores single-precision floating point values
double
Stores double-precision floating point values
decimal
Stores precise decimal type values with 28 significant digits
object
This is the base data type for all data types
223-304.qxd 2/24/03 10:46 AM Page 229
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
C# supports two kinds of types, value types and reference types. ◆ Value Types. Value types variables contain the actual data. Simple data types, such as int, char, bool, and enums, are value data types. ◆ Reference Types. Reference type variables store the reference of the actual data. Object data type, classes, interfaces, delegates, and array types are reference data types.
Variables There are seven types of variables in C#. Table 7-2 explains the four most commonly-used variables. Table 7-2 Variables in C# Variable
Description
Static
Can be accessed directly from the class to which it belongs and has a static modifier. A static variable can be accessed without creating an instance of a class. You can only access a static variable when the program in which it is declared is loaded and once the program terminates, the variable becomes inactive.
Instance
Declared without the static modifier.
Array elements
Stores the starting address of an array in memory. To access an array element, you need to create an instance of the array.
Local
Declared within a method. You need to initialize a local variable. This type of variable can be accessed only when the program that contains the local variable is executing.
Creating a Windows Application In this chapter, you will use C# to create the same project you created in the last chapter. Based on the blueprint created in the design phase of the last chapter, the
229
223-304.qxd 2/24/03 10:46 AM Page 230
230
Project 1
DATABASE INTEGRATION WITH .NET
team of programmers began creating the application. The steps to create the application are: 1. Create a new project. 2. Create the Titles Authored by Each Author form. 3. Create the Author Details Modification form. 4. Create the Entity Details Maintenance form. 5. Set the Startup Object property for the project. You will now learn about each step in detail.
Create New Project As per requirements, the application needs to be created as a Windows application. To create a new Windows application project, you need to perform the following steps: 1. On the File menu, click on the New command and then click on the Project command. Figure 7-1 displays the selected Project command. 2. Figure 7-2 displays the New Project dialog box obtained after clicking on the required menu commands.
TIP An alternate way to access the New Project dialog box is to click on the Ctrl, Shift, and N keys simultaneously. You can also access the New Project dialog box by clicking on the New Project button that appears on the Start Page.
3. To create a project in C#, you need to select the Visual C# Projects option from the Project Types pane. 4. The Templates pane displays the list of project templates available for Visual C# Projects. To create a Windows-based application in C#, you need to select the Windows Application option from the Templates pane, as shown in Figure 7-3.
223-304.qxd 2/24/03 10:46 AM Page 231
CREATING A WINDOWS APPLICATION IN C#
FIGURE 7-1 Selected Project command on the File menu
FIGURE 7-2 The New Project dialog box
Chapter 7
231
223-304.qxd 2/24/03 10:46 AM Page 232
232
Project 1
DATABASE INTEGRATION WITH .NET
FIGURE 7-3 The selected Windows Application option from the Templates pane
5. To name the project, type prjDBConnect in the Name text box. 6. Next, to accept the default location for saving the project, click on the OK button. By default, the new project will be created in C:\Documents and Settings\admin\My Documents\Visual Studio Projects. Upon clicking on the OK button, the Visual Studio.NET window displays a new project with a blank form in the design mode. Figure 7-4 displays the Visual Studio.NET window after the project prjDBConnect is created. As you learned in the last chapter, Visual Studio.NET creates a Windows Form that you can customize as per your requirements. You can now use the project to create the user interface for the report application. The Title bar of the Visual Studio.NET window displays the name of the project and the default name of the form. By default, the name of the form is Form1. In addition, a solution is created automatically when you create the new project. The corresponding solution for the project called prjDBConnect is created automatically. Now that you have created a solution and a project within, you need to create the forms in your application.
223-304.qxd 2/24/03 10:46 AM Page 233
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
FIGURE 7-4 The Visual Studio.NET window after the project prjDBConnect is created
Create the Titles Authored by Each Author Form The Titles Authored by Each Author form will display data in a tabular format. The steps to create the Titles Authored by Each Author form are described in the following list: 1. Rename the form as frmTitleByAuthor by modifying the Name property. 2. Change the Text property of the form to Titles Authored by Each Author. Figure 7-5 displays the Properties window with the modified value of the Text property. This figure also displays the changed name of the form. 3. Increase the display area of the form to ensure that all the columns with the required data are displayed in the Authors and Titles report. 4. After resizing the form, you need to place controls on the form. To display data in a tabular format, you need to add a ListView control and rename it as lvReport. The ListView control includes grid lines to display data in rows and columns. 5. Next, you need to resize the lvReport control to cover a large area of the form in the background and display report data with ease. Figure 7-6 shows the default display of the lvReport control.
233
223-304.qxd 2/24/03 10:46 AM Page 234
DATABASE INTEGRATION WITH .NET
AM FL Y
Project 1
FIGURE 7-5 The Properties window with modified Text property
TE
234
FIGURE 7-6 The default display of the lvReport control
By default, as displayed in Figure 7-6, the lvReport control does not display any rows or columns. Therefore, to display rows and columns in the lvReport control, you need to set the GridLines property of the control to True. To accomplish this task, you can double-click on the GridLines property in the Properties window. Figure 7-7 displays the GridLines property set to True.
Team-Fly®
223-304.qxd 2/24/03 10:46 AM Page 235
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
FIGURE 7-7 Properties window displaying the GridLines property as True
TIP Alternately, you can click on the GridLines property and then select the True option
Next, you need to add headers to the columns. To add column headers to the ListView control, you need to perform the following steps: 1. Click on the Columns property in the Properties window. Figure 7-8 displays the Columns property. 2. Select the Columns property, and then click on the Ellipsis button. 3. The ColumnHeader Collection Editor dialog box is displayed. You use this dialog box to add or remove columns to a ListView control and view or modify the properties of the columns. Figure 7-9 displays the dialog box. 4. To add a column to the ListView control, click on the Add button. By default, the name of the column header is ColumnHeader1. The properties of the newly added column header are displayed in the adjoining pane. 5. You need to specify the text that is displayed as the column header in the Authors and Titles report. To change the display name of the column
235
223-304.qxd 2/24/03 10:46 AM Page 236
236
Project 1
DATABASE INTEGRATION WITH .NET
FIGURE 7-8 Properties window displaying the Columns property
FIGURE 7-9 The ColumnHeader Collection Editor dialog box
header to Author ID, you need to double-click on the Text property under the Misc set of properties. Figure 7-10 displays the dialog box with the modified Text property.
223-304.qxd 2/24/03 10:46 AM Page 237
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
FIGURE 7-10 The ColumnHeader Collection Editor dialog box with the modified Text property
6. Similarly, you can add multiple columns to the ListView control and name the columns appropriately, as decided in the requirements phase, by repeating Steps 4 and 5. After adding the required columns, you need to click on the OK button. 7. Next, you need to set the View property to Details. Figure 7-11 displays the Properties window with the View property set to Details. After the grid lines and the columns are added to the Windows form, the form will be displayed as shown in Figure 7-12. After the required controls are added to the main form and appropriately named, you need to specify the code for the appropriate events of the controls. The Windows Forms Designer generates some code by default. You will now look at the code that you need to specify in addition to the code that is generated by default. To learn more about the code that is generated by default by the Windows Forms Designer, you may refer to the Appendix. The procedures for which you need to specify code for the Titles Authored by Each Author form are listed. ◆ prcTIDbyAuthWriteXML ◆ prcTIDbyAuthWriteXMLSchema
237
223-304.qxd 2/24/03 10:46 AM Page 238
238
Project 1
DATABASE INTEGRATION WITH .NET
FIGURE 7-11 The Properties window with the View property set to Details
FIGURE 7-12 Windows form after the columns and their respective headers are added
◆ prcTIDbyAuthWriteXMLWithSchema ◆ frmTitleByAuthor_Load
223-304.qxd 2/24/03 10:46 AM Page 239
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
Before I discuss the procedures, I will describe the steps to configure the data adapter and establish a connection. You need to do so in order to make the data stored in the database available in your application. 1. In the Server Explorer, expand the Servers node. The list of all the available servers appears as the child nodes. 2. Expand the appropriate Server node. All the available SQL Servers appear as nodes. 3. Expand the appropriate SQL Server node. The list of databases appears. 4. Expand the appropriate database node. 5. From the Tables node, click on and drag the appropriate table. The sqlDataAdapter1 and sqlConnection1 controls appear on the form. 6. Select Data, Generate Dataset command to create a dataset named dsAuth. With this you have established a connection with the database. You’ve also configured a data adapter control. I will now discuss the procedures to be created for the form.
The prcTIDbyAuthWriteXML Procedure The prcTIDbyAuthWriteXML procedure calls the WriteXml() method to write data from the dsAuth1 object to an XML file. The XML file is stored in the same folder where the project and solution file for the project are stored. Listing 7-1 lists the code for the prcTIDbyAuthWriteXML procedure. Listing 7-1 Code for the prcTIDbyAuthWriteXML Procedure public void prcTIDbyAuthWriteXML() { // Check if DataSet has been instantiated if(dsAuth1 != null) { // Use the WriteXml method of the dataset object to persist the data contained in the dataset into an XML file in application path dsAuth1.WriteXml(Application.StartupPath + “\\” + “XMLData.XML”, XmlWriteMode.IgnoreSchema); } }
239
223-304.qxd 2/24/03 10:46 AM Page 240
240
Project 1
DATABASE INTEGRATION WITH .NET
The prcTIDbyAuthWriteXMLSchema Procedure The prcTIDbyAuthWriteXMLSchema procedure uses the WriteXmlSchema() method to save the schema of the report data in a file called XMLSchema.XML. This file is stored in the same folder where the project and solution file for the project are stored. Listing 7-2 lists the code for the prcTIDbyAuthWriteXMLSchema procedure. Listing 7-2 Code for the prcTIDbyAuthWriteXMLSchema Procedure public void prcTIDbyAuthWriteXMLSchema() { // Check if DataSet has been instantiated if(dsAuth1 != null) { // Use the the WriteXmlSchema method of the DataSet object to persist the // XML schema corresponding to the data contents of the DataSet, // into an XML file in application path dsAuth1.WriteXmlSchema(Application.StartupPath + “\\” + “XMLSchema.XML”); } }
The prcTIDbyAuthWriteXMLWithSchema Procedure The prcTIDbyAuthWriteXMLWithSchema procedure uses the WriteXml() method to save the data and the schema of the report in a file called XMLData_with_Schema.XML. This file is stored in the same folder where the project and solution file for the project are stored. Listing 7-3 lists the code for the prcTIDbyAuthWriteXMLWithSchema procedure. Listing 7-3 Code for the prcTIDbyAuthWriteXMLWithSchema Procedure public void prcTIDbyAuthWriteXMLWithSchema() { // Check if DataSet has been instantiated if(dsAuth1 != null) { // Use the WriteXml method of the DataSet object to persist the data
223-304.qxd 2/24/03 10:46 AM Page 241
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
contained in the dataset in XML format,along with corresponding schema dsAuth1.WriteXml(Application.StartupPath + “\\” + “XMLData_with_Schema.XML”, XmlWriteMode.WriteSchema); } }
The frmTitleByAuthor_Load Procedure The frmTitleByAuthor_Load procedure is called when frmTitleByAuthor is loaded. This procedure is used to load the values stored in the tables contained inside the database in the ListView control. Listing 7-4 lists the code for the procedure. Listing 7-4 Code for the frmTitleByAuthor_Load Procedure private void frmTitleByAuthor_Load(object sender, System.EventArgs e) { sqlDataAdapter1.Fill(dsAuth1, “Authors”); SqlCommand SqlCmd; string SqlStr = “select distinct titleauthor.au_id,titles.title_id,titles.title from titleauthor,titles where titleauthor.title_id=titles.title_id”;
try { SqlCmd = new SqlCommand(SqlStr,sqlConnection1); sqlDataAdapter1.SelectCommand = SqlCmd; if(sqlConnection1.State == ConnectionState.Closed) { sqlConnection1.Open(); }
sqlDataAdapter1.SelectCommand.ExecuteNonQuery (); sqlDataAdapter1.Fill(dsAuth1,”TitleAuthor”);
//Establishing a relation between two tables
dsAuth1.Relations.Add(“author_titleauthor”,
241
223-304.qxd 2/24/03 10:46 AM Page 242
242
Project 1
DATABASE INTEGRATION WITH .NET
dsAuth1.Tables[“authors”].Columns[“au_id”], dsAuth1.Tables[“titleauthor”].Columns[“au_id”]).Nested = true;
foreach (DataRow rowPicker1 in dsAuth1.Tables[“authors”].Rows) { string []strArrAuthorDetails ; strArrAuthorDetails = new string [] {rowPicker1[“au_ID”].ToString(), rowPicker1[“au_fname”].ToString () + “, “ + rowPicker1[“au_lname”]};
lvReport.Items.Add(new ListViewItem(strArrAuthorDetails));
// Iterate through child rows(in the related table) to get title information for the current author // To display all titles written by author and their advance foreach(DataRow rowPicker2 in rowPicker1.GetChildRows(dsAuth1.Relations[“author_titleauthor”])) { string [] strArrTitleAuthorDetails = {“”, “”, rowPicker2[“title_ID”].ToString (), rowPicker2[“title”].ToString()}; lvReport.Items.Add(new ListViewItem(strArrTitleAuthorDetails)); } } sqlConnection1.Close(); } catch(Exception E1) { MessageBox.Show(“The following error occured \n” + E1.Message, “Error”); } }
Apart from the aforementioned procedures, the most important piece of code in your application is the code related to the inclusion of namespaces. The inclusion of namespaces is done in the form class file. You include the namespaces that contain the classes that will be used in the code of the application. In this application, you need to include the following two namespaces: using System.Data; using System.Data.SqlClient;
223-304.qxd 2/24/03 10:46 AM Page 243
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
The following listing, Listing 7-5, consists of the code for the frmTitleByAuthor.cs form. Listing 7-5 frmTitleByAuthor.cs using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Data.SqlClient;
namespace slnDBConnect { /// /// Summary description for frmTitleByAuthor. /// public class frmTitleByAuthor : System.Windows.Forms.Form { private System.Windows.Forms.ColumnHeader columnHeader1; private System.Windows.Forms.ColumnHeader columnHeader2; private System.Windows.Forms.ColumnHeader columnHeader3; private System.Windows.Forms.ColumnHeader columnHeader4; private System.Data.SqlClient.SqlCommand sqlSelectCommand1; private System.Data.SqlClient.SqlCommand sqlInsertCommand1; private System.Data.SqlClient.SqlCommand sqlUpdateCommand1; private System.Data.SqlClient.SqlCommand sqlDeleteCommand1; private System.Data.SqlClient.SqlConnection sqlConnection1; private System.Data.SqlClient.SqlDataAdapter sqlDataAdapter1; private slnDBConnect.dsAuth dsAuth1; private System.Windows.Forms.ListView lvReport;
/// /// Required designer variable. /// private System.ComponentModel.Container components = null; public frmTitleByAuthor()
243
223-304.qxd 2/24/03 10:46 AM Page 244
Project 1
DATABASE INTEGRATION WITH .NET
{ // Required for Windows Form Designer support InitializeComponent();
// TODO: Add any constructor code after InitializeComponent call } /// /// Clean up any resources being used.
AM FL Y
////
protected override void Dispose( bool disposing ) {
if( disposing ) {
if(components != null) {
components.Dispose();
TE
244
}
}
base.Dispose( disposing ); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. ///
private void InitializeComponent() { this.lvReport = new System.Windows.Forms.ListView(); this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); this.columnHeader3 = new System.Windows.Forms.ColumnHeader(); this.columnHeader4 = new System.Windows.Forms.ColumnHeader(); this.sqlSelectCommand1 = new System.Data.SqlClient.SqlCommand(); this.sqlInsertCommand1 = new System.Data.SqlClient.SqlCommand(); this.sqlUpdateCommand1 = new System.Data.SqlClient.SqlCommand(); this.sqlDeleteCommand1 = new System.Data.SqlClient.SqlCommand();
Team-Fly®
223-304.qxd 2/24/03 10:46 AM Page 245
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
this.sqlConnection1 = new System.Data.SqlClient.SqlConnection(); this.sqlDataAdapter1 = new System.Data.SqlClient.SqlDataAdapter(); this.dsAuth1 = new slnDBConnect.dsAuth(); ((System.ComponentModel.ISupportInitialize)(this.dsAuth1)).BeginInit(); this.SuspendLayout(); // // lvReport // this.lvReport.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.columnHeader1, this.columnHeader2, this.columnHeader3, this.columnHeader4}); this.lvReport.GridLines = true; this.lvReport.Location = new System.Drawing.Point(80, 48); this.lvReport.Name = “lvReport”; this.lvReport.Size = new System.Drawing.Size(800, 584); this.lvReport.TabIndex = 0; this.lvReport.View = System.Windows.Forms.View.Details; // // columnHeader1 // this.columnHeader1.Text = “Author ID”; this.columnHeader1.Width = 98; // // columnHeader2 // this.columnHeader2.Text = “Author Name”; this.columnHeader2.Width = 125; // // columnHeader3 // this.columnHeader3.Text = “Title ID”; this.columnHeader3.Width = 89; // // columnHeader4 // this.columnHeader4.Text = “Title Name”; this.columnHeader4.Width = 541;
245
223-304.qxd 2/24/03 10:46 AM Page 246
246
Project 1
DATABASE INTEGRATION WITH .NET
// // sqlSelectCommand1 // this.sqlSelectCommand1.CommandText = “SELECT au_id, au_lname, au_fname, phone, address, city, state, zip, contract FROM” + “ authors”; this.sqlSelectCommand1.Connection = this.sqlConnection1; // // sqlInsertCommand1 // this.sqlInsertCommand1.CommandText = @”INSERT INTO authors(au_id, au_lname, au_fname, phone, address, city, state, zip, contract) VALUES (@au_id, @au_lname, @au_fname, @phone, @address, @city, @state, @zip, @contract); SELECT au_id, au_lname, au_fname, phone, address, city, state, zip, contract FROM authors WHERE (au_id = @au_id)”; this.sqlInsertCommand1.Connection = this.sqlConnection1; this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_id”, System.Data.SqlDbType.VarChar, 11, “au_id”));
this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_lname”, System.Data.SqlDbType.VarChar, 40, “au_lname”));
this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_fname”, System.Data.SqlDbType.VarChar, 20, “au_fname”));
this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@phone”, System.Data.SqlDbType.VarChar, 12, “phone”)); this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@address”, System.Data.SqlDbType.VarChar, 40, “address”)); this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@city”, System.Data.SqlDbType.VarChar, 20, “city”));
223-304.qxd 2/24/03 10:46 AM Page 247
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@state”, System.Data.SqlDbType.VarChar, 2, “state”)); this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@zip”, System.Data.SqlDbType.VarChar, 5, “zip”));
this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@contract”, System.Data.SqlDbType.Bit, 1, “contract”));
// // sqlUpdateCommand1 // this.sqlUpdateCommand1.CommandText = @”UPDATE authors SET au_id = @au_id, au_lname = @au_lname, au_fname = @au_fname, phone = @phone, address = @address, city = @city, state = @state, zip = @zip, contract = @contract WHERE (au_id = @Original_au_id) AND (address = @Original_address OR @Original_address IS NULL AND address IS NULL) AND (au_fname = @Original_au_fname) AND (au_lname = @Original_au_lname) AND (city = @Original_city OR @Original_city IS NULL AND city IS NULL) AND (contract = @Original_contract) AND (phone = @Original_phone) AND (state = @Original_state OR @Original_state IS NULL AND state IS NULL) AND (zip = @Original_zip OR @Original_zip IS NULL AND zip IS NULL); SELECT au_id, au_lname, au_fname, phone, address, city, state, zip, contract FROM authors WHERE (au_id = @au_id)”; this.sqlUpdateCommand1.Connection = this.sqlConnection1; this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_id”, System.Data.SqlDbType.VarChar, 11, “au_id”)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_lname”, System.Data.SqlDbType.VarChar, 40, “au_lname”)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_fname”, System.Data.SqlDbType.VarChar, 20, “au_fname”)); this.sqlUpdateCommand1.Parameters.Add(new
247
223-304.qxd 2/24/03 10:46 AM Page 248
248
Project 1
DATABASE INTEGRATION WITH .NET
System.Data.SqlClient.SqlParameter(“@phone”, System.Data.SqlDbType.VarChar, 12, “phone”)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@address”, System.Data.SqlDbType.VarChar, 40, “address”)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@city”, System.Data.SqlDbType.VarChar, 20, “city”)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@state”, System.Data.SqlDbType.VarChar, 2, “state”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@zip”, System.Data.SqlDbType.VarChar, 5, “zip”)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@contract”, System.Data.SqlDbType.Bit, 1, “contract”)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_id”, System.Data.SqlDbType.VarChar, 11, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_id”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_address”, System.Data.SqlDbType.VarChar, 40, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “address”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_fname”, System.Data.SqlDbType.VarChar, 20, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_fname”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_lname”,
223-304.qxd 2/24/03 10:46 AM Page 249
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
System.Data.SqlDbType.VarChar, 40, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_lname”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_city”, System.Data.SqlDbType.VarChar, 20, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “city”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_contract”, System.Data.SqlDbType.Bit, 1, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “contract”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_phone”, System.Data.SqlDbType.VarChar, 12, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “phone”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_state”, System.Data.SqlDbType.VarChar, 2, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “state”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_zip”, System.Data.SqlDbType.VarChar, 5, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “zip”, System.Data.DataRowVersion.Original, null)); // // sqlDeleteCommand1 // this.sqlDeleteCommand1.CommandText = @”DELETE FROM authors WHERE (au_id = @Original_au_id) AND (address = @Original_address OR
249
223-304.qxd 2/24/03 10:46 AM Page 250
250
Project 1
DATABASE INTEGRATION WITH .NET
@Original_address IS NULL AND address IS NULL) AND (au_fname = @Original_au_fname) AND (au_lname = @Original_au_lname) AND (city = @Original_city OR @Original_city IS NULL AND city IS NULL) AND (contract = @Original_contract) AND (phone = @Original_phone) AND (state = @Original_state OR @Original_state IS NULL AND state IS NULL) AND (zip = @Original_zip OR @Original_zip IS NULL AND zip IS NULL)”; this.sqlDeleteCommand1.Connection = this.sqlConnection1; this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_id”, System.Data.SqlDbType.VarChar, 11, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_id”, System.Data.DataRowVersion.Original, null)); this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_address”, System.Data.SqlDbType.VarChar, 40, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “address”, System.Data.DataRowVersion.Original, null)); this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_fname”, System.Data.SqlDbType.VarChar, 20, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_fname”, System.Data.DataRowVersion.Original, null)); this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_lname”, System.Data.SqlDbType.VarChar, 40, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_lname”, System.Data.DataRowVersion.Original, null)); this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_city”, System.Data.SqlDbType.VarChar, 20, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “city”, System.Data.DataRowVersion.Original, null));
223-304.qxd 2/24/03 10:46 AM Page 251
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_contract”, System.Data.SqlDbType.Bit, 1, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “contract”, System.Data.DataRowVersion.Original, null)); this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_phone”, System.Data.SqlDbType.VarChar, 12, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “phone”, System.Data.DataRowVersion.Original, null)); this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_state”, System.Data.SqlDbType.VarChar, 2, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “state”, System.Data.DataRowVersion.Original, null)); this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_zip”, System.Data.SqlDbType.VarChar, 5, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “zip”, System.Data.DataRowVersion.Original, null)); // // sqlConnection1 // this.sqlConnection1.ConnectionString = “data source=NPANDEYD185;initial catalog=pubs;persist security info=False;user id” + “=sa;workstation id=YS-D185;packet size=4096”; // // sqlDataAdapter1 // this.sqlDataAdapter1.DeleteCommand = this.sqlDeleteCommand1; this.sqlDataAdapter1.InsertCommand = this.sqlInsertCommand1; this.sqlDataAdapter1.SelectCommand = this.sqlSelectCommand1; this.sqlDataAdapter1.TableMappings.AddRange(new System.Data.Common.DataTableMapping[] { new System.Data.Common.DataTableMapping(“Table”, “authors”,
251
223-304.qxd 2/24/03 10:46 AM Page 252
252
Project 1
DATABASE INTEGRATION WITH .NET
new System.Data.Common.DataColumnMapping[] { new stem.Data.Common.DataColumnMapping(“au_id”, “au_id”),
new System.Data.Common.DataColumnMapping(“au_lname”, “au_lname”), new System.Data.Common.DataColumnMapping(“au_fname”, “au_fname”), new System.Data.Common.DataColumnMapping(“phone”, “phone”), new System.Data.Common.DataColumnMapping(“address”, “address”), new System.Data.Common.DataColumnMapping(“city”, “city”), new System.Data.Common.DataColumnMapping(“state”, “state”), new System.Data.Common.DataColumnMapping(“zip”, “zip”), new System.Data.Common.DataColumnMapping(“contract”, “contract”)})}); this.sqlDataAdapter1.UpdateCommand = this.sqlUpdateCommand1; // // dsAuth1 // this.dsAuth1.DataSetName = “dsAuth”; this.dsAuth1.Locale = new System.Globalization.CultureInfo(“en-US”); this.dsAuth1.Namespace = “http://www.tempuri.org/dsAuth.xsd”; // // frmTitleByAuthor // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(912, 581); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.lvReport}); this.Name = “frmTitleByAuthor”; this.Text = “Titles by Author”; this.WindowState = System.Windows.Forms.FormWindowState.Maximized; this.Load += new System.EventHandler(this.frmTitleByAuthor_Load); ((System.ComponentModel.ISupportInitialize)(this.dsAuth1)).EndInit(); this.ResumeLayout(false);
} #endregion
private void frmTitleByAuthor_Load(object sender, System.EventArgs e) {
223-304.qxd 2/24/03 10:46 AM Page 253
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
sqlDataAdapter1.Fill(dsAuth1, “Authors”); SqlCommand SqlCmd; string SqlStr = “select distinct titleauthor.au_id,titles.title_id,titles.title from titleauthor,titles where titleauthor.title_id=titles.title_id”;
try { SqlCmd = new SqlCommand(SqlStr,sqlConnection1); sqlDataAdapter1.SelectCommand = SqlCmd; if(sqlConnection1.State == ConnectionState.Closed) { sqlConnection1.Open(); } sqlDataAdapter1.SelectCommand.ExecuteNonQuery (); sqlDataAdapter1.Fill(dsAuth1,”TitleAuthor”); //Establishing a relation between two tables
dsAuth1.Relations.Add(“author_titleauthor”, dsAuth1.Tables[“authors”].Columns[“au_id”], dsAuth1.Tables[“titleauthor”].Columns[“au_id”]).Nested = true;
foreach (DataRow rowPicker1 in dsAuth1.Tables[“authors”].Rows) {
string []strArrAuthorDetails ; strArrAuthorDetails = new string [] {rowPicker1[“au_ID”].ToString (), rowPicker1[“au_fname”].ToString () + “, “ + rowPicker1[“au_lname”]};
lvReport.Items.Add(new ListViewItem(strArrAuthorDetails));
// Iterate through child rows(in the related table) to get title information for the current author // To display all titles written by author and their advance.
253
223-304.qxd 2/24/03 10:46 AM Page 254
Project 1
DATABASE INTEGRATION WITH .NET
foreach(DataRow rowPicker2 in rowPicker1.GetChildRows(dsAuth1.Relations[“author_titleauthor”])) { string [] strArrTitleAuthorDetails = {“”, “”, rowPicker2[“title_ID”].ToString (), rowPicker2[“title”].ToString()}; lvReport.Items.Add(new ListViewItem(strArrTitleAuthorDetails)); }
AM FL Y
}
sqlConnection1.Close(); }
catch(Exception E1) {
MessageBox.Show(“The following error occured \n” + E1.Message, “Error”) ;
TE
254
}
} public void prcTIDbyAuthWriteXML() { // Check if DataSet has been instantiated if(dsAuth1 != null) { // Use the WriteXml method of the dataset object to persist the data contained in the dataset into an XML file in application path dsAuth1.WriteXml(Application.StartupPath + “\\” + “XMLData.XML”, XmlWriteMode.IgnoreSchema); } } public void prcTIDbyAuthWriteXMLSchema() { // Check if DataSet has been instantiated
Team-Fly®
223-304.qxd 2/24/03 10:46 AM Page 255
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
if(dsAuth1 != null) { // Use the the WriteXmlSchema method of the DataSet object to persist the XML schema corresponding to the data contents of the DataSet, // into an XML file in application path dsAuth1.WriteXmlSchema(Application.StartupPath + “\\” + “XMLSchema.XML”); } }
public void prcTIDbyAuthWriteXMLWithSchema() { // Check if DataSet has been instantiated if(dsAuth1 != null) { // Use the WriteXml method of the DataSet object to persist the data contained in the dataset in XML format,along with corresponding schema dsAuth1.WriteXml(Application.StartupPath + “\\” + “XMLData_with_Schema.XML”, XmlWriteMode.WriteSchema); } }
} }
Create Author Details Modification Form You now need to create the Author Details Modification form and add the associated controls on the form. To add a form to the application, perform the following steps: 1. Click on Add New Item from the File menu. 2. The Add New Item dialog box is displayed. Figure 7-13 shows the dialog box.
255
223-304.qxd 2/24/03 10:46 AM Page 256
256
Project 1
DATABASE INTEGRATION WITH .NET
FIGURE 7-13 The Add New Item dialog box
TIP Alternately, you can display the Add New Item dialog box by clicking on the Ctrl, Shift, and A keys simultaneously.
3. To add a form, select the Windows Form option from the Templates pane. 4. Specify the name of the new form as frmAuthorModify.cs in the Name text box. Figure 7-14 displays the Add New Item dialog box with the modified name value. 5. Click on the Open button to create a new form. A new form as shown in Figure 7-15 is displayed. Next, you need to add controls on the form. You can refer to Figure 6-4 (in the last chapter) for the controls to be added to the form. As seen in the figure, the form consists of a drop-down list that displays the authors associated with TecPublishers. It also displays the details of the selected author in a non-editable state. The form also has options to modify, save, or to cancel a modifying operation. You will add the controls as listed in Table 7-3.
223-304.qxd 2/24/03 10:46 AM Page 257
CREATING A WINDOWS APPLICATION IN C#
FIGURE 7-14 Add New Item dialog box with the modified name value
FIGURE 7-15 The new form added to the application
Chapter 7
257
223-304.qxd 2/24/03 10:46 AM Page 258
258
Project 1
DATABASE INTEGRATION WITH .NET
Table 7-3 Controls to be Added to frmAuthorModify Control Name
Control Type
Functionality
ddlAuthors
System.Windows.Forms.ComboBox
Lists all authors
txtID
System.Windows.Forms.TextBox
Displays author ID
txtLname
System.Windows.Forms.TextBox
Displays author last name
txtFname
System.Windows.Forms.TextBox
Displays author first name
txtPhone
System.Windows.Forms.TextBox
Displays author phone number
txtAddress
System.Windows.Forms.TextBox
Displays author address
txtCity
System.Windows.Forms.TextBox
Displays author city
txtState
System.Windows.Forms.TextBox
Displays author state
txtZip
System.Windows.Forms.TextBox
Displays author zip
txtContract
System.Windows.Forms.TextBox
Displays author contract type
Label1-Label10
System.Windows.Forms.Label
Labels various controls
btnModify authordetails
System.Windows.Forms.Button
Allows modification of
btnSave
System.Windows.Forms.Button
Saves the modified author details
btnCancel
System.Windows.Forms.Button
Clears all the text boxes
After adding the required controls to the form, you need to set the property of the controls. For instance, you need to set the Text property of all the various controls on the form. In addition, you need to change the Enabled property for txtID, grpDetails, btnModify, BtnSave, and BtnCancel to False. Next, you need to add code for the frmAuthorModify form. Before writing the code, you need to configure a data adapter and establish a connection with the database. To do so, repeat the same set of steps as mentioned earlier. In this case the control names are as follows, sqlDataAdapter1, sqlConnection1, and dsAuthors1. Listing 7-6 displays the code for the Load event of frmAuthorModify. When the form loads, the frmAuthorModify_Load event fires. In this event procedure, the
223-304.qxd 2/24/03 10:46 AM Page 259
CREATING A WINDOWS APPLICATION IN C#
author name list is populated with the records from the object.
Chapter 7
dsAuthors1
DataSet
Listing 7-6 The frmAuthorModify_Load Method private void frmAuthorModify_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here sqlDataAdapter1.Fill (dsAuthors1, “Authors”); int count; count = dsAuthors1.Tables[“Authors”].Rows.Count; strArrAuID = new string [count]; int idCtr; idCtr=0; foreach (DataRow rowPicker1 in dsAuthors1.Tables[“Authors”].Rows) { ddlAuthors.Items.Add(rowPicker1[“au_fname”] + “ “ + rowPicker1[“au_lname”]); strArrAuID[idCtr] = rowPicker1[“au_id”].ToString() ; idCtr++; } }
Next, you need to add code for the Click events of the Modify, Save, and Cancel buttons, respectively. The following code snippet lists the code for the Click event of the Modify button. private void btnModify_Click(object sender, System.EventArgs e) { ddlAuthors.Enabled = false; txtID.Enabled = false; txtLName.Enabled = true; txtFName.Enabled = true; txtPhone.Enabled = true; txtAddress.Enabled = true; txtCity.Enabled = true; txtState.Enabled = true; txtZip.Enabled = true; txtContract.Enabled = true;
259
223-304.qxd 2/24/03 10:46 AM Page 260
260
Project 1
DATABASE INTEGRATION WITH .NET
btnCancel.Enabled = true; btnSave.Enabled = true; btnModify.Enabled = false; btnError.Visible = false; btnDone.Visible = false; grpStatus.Visible = false; }
The following code snippet lists the code for the Click event of the Save button. private void btnSave_Click(object sender, System.EventArgs e) { //Check for an missing values if (txtFName.Text.Length == 0 | txtLName.Text.Length == 0 | txtPhone.Text.Length == 0 | txtAddress.Text.Length == 0 | txtCity.Text.Length ==0 | txtState.Text.Length == 0 | txtZip.Text.Length==0 | txtContract.Text.Length ==0) { lblInfo.ForeColor = Color.Red; lblInfo.Text = “Details Missing!!”; lblInfo.Visible = true; btnError.Visible = true; grpStatus.Visible = true; return; }
//Create the string to update records string strSQL; strSQL = “update authors set “ + “au_lname = @LN ,” + “au_fname = @FN ,” + “phone = @PH ,” + “address = @AD ,” + “city = @CI ,” + “state = @ST ,” +
223-304.qxd 2/24/03 10:46 AM Page 261
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
“zip= @ZI ,” + “contract = @CO “ + “where au_id= @ID”;
//Check whether the connection is Open try { if (sqlConnection1.State != ConnectionState.Open ) { sqlConnection1.Open (); }
//Create a SqlCommand object SqlCommand myComm; myComm = new SqlCommand(strSQL,sqlConnection1); //Assign the SqlCommand object to the UpdateCommand property of the Data Adapter sqlDataAdapter1.UpdateCommand = myComm; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@LN”, SqlDbType.VarChar, 20).Value = txtLName.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@FN”, SqlDbType.VarChar, 40).Value = txtFName.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@PH”,SqlDbType.Char, 12).Value = txtPhone.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@AD”,SqlDbType.VarChar , 40).Value = txtAddress.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@CI”,SqlDbType.VarChar, 20).Value = txtCity.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@ST”,SqlDbType.Char, 2).Value = txtState.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@ZI”,SqlDbType.Char, 5).Value = txtZip.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@CO”,SqlDbType.Bit).Value = Convert.ToBoolean(txtContract.Text ); sqlDataAdapter1.UpdateCommand.Parameters.Add(“@ID”,SqlDbType.VarChar, 11).Value = txtID.Text;
//Execute the Update Command
261
223-304.qxd 2/24/03 10:46 AM Page 262
262
Project 1
DATABASE INTEGRATION WITH .NET
sqlDataAdapter1.UpdateCommand.ExecuteNonQuery (); } catch(Exception E1) { lblInfo.ForeColor = Color.Red; lblInfo.Text = “The following error occured: \n” + E1.Message ; btnDone.Visible = false; btnError.Visible = true; grpStatus.Visible = true; }
//Display to the user that the records was updated successfully lblInfo.Text = “Record updated!! \n Author ID: “ + txtID.Text; lblInfo.ForeColor = Color.Blue; btnDone.Visible = true; btnError.Visible = false; grpStatus.Visible = true; // Code to manipulate controls ddlAuthors.Enabled = true; txtID.Enabled = false; txtLName.Enabled = false; txtFName.Enabled = false; txtPhone.Enabled = false; txtAddress.Enabled = false; txtCity.Enabled = false; txtState.Enabled = false; txtZip.Enabled = false; txtContract.Enabled = false; btnCancel.Enabled = false; btnSave.Enabled = false; btnModify.Enabled = true; }
The preceding code uses a parameterized SQL statement to update the record for an author. In the statement, you create a string that contains an SQL query along with embedded placeholders for parameters. The embedded placeholders are
223-304.qxd 2/24/03 10:46 AM Page 263
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
marked using the @ symbol followed by a name, such as @ID. You use this string with an SqlConnection object to initialize an SqlCommand object. Next, you assign this SqlCommand object to the InsertCommannd property of the sqlDataAdapter1 object. Then you add parameters to the Parameters collection of the SelectCommand property of the SqlDataAdapter object. While adding parameters to the collection, it is critical to add them in the same sequence as the corresponding placeholders in the parameterized query string. It is also a good idea to add parameters in the form of name-value pairs. This helps in easy reference of these items through code. You can access these members through the index numbers also, but accessing by name proves to be a comparatively less error-prone implementation. The following code snippet lists the code for the Click event of the Cancel button. private void btnCancel_Click(object sender, System.EventArgs e) { ...ddlAuthors.Enabled = true; ...txtID.Enabled = false; ...txtLName.Enabled = false; ...txtFName.Enabled = false; ...txtPhone.Enabled = false; ...txtAddress.Enabled = false; ...txtCity.Enabled = false; ...txtState.Enabled = false; ...txtZip.Enabled = false; ...txtContract.Enabled = false; ...btnCancel.Enabled = false; ...btnSave.Enabled = false; ...btnModify.Enabled = true; ...btnError.Visible = false; ...btnDone.Visible = false; ...grpStatus.Visible = false; }
Listing 7-7 displays the entire code for the frmAuthorModify.cs form file after you add the preceding lines of code.
263
223-304.qxd 2/24/03 10:46 AM Page 264
Project 1
DATABASE INTEGRATION WITH .NET
Listing 7-7 frmAuthorModify.cs using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data;
namespace slnDBConnect { ///
AM FL Y
using System.Data.SqlClient;
/// Summary description for frmAuthorModify. ///
public class frmAuthorModify : System.Windows.Forms.Form {
TE
264
private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Label label1; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; private System.Windows.Forms.TextBox txtID; private System.Windows.Forms.TextBox txtLName; private System.Windows.Forms.TextBox txtFName; private System.Windows.Forms.Label label5; private System.Windows.Forms.TextBox txtPhone; private System.Windows.Forms.Label label6; private System.Windows.Forms.TextBox txtAddress; private System.Windows.Forms.Label State; private System.Windows.Forms.Label label7; private System.Windows.Forms.TextBox txtState; private System.Windows.Forms.Label label8; private System.Windows.Forms.TextBox txtCity; private System.Windows.Forms.Label label9; private System.Windows.Forms.Label label10; private System.Windows.Forms.TextBox txtZip;
Team-Fly®
223-304.qxd 2/24/03 10:46 AM Page 265
CREATING A WINDOWS APPLICATION IN C#
private System.Windows.Forms.TextBox txtContract; private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.Button btnCancel; private System.Windows.Forms.Button btnSave; private System.Windows.Forms.Button btnModify; private System.Windows.Forms.Button btnError; private System.Windows.Forms.Button btnDone; private System.Windows.Forms.GroupBox grpStatus; private System.Windows.Forms.Label lblInfo; private System.Data.SqlClient.SqlCommand sqlSelectCommand1; private System.Data.SqlClient.SqlCommand sqlInsertCommand1; private System.Data.SqlClient.SqlCommand sqlUpdateCommand1; private System.Data.SqlClient.SqlCommand sqlDeleteCommand1; private System.Data.SqlClient.SqlConnection sqlConnection1; private System.Data.SqlClient.SqlDataAdapter sqlDataAdapter1; private slnDBConnect.dsAuthors dsAuthors1; private System.Windows.Forms.ComboBox ddlAuthors;
public string [] strArrAuID ; /// /// Required designer variable. /// private System.ComponentModel.Container components = null;
public frmAuthorModify() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// /// Clean up any resources being used.
Chapter 7
265
223-304.qxd 2/24/03 10:46 AM Page 266
266
Project 1
DATABASE INTEGRATION WITH .NET
/// protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); }
#region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(frmAuthorModify)); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.ddlAuthors = new System.Windows.Forms.ComboBox(); this.label1 = new System.Windows.Forms.Label(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.txtContract = new System.Windows.Forms.TextBox(); this.txtZip = new System.Windows.Forms.TextBox(); this.label10 = new System.Windows.Forms.Label(); this.label9 = new System.Windows.Forms.Label(); this.txtCity = new System.Windows.Forms.TextBox(); this.label8 = new System.Windows.Forms.Label(); this.txtState = new System.Windows.Forms.TextBox(); this.State = new System.Windows.Forms.Label(); this.txtAddress = new System.Windows.Forms.TextBox(); this.label6 = new System.Windows.Forms.Label(); this.txtPhone = new System.Windows.Forms.TextBox();
223-304.qxd 2/24/03 10:46 AM Page 267
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
this.label5 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label(); this.txtFName = new System.Windows.Forms.TextBox(); this.txtLName = new System.Windows.Forms.TextBox(); this.txtID = new System.Windows.Forms.TextBox(); this.label7 = new System.Windows.Forms.Label(); this.groupBox3 = new System.Windows.Forms.GroupBox(); this.btnCancel = new System.Windows.Forms.Button(); this.btnSave = new System.Windows.Forms.Button(); this.btnModify = new System.Windows.Forms.Button(); this.grpStatus = new System.Windows.Forms.GroupBox(); this.lblInfo = new System.Windows.Forms.Label(); this.btnDone = new System.Windows.Forms.Button(); this.btnError = new System.Windows.Forms.Button(); this.sqlSelectCommand1 = new System.Data.SqlClient.SqlCommand(); this.sqlConnection1 = new System.Data.SqlClient.SqlConnection(); this.sqlInsertCommand1 = new System.Data.SqlClient.SqlCommand(); this.sqlUpdateCommand1 = new System.Data.SqlClient.SqlCommand(); this.sqlDeleteCommand1 = new System.Data.SqlClient.SqlCommand(); this.sqlDataAdapter1 = new System.Data.SqlClient.SqlDataAdapter(); this.dsAuthors1 = new slnDBConnect.dsAuthors(); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); this.groupBox3.SuspendLayout(); this.grpStatus.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dsAuthors1)).BeginInit(); this.SuspendLayout(); // // groupBox1 //
267
223-304.qxd 2/24/03 10:46 AM Page 268
268
Project 1
DATABASE INTEGRATION WITH .NET
this.groupBox1.Controls.AddRange(new System.Windows.Forms.Control[] { this.ddlAuthors, this.label1}); this.groupBox1.Location = new System.Drawing.Point(115, 21); this.groupBox1.Name = “groupBox1”; this.groupBox1.Size = new System.Drawing.Size(488, 64); this.groupBox1.TabIndex = 0; this.groupBox1.TabStop = false; this.groupBox1.Text = “Select the Author”; // // ddlAuthors // this.ddlAuthors.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.ddlAuthors.Location = new System.Drawing.Point(209, 24); this.ddlAuthors.Name = “ddlAuthors”; this.ddlAuthors.Size = new System.Drawing.Size(208, 21); this.ddlAuthors.TabIndex = 1; this.ddlAuthors.SelectedIndexChanged += new System.EventHandler(this.ddlAuthors_SelectedIndexChanged) // // label1 // this.label1.Location = new System.Drawing.Point(73, 24); this.label1.Name = “label1”; this.label1.TabIndex = 1; this.label1.Text = “Author Name”; // // groupBox2 // this.groupBox2.Controls.AddRange(new System.Windows.Forms.Control[] {
223-304.qxd 2/24/03 10:46 AM Page 269
CREATING A WINDOWS APPLICATION IN C#
this.txtContract, this.txtZip, this.label10, this.label9, this.txtCity, this.label8, this.txtState, this.State, this.txtAddress, this.label6, this.txtPhone, this.label5, this.label2, this.label3, this.label4, this.txtFName, this.txtLName, this.txtID}); this.groupBox2.Location = new System.Drawing.Point(79, 148); this.groupBox2.Name = “groupBox2”; this.groupBox2.Size = new System.Drawing.Size(601, 323); this.groupBox2.TabIndex = 1; this.groupBox2.TabStop = false; this.groupBox2.Text = “Author Details”; // // txtContract // this.txtContract.Enabled = false; this.txtContract.Location = new System.Drawing.Point(440, 176); this.txtContract.Name = “txtContract”; this.txtContract.TabIndex = 16; this.txtContract.Text = “”; // // txtZip //
Chapter 7
269
223-304.qxd 2/24/03 10:46 AM Page 270
270
Project 1
DATABASE INTEGRATION WITH .NET
this.txtZip.Enabled = false; this.txtZip.Location = new System.Drawing.Point(440, 136); this.txtZip.Name = “txtZip”; this.txtZip.TabIndex = 15; this.txtZip.Text = “”; // // label10 // this.label10.AutoSize = true; this.label10.Location = new System.Drawing.Point(376, 176); this.label10.Name = “label10”; this.label10.Size = new System.Drawing.Size(47, 13); this.label10.TabIndex = 14; this.label10.Text = “Contract”; // // label9 // this.label9.AutoSize = true; this.label9.Location = new System.Drawing.Point(376, 136); this.label9.Name = “label9”; this.label9.Size = new System.Drawing.Size(20, 13); this.label9.TabIndex = 13; this.label9.Text = “Zip”; // // txtCity // this.txtCity.Enabled = false; this.txtCity.Location = new System.Drawing.Point(440, 96); this.txtCity.Name = “txtCity”; this.txtCity.TabIndex = 12; this.txtCity.Text = “”; // // label8 //
223-304.qxd 2/24/03 10:46 AM Page 271
CREATING A WINDOWS APPLICATION IN C#
this.label8.AutoSize = true; this.label8.Location = new System.Drawing.Point(376, 96); this.label8.Name = “label8”; this.label8.Size = new System.Drawing.Size(24, 13); this.label8.TabIndex = 11; this.label8.Text = “City”; // // txtState // this.txtState.Enabled = false; this.txtState.Location = new System.Drawing.Point(440, 56); this.txtState.Name = “txtState”; this.txtState.TabIndex = 10; this.txtState.Text = “”; // // State // this.State.AutoSize = true; this.State.Location = new System.Drawing.Point(376, 56); this.State.Name = “State”; this.State.Size = new System.Drawing.Size(31, 13); this.State.TabIndex = 9; this.State.Text = “State”; // // txtAddress // this.txtAddress.Enabled = false; this.txtAddress.Location = new System.Drawing.Point(128, 216); this.txtAddress.Name = “txtAddress”; this.txtAddress.TabIndex = 8; this.txtAddress.Text = “”; // // label6 //
Chapter 7
271
223-304.qxd 2/24/03 10:46 AM Page 272
272
Project 1
DATABASE INTEGRATION WITH .NET
this.label6.AutoSize = true; this.label6.Location = new System.Drawing.Point(23, 216); this.label6.Name = “label6”; this.label6.Size = new System.Drawing.Size(46, 13); this.label6.TabIndex = 7; this.label6.Text = “Address”; // // txtPhone // this.txtPhone.Enabled = false; this.txtPhone.Location = new System.Drawing.Point(128, 176); this.txtPhone.Name = “txtPhone”; this.txtPhone.TabIndex = 6; this.txtPhone.Text = “”; // // label5 // this.label5.AutoSize = true; this.label5.Location = new System.Drawing.Point(23, 176); this.label5.Name = “label5”; this.label5.Size = new System.Drawing.Size(37, 13); this.label5.TabIndex = 5; this.label5.Text = “Phone”; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(23, 56); this.label2.Name = “label2”; this.label2.Size = new System.Drawing.Size(52, 13); this.label2.TabIndex = 2; this.label2.Text = “Author ID”; // // label3
223-304.qxd 2/24/03 10:46 AM Page 273
CREATING A WINDOWS APPLICATION IN C#
// this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(23, 136); this.label3.Name = “label3”; this.label3.Size = new System.Drawing.Size(59, 13); this.label3.TabIndex = 3; this.label3.Text = “First Name”; // // label4 // this.label4.AutoSize = true; this.label4.Location = new System.Drawing.Point(23, 96); this.label4.Name = “label4”; this.label4.Size = new System.Drawing.Size(59, 13); this.label4.TabIndex = 4; this.label4.Text = “Last Name”; // // txtFName // this.txtFName.Enabled = false; this.txtFName.Location = new System.Drawing.Point(128, 136); this.txtFName.Name = “txtFName”; this.txtFName.TabIndex = 4; this.txtFName.Text = “”; // // txtLName // this.txtLName.Enabled = false; this.txtLName.Location = new System.Drawing.Point(128, 96); this.txtLName.Name = “txtLName”; this.txtLName.TabIndex = 3; this.txtLName.Text = “”; // // txtID
Chapter 7
273
223-304.qxd 2/24/03 10:46 AM Page 274
DATABASE INTEGRATION WITH .NET
// this.txtID.Enabled = false; this.txtID.Location = new System.Drawing.Point(128, 56); this.txtID.Name = “txtID”; this.txtID.TabIndex = 2; this.txtID.Text = “”; // // label7 //
AM FL Y
Project 1
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(3, 16);
this.label7.Name = “label7”;
this.label7.Size = new System.Drawing.Size(0, 13); this.label7.TabIndex = 0; //
TE
274
// groupBox3 //
this.groupBox3.Controls.AddRange(new System.Windows.Forms.Control[] { this.btnCancel, this.btnSave, this.btnModify}); this.groupBox3.Location = new System.Drawing.Point(232, 488); this.groupBox3.Name = “groupBox3”; this.groupBox3.Size = new System.Drawing.Size(360, 96); this.groupBox3.TabIndex = 4; this.groupBox3.TabStop = false; this.groupBox3.Text = “Operations”; // // btnCancel // this.btnCancel.Location = new System.Drawing.Point(248, 40); this.btnCancel.Name = “btnCancel”;
Team-Fly®
223-304.qxd 2/24/03 10:46 AM Page 275
CREATING A WINDOWS APPLICATION IN C#
this.btnCancel.TabIndex = 2; this.btnCancel.Text = “Cancel”; this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); // // btnSave // this.btnSave.Location = new System.Drawing.Point(152, 40); this.btnSave.Name = “btnSave”; this.btnSave.TabIndex = 1; this.btnSave.Text = “Save”; this.btnSave.Click += new System.EventHandler(this.btnSave_Click); // // btnModify // this.btnModify.Location = new System.Drawing.Point(57, 40); this.btnModify.Name = “btnModify”; this.btnModify.TabIndex = 0; this.btnModify.Text = “Modify”; this.btnModify.Click += new System.EventHandler(this.btnModify_Click); // // grpStatus // this.grpStatus.Controls.AddRange(new System.Windows.Forms.Control[] { this.lblInfo, this.btnDone, this.btnError}); this.grpStatus.Location = new System.Drawing.Point(792, 192); this.grpStatus.Name = “grpStatus”; this.grpStatus.Size = new System.Drawing.Size(152, 176); this.grpStatus.TabIndex = 3;
Chapter 7
275
223-304.qxd 2/24/03 10:46 AM Page 276
276
Project 1
DATABASE INTEGRATION WITH .NET
this.grpStatus.TabStop = false; this.grpStatus.Text = “Status”; this.grpStatus.Visible = false; // // lblInfo // this.lblInfo.Location = new System.Drawing.Point(24, 80); this.lblInfo.Name = “lblInfo”; this.lblInfo.Size = new System.Drawing.Size(120, 80); this.lblInfo.TabIndex = 2; // // btnDone // this.btnDone.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.btnDone.Image = (System.Drawing.Bitmap)(resources.GetObject(“btnDone.Image”))); this.btnDone.Location = new System.Drawing.Point(56, 24); this.btnDone.Name = “btnDone”; this.btnDone.Size = new System.Drawing.Size(56, 48); this.btnDone.TabIndex = 1; this.btnDone.Visible = false; // // btnError // this.btnError.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.btnError.Image = ((System.Drawing.Bitmap)(resources.GetObject(“btnError.Image”))); this.btnError.Location = new System.Drawing.Point(56, 24); this.btnError.Name = “btnError”; this.btnError.Size = new System.Drawing.Size(56, 48); this.btnError.TabIndex = 0; this.btnError.Visible = false; //
223-304.qxd 2/24/03 10:46 AM Page 277
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
// sqlSelectCommand1 // this.sqlSelectCommand1.CommandText = “SELECT au_id, au_lname, au_fname, phone, address, city, state, zip, contract FROM” + “authors”; this.sqlSelectCommand1.Connection = this.sqlConnection1; // // sqlConnection1 // this.sqlConnection1.ConnectionString = “data source=NPANDEY-D185;initial catalog=pubs;persist security info=False;user id” + “=sa;workstation id=YS-D185;packet size=4096”; // // sqlInsertCommand1 // this.sqlInsertCommand1.CommandText = @”INSERT INTO authors(au_id, au_lname, au_fname, phone, address, city, state, zip, contract) VALUES (@au_id, @au_lname, @au_fname, @phone, @address, @city, @state, @zip, @contract); SELECT au_id, au_lname, au_fname, phone, address, city, state, zip, contract FROM authors WHERE (au_id = @au_id)”; this.sqlInsertCommand1.Connection = this.sqlConnection1; this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_id”, System.Data.SqlDbType.VarChar, 11, “au_id”)); this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_lname”, System.Data.SqlDbType.VarChar, 40, “au_lname”)); this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_fname”, System.Data.SqlDbType.VarChar, 20, “au_fname”)); this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@phone”,
277
223-304.qxd 2/24/03 10:46 AM Page 278
278
Project 1
DATABASE INTEGRATION WITH .NET
System.Data.SqlDbType.VarChar, 12, “phone”));
this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@address”, System.Data.SqlDbType.VarChar, 40, “address”)); this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@city”, System.Data.SqlDbType.VarChar, 20, “city”));
this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@state”, System.Data.SqlDbType.VarChar, 2, “state”)); this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@zip”, System.Data.SqlDbType.VarChar, 5, “zip”));
this.sqlInsertCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@contract”, System.Data.SqlDbType.Bit, 1, “contract”)); // // sqlUpdateCommand1 // this.sqlUpdateCommand1.CommandText = @”UPDATE authors SET au_id = @au_id, au_lname = @au_lname, au_fname = @au_fname, phone = @phone, address = @address, city = @city, state = @state, zip = @zip, contract = @contract WHERE (au_id = @Original_au_id) AND (address = @Original_address OR @Original_address IS NULL AND address IS NULL) AND (au_fname = @Original_au_fname) AND (au_lname = @Original_au_lname) AND (city = @Original_city OR @Original_city IS NULL AND city IS NULL) AND (contract = @Original_contract) AND (phone = @Original_phone) AND (state = @Original_state OR @Original_state IS NULL AND state IS NULL) AND (zip = @Original_zip OR @Original_zip IS NULL AND zip IS NULL); SELECT au_id, au_lname, au_fname, phone, address, city, state, zip, contract FROM authors WHERE (au_id = @au_id)”;
223-304.qxd 2/24/03 10:46 AM Page 279
CREATING A WINDOWS APPLICATION IN C#
this.sqlUpdateCommand1.Connection = this.sqlConnection1;
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_id”, System.Data.SqlDbType.VarChar, 11, “au_id”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_lname”, System.Data.SqlDbType.VarChar, 40, “au_lname”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@au_fname”, System.Data.SqlDbType.VarChar, 20, “au_fname”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@phone”, System.Data.SqlDbType.VarChar, 12, “phone”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@address”, System.Data.SqlDbType.VarChar, 40, “address”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@city”, System.Data.SqlDbType.VarChar, 20, “city”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@state”, System.Data.SqlDbType.VarChar, 2, “state”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@zip”, System.Data.SqlDbType.VarChar, 5, “zip”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@contract”,
Chapter 7
279
223-304.qxd 2/24/03 10:46 AM Page 280
280
Project 1
DATABASE INTEGRATION WITH .NET
System.Data.SqlDbType.Bit, 1, “contract”));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_id”, System.Data.SqlDbType.VarChar, 11, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_id”, System.Data.DataRowVersion.Original, null));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_address”, System.Data.SqlDbType.VarChar, 40, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “address”, System.Data.DataRowVersion.Original, null));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_fname”, System.Data.SqlDbType.VarChar, 20, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_fname”, System.Data.DataRowVersion.Original, null));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_lname”, System.Data.SqlDbType.VarChar, 40, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_lname”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_city”, System.Data.SqlDbType.VarChar, 20, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “city”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_contract”, System.Data.SqlDbType.Bit, 1,
223-304.qxd 2/24/03 10:46 AM Page 281
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “contract”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_phone”, System.Data.SqlDbType.VarChar, 12, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “phone”, System.Data.DataRowVersion.Original, null)); this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_state”, System.Data.SqlDbType.VarChar, 2, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “state”, System.Data.DataRowVersion.Original, null));
this.sqlUpdateCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_zip”, System.Data.SqlDbType.VarChar, 5, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “zip”, System.Data.DataRowVersion.Original, null));
// sqlDeleteCommand1 // this.sqlDeleteCommand1.CommandText = @”DELETE FROM authors WHERE (au_id = @Original_au_id) AND (address = @Original_address OR @Original_address IS NULL AND address IS NULL) AND (au_fname = @Original_au_fname) AND (au_lname = @Original_au_lname) AND (city = @Original_city OR @Original_city IS NULL AND city IS NULL) AND (contract = @Original_contract) AND (phone = @Original_phone) AND (state = @Original_state OR @Original_state IS NULL AND state IS NULL) AND (zip = @Original_zip OR @Original_zip IS NULL AND zip IS NULL)”;
this.sqlDeleteCommand1.Connection =
281
223-304.qxd 2/24/03 10:46 AM Page 282
282
Project 1
DATABASE INTEGRATION WITH .NET
this.sqlConnection1; this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_id”, System.Data.SqlDbType.VarChar, 11, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_id”, System.Data.DataRowVersion.Original, null));
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_address”, System.Data.SqlDbType.VarChar, 40, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “address”, System.Data.DataRowVersion.Original, null));
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_fname”, System.Data.SqlDbType.VarChar, 20, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_fname”, System.Data.DataRowVersion.Original, null));
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_au_lname”, System.Data.SqlDbType.VarChar, 40, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “au_lname”, System.Data.DataRowVersion.Original, null));
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_city”, System.Data.SqlDbType.VarChar, 20, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “city”, System.Data.DataRowVersion.Original, null));
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_contract”,
223-304.qxd 2/24/03 10:46 AM Page 283
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
System.Data.SqlDbType.Bit, 1, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “contract”, System.Data.DataRowVersion.Original, null));
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_phone”, System.Data.SqlDbType.VarChar, 12, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “phone”, System.Data.DataRowVersion.Original, null));
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_state”, System.Data.SqlDbType.VarChar, 2, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “state”, System.Data.DataRowVersion.Original, null));
this.sqlDeleteCommand1.Parameters.Add(new System.Data.SqlClient.SqlParameter(“@Original_zip”, System.Data.SqlDbType.VarChar, 5, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), “zip”, System.Data.DataRowVersion.Original, null));
// sqlDataAdapter1 this.sqlDataAdapter1.DeleteCommand = this.sqlDeleteCommand1;
this.sqlDataAdapter1.InsertCommand = this.sqlInsertCommand1; this.sqlDataAdapter1.SelectCommand = this.sqlSelectCommand1; this.sqlDataAdapter1.TableMappings.AddRange(new System.Data.Common.DataTableMapping[] { new System.Data.Common.DataTableMapping(“Table”, “authors”, new System.Data.Common.DataColumnMapping[] {
283
223-304.qxd 2/24/03 10:46 AM Page 284
Project 1
DATABASE INTEGRATION WITH .NET
new System.Data.Common.DataColumnMapping(“au_id”, “au_id”), new System.Data.Common.DataColumnMapping(“au_lname”, “au_lname”), new System.Data.Common.DataColumnMapping(“au_fname”, “au_fname”), new System.Data.Common.DataColumnMapping(“phone”, “phone”), new System.Data.Common.DataColumnMapping(“address”, “address”),
AM FL Y
new System.Data.Common.DataColumnMapping(“city”, “city”),
new System.Data.Common.DataColumnMapping(“state”, “state”),
new System.Data.Common.DataColumnMapping(“zip”, “zip”),
new System.Data.Common.DataColumnMapping(“contract”, “contract”)})});
TE
284
this.sqlDataAdapter1.UpdateCommand = this.sqlUpdateCommand1; // dsAuthors1 this.dsAuthors1.DataSetName = “dsAuthors”; this.dsAuthors1.Locale = new System.Globalization.CultureInfo(“en-US”); this.dsAuthors1.Namespace = “http://www.tempuri.org/dsAuthors.xsd”; // frmAuthorModify
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(1024, 605); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.groupBox3, this.groupBox2, this.groupBox1, this.grpStatus}); this.Name = “frmAuthorModify”; this.Text = “Author Details”; this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
Team-Fly®
223-304.qxd 2/24/03 10:46 AM Page 285
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
this.Load += new System.EventHandler(this.frmAuthorModify_Load); this.groupBox1.ResumeLayout(false); this.groupBox2.ResumeLayout(false); this.groupBox3.ResumeLayout(false); this.grpStatus.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dsAuthors1)).EndInit(); this.ResumeLayout(false);
} #endregion
private void ddlAuthors_SelectedIndexChanged(object sender, System.EventArgs e) { string strAuID;
strAuID = strArrAuID[ddlAuthors.SelectedIndex ]; txtID.Text = strAuID;
DataRow foundRows; // Select rows matching for currently selected Author foundRows = dsAuthors1.Tables[“authors”].Rows.Find(strAuID);
// if rows were found, update the controls on the web form with author details if(foundRows.IsNull(0) == false) //GetLowerBound(0) != foundRows.GetUpperBound(0) ) { txtLName.Text = foundRows[“au_lname”].ToString(); txtFName.Text = foundRows[“au_fname”].ToString (); txtPhone.Text = foundRows[“phone”].ToString (); txtAddress.Text = foundRows[“address”].ToString (); txtCity.Text = foundRows[“city”].ToString (); txtState.Text = foundRows[“state”].ToString (); txtZip.Text = foundRows[“zip”].ToString (); txtContract.Text = foundRows[“contract”].ToString(); }
285
223-304.qxd 2/24/03 10:46 AM Page 286
286
Project 1
DATABASE INTEGRATION WITH .NET
btnModify.Enabled = true; grpStatus.Visible=false; }
private void frmAuthorModify_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here sqlDataAdapter1.Fill (dsAuthors1, “Authors”); int count; count = dsAuthors1.Tables[“Authors”].Rows.Count; strArrAuID = new string [count]; int idCtr; idCtr=0; foreach (DataRow rowPicker1 in dsAuthors1.Tables[“Authors”].Rows) { ddlAuthors.Items.Add(rowPicker1[“au_fname”] + “ “ + rowPicker1[“au_lname”]); strArrAuID[idCtr] = rowPicker1[“au_id”].ToString() ;
idCtr++; } }
private void btnModify_Click(object sender, System.EventArgs e) { ddlAuthors.Enabled = false; txtID.Enabled = false; txtLName.Enabled = true; txtFName.Enabled = true; txtPhone.Enabled = true; txtAddress.Enabled = true; txtCity.Enabled = true; txtState.Enabled = true; txtZip.Enabled = true; txtContract.Enabled = true; btnCancel.Enabled = true;
223-304.qxd 2/24/03 10:46 AM Page 287
CREATING A WINDOWS APPLICATION IN C#
btnSave.Enabled = true; btnModify.Enabled = false; btnError.Visible = false; btnDone.Visible = false; grpStatus.Visible = false; }
private void btnSave_Click(object sender, System.EventArgs e) { //Check for an missing values if (txtFName.Text.Length == 0 | txtLName.Text.Length == 0 | txtPhone.Text.Length == 0 | txtAddress.Text.Length == 0 | txtCity.Text.Length ==0 | txtState.Text.Length == 0 | txtZip.Text.Length==0 | txtContract.Text.Length ==0) {
lblInfo.ForeColor = Color.Red; lblInfo.Text = “Details Missing!!”; lblInfo.Visible = true; btnError.Visible = true; grpStatus.Visible = true; return; }
//Create the string to update records string strSQL;
strSQL = “update authors set “ + “au_lname = @LN ,” + “au_fname = @FN ,” + “phone = @PH ,” + “address = @AD ,” + “city = @CI ,” + “state = @ST ,” +
Chapter 7
287
223-304.qxd 2/24/03 10:46 AM Page 288
288
Project 1
DATABASE INTEGRATION WITH .NET
“zip= @ZI ,” + “contract = @CO “ + “where au_id= @ID”;
//Check whether the connection is Open try { if (sqlConnection1.State != ConnectionState.Open ) { sqlConnection1.Open (); }
//Create a SqlCommand object SqlCommand myComm; myComm = new SqlCommand(strSQL,sqlConnection1);
//Assign the SqlCommand object to the UpdateCommand property of the Data Adapter sqlDataAdapter1.UpdateCommand = myComm; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@LN”, SqlDbType.VarChar, 20).Value = txtLName.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@FN”, SqlDbType.VarChar, 40).Value = txtFName.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@PH”,SqlDbType.Char, 12).Value = txtPhone.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@AD”,SqlDbType.VarChar , 40).Value = txtAddress.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@CI”,SqlDbType.VarChar, 20).Value = txtCity.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@ST”,SqlDbType.Char , 2).Value = txtState.Text; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@ZI”,SqlDbType.Char, 5).Value = txtZip.Text ; sqlDataAdapter1.UpdateCommand.Parameters.Add(“@CO”,SqlDbType.Bit).Value = Convert.ToBoolean(txtContract.Text ); sqlDataAdapter1.UpdateCommand.Parameters.Add(“@ID”,SqlDbType.VarChar, 11).Value = txtID.Text;
223-304.qxd 2/24/03 10:46 AM Page 289
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
//Execute the Update Command sqlDataAdapter1.UpdateCommand.ExecuteNonQuery (); } catch(Exception E1) { lblInfo.ForeColor = Color.Red; lblInfo.Text = “The following error occured: \n” + E1.Message ; btnDone.Visible = false; btnError.Visible = true; grpStatus.Visible = true; }
//Display to the user that the records was updated successfully lblInfo.Text = “Record updated!! \n Author ID: “ + txtID.Text; lblInfo.ForeColor = Color.Blue; btnDone.Visible = true; btnError.Visible = false; grpStatus.Visible = true;
// Code to manipulate controls ddlAuthors.Enabled = true; txtID.Enabled = false; txtLName.Enabled = false; txtFName.Enabled = false; txtPhone.Enabled = false; txtAddress.Enabled = false; txtCity.Enabled = false; txtState.Enabled = false; txtZip.Enabled = false; txtContract.Enabled = false; btnCancel.Enabled = false; btnSave.Enabled = false; btnModify.Enabled = true; }
289
223-304.qxd 2/24/03 10:46 AM Page 290
290
Project 1
DATABASE INTEGRATION WITH .NET
private void btnCancel_Click(object sender, System.EventArgs e) { ddlAuthors.Enabled = true; txtID.Enabled = false; txtLName.Enabled = false; txtFName.Enabled = false; txtPhone.Enabled = false; txtAddress.Enabled = false; txtCity.Enabled = false; txtState.Enabled = false; txtZip.Enabled = false; txtContract.Enabled = false; btnCancel.Enabled = false; btnSave.Enabled = false; btnModify.Enabled = true; btnError.Visible = false; btnDone.Visible = false; grpStatus.Visible = false; } } }
Create the Entity Details Maintenance Form In the next step, you need to create the Entity Details Maintenance form. As the first step, you need to add a new form by using the steps listed in the section “Create the Author Details Modification Form.” You need to name the form as frmMDIMain and specify the Text property for the form as Entity Details Maintenance. Next, you need to add the required controls on the form. To add the menu control to the form, you need to perform the following steps: 1. Add a MainMenu control to the form by dragging the control from the Toolbox to the form. Rename this as mnuEntityModify. 2. Select the form. Double-click on the IsMdiContainer property in the Properties dialog box to change it to True. Figure 7-16 displays the Properties window with the modified IsMdiContainer property.
223-304.qxd 2/24/03 10:46 AM Page 291
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
FIGURE 7-16 The Properties window with the modified IsMdiContainer property
3. Double-click on the Menu property in the Properties window to display the added menu on the form. Figure 7-17 displays the Properties window with the modified Menu property.
FIGURE 7-17 The Properties window with the modified Menu property
291
223-304.qxd 2/24/03 10:46 AM Page 292
292
Project 1
DATABASE INTEGRATION WITH .NET
4. Next, you need to add the required menus to the form. To add the Modify menu, click on the form at the left-most corner of the form. To display the menu as Modify, type &Modify in the Text property value. Specify the Name property of the menu as mnuModify. 5. Name the menu options as mnuModify, mnuModAuthorDetails, and mnuMore, respectively. 6. Set the Enabled property of mnuMore to False. 7. Similarly, create the remaining menus on the form. Set the Enabled property of mnuMoreReports to False. You can now specify code for the events of the controls on the form. The following lists specify the procedures for which you need to write code: ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆
mnuModAuthorDetails_Click mnuTIDbyAuthShow_Click mnuTIDbyAuthWriteXML_Click mnuTIDbyAuthWriteXMLSchema_Click mnuTIDbyAuthWriteXMLWithSchema_Click mnuClose_Click instfrmTidByAuthor_Closed instfrmAuthorModify_Closed
The subsequent sections discuss the procedures.
The mnuModAuthorDetails_Click Procedure This procedure is invoked when the Author Details menu command is clicked on. This procedure displays the Author Details Modification form and resizes the existing form. The code for the Click event handler is specified in Listing 7-8. Listing 7-8 Code for the Click Event Handler of mnuModAuthorDetails_Click private void mnuModAuthorDetails_Click(object sender, System.EventArgs e) { ...frmAuthorModify frmMod; ...frmMod = new frmAuthorModify (); ...frmMod.MdiParent = this; ...frmMod.Show (); }
223-304.qxd 2/24/03 10:46 AM Page 293
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
The mnuTIDbyAuthShow_Click Procedure This procedure is invoked when the Show Report menu command is clicked on. This procedure displays the Authors and Titles report. In addition, this procedure disables the Show Report command while enabling the remaining commands on the Title IDs by author menu. The code for the Click event handler of the mnuTIDbyAuthShow command is specified in Listing 7-9. Listing 7-9 Code for the Click Event Handler of mnuTIDbyAuthShow_Click private void mnuTIDbyAuthShow_Click(object sender, System.EventArgs e) { ...frmTitle = new frmTitleByAuthor(); ...frmTitle.MdiParent = this; ...mnuTIDbyAuthWriteXML.Enabled =true; ...mnuTIDAuthWriteXMLSchema.Enabled =true; ...mnuTIDbyAuthWriteXMLwithSchema.Enabled=true; ...mnuTIDbyAuthShow.Enabled = false; ...frmTitle.Show(); }
The mnuTIDbyAuthWriteXML_Click Procedure This procedure is invoked when the Write XML menu command is clicked on. This procedure calls prcTIDbyAuthWriteXML(). The prcTIDbyAuthWriteXML() procedure is covered in the section “The prcTIDbyAuthWriteXML Procedure.” The code for the Click event handler of the Write XML command is specified in Listing 7-10. Listing 7-10 Code for the Click Event Handler of mnuTIDbyAuthWriteXML_Click private void mnuTIDbyAuthWriteXML_Click(object sender, System.EventArgs e) { frmTitle.prcTIDbyAuthWriteXML (); }
293
223-304.qxd 2/24/03 10:46 AM Page 294
Project 1
DATABASE INTEGRATION WITH .NET
The mnuTIDbyAuthWriteXMLSchema_Click Procedure This procedure is invoked when the Write XML Schema menu command is clicked on. This procedure calls prcTIDbyAuthWriteXMLSchema. The prcTIDbyAuthWriteXMLSchema procedure is covered in the section “The prcTIDbyAuthWriteXMLSchema Procedure.” The code for the Click event handler of the Write XML Schema command is specified in Listing 7-11. Listing 7-11 Code for the Click Event Handler of
AM FL Y
mnuTIDbyAuthWriteXMLSchema_Click private void mnuTIDAuthWriteXMLSchema_Click(object sender, System.EventArgs e) {
frmTitle.prcTIDbyAuthWriteXMLSchema (); }
TE
294
The mnuTIDbyAuthWriteXMLWithSchema_Click Procedure This procedure is invoked when the Write XML with Schema menu command is clicked on. This procedure calls prcTIDbyAuthWriteXMLWithSchema. The prcTIDbyAuthWriteXMLWithSchema procedure is covered in the section “The prcTIDbyAuthWriteXMLWithSchema Procedure.” The code for the Click event handler of the Write XML with Schema command is specified in Listing 7-12. Listing 7-12 Code for the Click Event Handler of mnuTIDbyAuthWriteXMLWithSchema_Click private void mnuTIDbyAuthWriteXMLwithSchema_Click(object sender, System.EventArgs e) { frmTitle.prcTIDbyAuthWriteXMLWithSchema(); }
The mnuClose_Click Procedure This procedure is invoked when the Close menu command is clicked. This procedure calls Exit() method for the current form. The code for the Click event handler of the Close menu is specified in Listing 7-13.
Team-Fly®
223-304.qxd 2/24/03 10:46 AM Page 295
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
Listing 7-13 Code for the Click Event Handler of mnuClose_Click private void mnuClose_Click(object sender, System.EventArgs e) { Application.Exit(); }
Listing 7-14 displays the entire code for the frmMDIMain.cs form file, after adding the preceding lines of code. Listing 7-14 frmMDIMain.cs using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data;
namespace slnDBConnect { // /// Summary description for FrmMDIMain. /// public class FrmMDIMain : System.Windows.Forms.Form { private System.Windows.Forms.MenuItem mnuModify; private System.Windows.Forms.MenuItem mnuModAuthorDetails; private System.Windows.Forms.MenuItem mnuMore; private System.Windows.Forms.MenuItem mnuReports; private System.Windows.Forms.MenuItem mnuTIDByAuthor; private System.Windows.Forms.MenuItem menuItem3; private System.Windows.Forms.MenuItem mnuTIDbyAuthShow; private System.Windows.Forms.MenuItem mnuTIDbyAuthWriteXML; private System.Windows.Forms.MenuItem mnuTIDAuthWriteXMLSchema; private System.Windows.Forms.MenuItem mnuTIDbyAuthWriteXMLwithSchema; private System.Windows.Forms.MenuItem menuItem1;
295
223-304.qxd 2/24/03 10:46 AM Page 296
296
Project 1
DATABASE INTEGRATION WITH .NET
private System.Windows.Forms.MainMenu mnuEntityModify; /// /// Required designer variable. /// private System.ComponentModel.Container components = null; private System.Windows.Forms.MenuItem mnuClose; frmTitleByAuthor frmTitle;
public FrmMDIMain() { // // Required for Windows Form Designer support // InitializeComponent();
// // TODO: Add any constructor code after InitializeComponent call // }
/// /// Clean up any resources being used. ///
protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); }
#region Windows Form Designer generated code ///
223-304.qxd 2/24/03 10:46 AM Page 297
CREATING A WINDOWS APPLICATION IN C#
/// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.mnuEntityModify = new System.Windows.Forms.MainMenu(); this.mnuModify = new System.Windows.Forms.MenuItem(); this.mnuModAuthorDetails = new System.Windows.Forms.MenuItem(); this.mnuMore = new System.Windows.Forms.MenuItem(); this.mnuReports = new System.Windows.Forms.MenuItem(); this.mnuTIDByAuthor = new System.Windows.Forms.MenuItem(); this.mnuTIDbyAuthShow = new System.Windows.Forms.MenuItem(); this.mnuTIDbyAuthWriteXML = new System.Windows.Forms.MenuItem(); this.mnuTIDAuthWriteXMLSchema = new System.Windows.Forms.MenuItem(); this.mnuTIDbyAuthWriteXMLwithSchema = new System.Windows.Forms.MenuItem(); this.menuItem3 = new System.Windows.Forms.MenuItem(); this.menuItem1 = new System.Windows.Forms.MenuItem(); this.mnuClose = new System.Windows.Forms.MenuItem(); // // mnuEntityModify // this.mnuEntityModify.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.mnuModify, this.mnuReports, this.menuItem1}); // // mnuModify // this.mnuModify.Index = 0; this.mnuModify.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.mnuModAuthorDetails, this.mnuMore});
Chapter 7
297
223-304.qxd 2/24/03 10:46 AM Page 298
298
Project 1
DATABASE INTEGRATION WITH .NET
this.mnuModify.Text = “&Modify”; // // mnuModAuthorDetails // this.mnuModAuthorDetails.Index = 0; this.mnuModAuthorDetails.Text = “Author Details”; this.mnuModAuthorDetails.Click += new System.EventHandler(this.mnuModAuthorDetails_Click); // // mnuMore // this.mnuMore.Enabled = false; this.mnuMore.Index = 1; this.mnuMore.Text = “More...”; // // mnuReports // this.mnuReports.Index = 1; this.mnuReports.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.mnuTIDByAuthor, this.menuItem3}); this.mnuReports.Text = “&Reports”; // // mnuTIDByAuthor // this.mnuTIDByAuthor.Index = 0; this.mnuTIDByAuthor.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.mnuTIDbyAuthShow, this.mnuTIDbyAuthWriteXML, this.mnuTIDAuthWriteXMLSchema, this.mnuTIDbyAuthWriteXMLwithSchema}); this.mnuTIDByAuthor.Text = “Titles by Author”; // // mnuTIDbyAuthShow // this.mnuTIDbyAuthShow.Index = 0; this.mnuTIDbyAuthShow.Text = “Show Report”;
223-304.qxd 2/24/03 10:46 AM Page 299
CREATING A WINDOWS APPLICATION IN C#
this.mnuTIDbyAuthShow.Click += new System.EventHandler(this.mnuTIDbyAuthShow_Click); // // mnuTIDbyAuthWriteXML // this.mnuTIDbyAuthWriteXML.Enabled = false; this.mnuTIDbyAuthWriteXML.Index = 1; this.mnuTIDbyAuthWriteXML.Text = “Write XML”; this.mnuTIDbyAuthWriteXML.Click += new System.EventHandler(this.mnuTIDbyAuthWriteXML_Click); // // mnuTIDAuthWriteXMLSchema // this.mnuTIDAuthWriteXMLSchema.Enabled = false; this.mnuTIDAuthWriteXMLSchema.Index = 2; this.mnuTIDAuthWriteXMLSchema.Text = “Write XML Schema”; this.mnuTIDAuthWriteXMLSchema.Click += new System.EventHandler(this.mnuTIDAuthWriteXMLSchema_Click); // // mnuTIDbyAuthWriteXMLwithSchema // this.mnuTIDbyAuthWriteXMLwithSchema.Enabled = false; this.mnuTIDbyAuthWriteXMLwithSchema.Index = 3; this.mnuTIDbyAuthWriteXMLwithSchema.Text = “Write XML with Schema”; this.mnuTIDbyAuthWriteXMLwithSchema.Click += new System.EventHandler(this.mnuTIDbyAuthWriteXMLwithSchema_Click); // // menuItem3 // this.menuItem3.Enabled = false; this.menuItem3.Index = 1; this.menuItem3.Text = “More Reports...”; // // menuItem1 // this.menuItem1.Index = 2; this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {this.mnuClose});
Chapter 7
299
223-304.qxd 2/24/03 10:46 AM Page 300
300
Project 1
DATABASE INTEGRATION WITH .NET
this.menuItem1.Text = “E&xit”; // // mnuClose // this.mnuClose.Index = 0; this.mnuClose.Text = “Close”; this.mnuClose.Click += new System.EventHandler(this.mnuClose_Click); // // FrmMDIMain // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 274); this.IsMdiContainer = true; this.Menu = this.mnuEntityModify; this.Name = “FrmMDIMain”; this.Text = “Maintaining Entity Details”; this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
} #endregion
/// /// The main entry point for the application. /// [STAThread]
static void Main() { Application.Run(new FrmMDIMain()); } private void mnuModAuthorDetails_Click(object sender, System.EventArgs e) { frmAuthorModify frmMod; frmMod = new frmAuthorModify ();
223-304.qxd 2/24/03 10:46 AM Page 301
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
frmMod.MdiParent = this; frmMod.Show (); }
private void mnuTIDbyAuthShow_Click(object sender, System.EventArgs e) { frmTitle = new frmTitleByAuthor(); frmTitle.MdiParent = this; mnuTIDbyAuthWriteXML.Enabled =true; mnuTIDAuthWriteXMLSchema.Enabled =true; mnuTIDbyAuthWriteXMLwithSchema.Enabled=true; mnuTIDbyAuthShow.Enabled = false; frmTitle.Show(); }
private void mnuTIDbyAuthWriteXML_Click(object sender, System.EventArgs e) { frmTitle.prcTIDbyAuthWriteXML (); }
private void mnuTIDAuthWriteXMLSchema_Click(object sender, System.EventArgs e) { frmTitle.prcTIDbyAuthWriteXMLSchema (); }
private void mnuTIDbyAuthWriteXMLwithSchema_Click(object sender, System.EventArgs e) { frmTitle.prcTIDbyAuthWriteXMLWithSchema(); }
private void mnuClose_Click(object sender, System.EventArgs e) { Application.Exit(); }
} }
301
223-304.qxd 2/24/03 10:46 AM Page 302
302
Project 1
DATABASE INTEGRATION WITH .NET
Set the Startup Object Property for the Project After specifying the code for the forms, you need to specify the order in which the forms should be displayed when the prjDBConnect application is run. It is essential to specify the order in which the forms are displayed because you want to display the frmMDIMain form as the first form of the application. The remaining forms in the application can be displayed when the appropriate menu commands are clicked on. To accomplish this task, you need to set the startup property for the application by using the Startup object property. To set the Startup object property, you need to perform the following steps: 1. Right-click on the project in the Solution Explorer and then select Properties. 2. The prjDBConnect Property Pages dialog box is displayed. The left pane of the dialog box displays a list of property types. Select General from the Common Properties folder. This option is selected by default. Figure 7-18 displays the General option selected from the Common Properties folder. 3. To ensure that the frmMDIMain form is the first form to be displayed when the prjDBConnect application is run, you need to select frmMDIMain from the Startup object drop-down list.
FIGURE 7-18 The General option selected from the Common Properties folder
223-304.qxd 2/24/03 10:46 AM Page 303
CREATING A WINDOWS APPLICATION IN C#
Chapter 7
Summary In this chapter, you learned how to design the forms for an application to display report data and update records. You also learned about the requirements and the design of the application. Finally, you learned about the working of the application and the code attached to the various controls of the different forms.
303
223-304.qxd 2/24/03 10:46 AM Page 304
TE
AM FL Y
This page intentionally left blank
Team-Fly®
305-312.qxd 2/24/03 10:47 AM Page 305
Chapter 8 Transactions in .NET— Overview and Implementation
305-312.qxd 2/24/03 10:47 AM Page 306
he recent years have witnessed a remarkable growth in the Internet and Internet-related technologies. A greater number of organizations have opted for distributed computing as compared to centralized computing. This growth in distributed computing has led to an increase in the requirement for coordinating transactions over the network so that it does not lead to potentially disruptive situations.
T
Consider a situation where two users try to access a Web site at the same time and add data to the database. Based on the timing of the insert operation, there could be three possible outcomes: ◆ Case 1. Both the insert operations will be successful. ◆ Case 2. One of the insert operations will be lost. ◆ Case 3. Both the insert operations will fail because of data corruption. Of these scenarios, Case 2 and Case 3 are situations that could lead to data loss and therefore need to be an important consideration in any application design. Enter transactions that help prevent such situations. In the following sections of this chapter, you will learn what transactions and the transaction models are supported by the .NET Framework. Finally, you will learn to implement manual transactions in an application.
What Is a Transaction? A transaction is a unit of work that is composed of a set of operations that are executed as a whole. Any transaction is an atomic unit of work and a transaction either succeeds or fails as a unit. A transaction has to meet the “ACID test” to handle transactions. In other words, any transaction must exhibit the following properties to qualify as a transaction. ◆ Atomicity. Either all the operations in the transaction are committed or all are rolled back. This means that either all or none of the affected tables will be updated. For instance, in a banking scenario, when money is transferred from one account to another, two accounts are affected. In
305-312.qxd 2/24/03 10:47 AM Page 307
TRANSACTIONS IN .NET
Chapter 8
this case, either both the accounts should be updated or none should be updated. ◆ Consistency. The transaction must leave the entire data in a consistent state. This means that when a transaction is executed it must ensure that all the rules in the database are checked for and met. Going back to our banking scenario, there could be a rule that when the amount being transferred from one account to another is greater that $5000, an entry for the transaction should be made in an Approval table. In this situation, the transaction should be aborted if it is unable to make an entry in the Approval table. ◆ Isolation. This property states that all transactions should run independent of one another. Let me take an example to illustrate this point. Consider a situation where Transaction 1 and Transaction 2 are executing simultaneously. Both these transactions transfer money from one account to another. Based on the Isolation property, Transaction 1 should be able to see the data in the database either before Transaction 2 is completed or after Transaction 2 is completed and vice versa. ◆ Durability. Once a transaction is completed, its results are permanent and cannot be reversed. This actually means that once a transaction is committed, it should survive any system or media failures. In our scenario, if money has been transferred from one account to another and the system crashes after a few seconds, the tables will not show incorrect Credit and Debit balances because the system will ensure that either both accounts or neither account will be affected.
CAUTION Remember that your underlying data source must support transactions in order to use the transaction features supported by Visual Studio.NET.
Having gone through the basic concepts of what makes a transaction and the properties of a transaction, you will next learn about the different transaction models that the .NET Framework supports.
307
305-312.qxd 2/24/03 10:47 AM Page 308
308
Project 1
DATABASE INTEGRATION WITH .NET
Transaction Models The .NET Framework supports two transaction models, manual and automatic. The activities that are performed when programming transactions depend on the transaction model. The CLR supports both types of transaction models. Let me now explain the manual transaction model.
Manual Transaction Model Almost all data access mechanisms such as ADO, OLE DB, and ODBC provide support for the manual transaction model. In a manual transaction: ◆ You can explicitly begin a transaction. ◆ You need to provide all the code support that is required to meet the ACID properties associated with the transaction.
Automatic Transaction Model The .NET Framework supports automatic transactions in ASP.NET applications, XML Web services, and .NET Framework classes. When an application is specified to be part of a transaction, it automatically executes within the scope of the transaction. You can implement automatic transactions in ASP.NET applications running on a Windows 2000 platform by using a directive. The following code sample illustrates the same:
This directive can take the following values: ◆ Supported. Indicates that the Web page runs within the context of a transaction. ◆ NotSupported. Indicates that the Web page does not run within the scope of a transaction. ◆ Disabled. Means that the transaction context will be ignored by the application. ◆ Required. Indicates that the page executes in the context of an existing transaction. In case there are no existing transactions then a new transaction is created.
305-312.qxd 2/24/03 10:47 AM Page 309
TRANSACTIONS IN .NET
Chapter 8
◆ RequiresNew. Indicates that the page executes in a new transaction and every request is executed in a new transaction. The following section discusses the steps involved in implementing manual transaction.
Implementing Manual Transactions in an Application Using ADO.NET You can implement manual transactions in your application using ADO.NET by using three commands. ◆ BEGIN TRANSACTION. This statement marks the beginning of a transaction block. All statements after this command are part of the transaction. ◆ COMMIT TRANSACTION. This statement marks the successful completion of the transaction. ◆ ROLLBACK TRANSACTION. This statement is used to undo a transaction.
Steps Involved in Manual Transactions ADO.NET provides you with the Connection and Transaction objects to implement manual transactions. The steps to follow to implement transactions in an application using ADO.NET are provided in the following list. In all the following code snippets, I am referencing the pubs database in SQL. 1. Create an object of the appropriate Connection class. SqlConnection Connection1 = new SqlConnection(“Data Source=localhost;Integrated
Security=SSPI;Initial Catalog=pubs”);
2. Create an object of the appropriate Transaction class and invoke the BeginTransaction() method of the Connection object. This method marks the beginning of a transaction and returns a reference to the Transaction. SqlTransaction myTrans1 = Connection1.BeginTransaction();
3. Create a Command object of the appropriate class. SqlCommand myCommand = new SqlCommand();
309
305-312.qxd 2/24/03 10:47 AM Page 310
310
Project 1
DATABASE INTEGRATION WITH .NET
4. Associate the Command object with the Connection object. myCommand.Connection=Connection1;
5. Assign the Transaction object to the Transaction property of the Command to be executed. myCommand.Transaction = myTrans1;
6. Execute the required commands. 7. Call the Commit() method of the Transaction object to successfully complete the transaction or else call the Rollback() method to abort the transaction. Having looked at the steps involved in implementing transactions in an application using ADO.NET, I will now discuss a complete sample example, which illustrates the use of transactions.
A Complete Example The following example is created using C# and it uses the Bank1 database as its back-end. The Bank1 database comprises a number of tables that are involved in a typical banking scenario. For this example, two tables of this database are referenced—AcHolderTransact_Info, which stores details of all the transactions related to an account, and AcHolder_Info, which stores all details related to an account holder. The structure of the AcHolderTransact_Info table is given in Table 8-1. Table 8-1 Structure of the AcHolderTransact_Info Table Field Name
Data Type
Account_no
char
Transaction_date
datetime
Transaction_mode
char
Check_no
char
Amount
money
Table 8-2 provides the structure of the AcHolder_Info table.
305-312.qxd 2/24/03 10:47 AM Page 311
TRANSACTIONS IN .NET
Chapter 8
Table 8-2 Structure of the AcHolder_Info table Field Name
Data Type
Account_no
char
Register_Id
char
Balance
money
Account_type
char
Branch
varchar
The following code snippet adds records to the AcHolderTransact_Info table and also updates the details of the transaction in the AcHolder_Info table. SqlConnection Connection1 = new SqlConnection(“Data Source=localhost;Integrated Security=SSPI;Initial Catalog=bank1”); Connection1.Open(); SqlTransaction myTrans1 = Connection1.BeginTransaction(); SqlCommand Command1 = new SqlCommand(); Command1.Connection=Connection1; Command1.Transaction = myTrans1; try { Command1.CommandText=”Insert AcHolderTransact_Info values(‘A00001’,’01Jan 2002’, ‘Debit’, ‘9978’, 2000)”; Command1.ExecuteNonQuery(); Command1.CommandText=”Insert AcHolderTransact_Info values(‘A00002’,’01Jan 2002’, ‘Credit’, ‘9978’, 2000)”; Command1.ExecuteNonQuery(); Command1.CommandText = “update acholder_info set balance=balance -2000 where Account_No = ‘A00001’”; Command1.ExecuteNonQuery(); Command1.CommandText = “update acholder_info set balance=balance +2000 where Account_No = ‘A00002’”; Command1.ExecuteNonQuery(); myTrans1.Commit(); Console.WriteLine(“Records were updated in both the tables”); }
311
305-312.qxd 2/24/03 10:47 AM Page 312
312
Project 1
DATABASE INTEGRATION WITH .NET
catch(Exception e) { myTrans1.Rollback(); Console.WriteLine(e.ToString()); Console.WriteLine(“Neither of the tables were affected”); }
finally { Connection1.Close(); }
Console.ReadLine();
} }
Summary A transaction is a unit of work that is composed of a set of operations that are executed as a whole. Any transaction is an atomic unit of work and a transaction either succeeds or fails as a unit. A transaction must exhibit the following properties: ◆ Atomicity ◆ Consistency ◆ Isolation ◆ Durability The .NET Framework supports two transaction models, manual and automatic. The activities that are performed when programming transactions depend on the transaction model.
313-314.qxd 2/24/03 10:49 AM Page 313
PART
III Professional Project 2
313-314.qxd 2/24/03 10:49 AM Page 314
TE
AM FL Y
This page intentionally left blank
Team-Fly®
315-316.qxd 2/24/03 10:49 AM Page 315
Project 2 XML Designer: Creating XML Schemas
315-316.qxd 2/24/03 10:49 AM Page 316
Project 2 Overview The application created in this project can be used to share reports. Users can use the application to read report data from a remote XML file and display it in a tabular format on the application form. The application will also write and display the same data as an HTML file. Users can send the report data as an XML file through e-mail or FTP. In addition, users can host these files on an intranet site or place them in a shared folder. The application has been built in Visual Basic.NET by using Visual Studio.NET. The following concepts have been used to code this application: ◆ ADO.NET to retrieve data from the pubs database ◆ XSL transformation for HTML creation
317-346.qxd 2/24/03 10:51 AM Page 317
Chapter 9 Overview of XML
317-346.qxd 2/24/03 10:51 AM Page 318
ver since its inception, the Internet has constantly improved and gained importance as an efficient and effective medium for communication and information exchange. Organizations are increasingly dependent on the Web to conduct business, and as a result, the need for communicating information across the world is increasing. To find a solution to the seemingly Herculean task of communication, it is imperative that Web applications present data in a standard format that’s compatible with a majority of hardware and software platforms. The W3C has offered the much-needed solution in the form of XML—one of the latest Web technologies. XML is a markup language defined and standardized by the W3C that prescribes a format for structuring and describing data on the Web. The data presented in the XML format remains uniform and independent of applications or vendors.
E
TIP You can access the W3C Web site at the URL: http://www.w3.org.
XML has provided relief to Web application developers ever since it appeared on the scene in 1998. Most upcoming software, including Microsoft’s .NET Framework, provide inherent support to XML. In this chapter, you will examine the basics of XML and then proceed to learn about XML specifications, architectures, components, and schemas.
Overview of XML and Related Specifications XML is a W3C-defined standard that provides a format to present structured data. The data to be presented are stored in XML documents. These XML documents are similar to databases in the sense that they allow you to store data. XML documents, however, store data as plain text to enable multiple platforms to
317-346.qxd 2/24/03 10:51 AM Page 319
OVERVIEW OF XML
Chapter 9
understand and interpret the data. XML thus provides a standard interface for interchanging data across Web applications, irrespective of platform. In simple terms, XML is a language used to create Web applications. It allows Web application designers to create their own customized tags, enabling the definition, transmission, validation, and interpretation of data between applications. In the .NET framework, XML provides a comprehensive and integrated set of classes and APIs that help you work with XML data and documents. Some of the XML class groups that I will discuss during the course of this chapter include: ◆ Writing XML ◆ Validating XML ◆ XmlReader, XmlWriter ◆ XpathNavigator ◆ XslTransform and XSL Transformations (XSLT) ◆ XslSchema and XML Schema Definition language (XSD) As the first step, you must compare and contrast XML with another popular markup language, HTML. You must also know how to write an XML code and view its output.
XML and HTML HTML uses a set of predefined tags to define the layout of a Web page and the appearance of data on a Web page. XML also uses tags, but they are not predefined and are used for a different purpose. XML tags do not focus on the appearance of the data, but on the data itself. To understand this concept, consider the following example. The ... tags are used in HTML to format the data enclosed within these tags in boldface. Irrespective of the contents, anything within the tags is displayed in boldface when the page is viewed in a browser. On the other hand, XML enables you to create your own tags to define the structure of data. For example, to present employee data of an organization, you can create a tag called to enclose employees’ names within this tag. Thus, tags in XML focus on structuring data rather than the appearance of data. To make the difference between HTML and XML clearer, the output of two sample codes will be shown as examples. First, the following HTML document
319
317-346.qxd 2/24/03 10:51 AM Page 320
320
Project 2
XML DESIGNER: CREATING XML SCHEMAS
named Employees.html is created in Notepad to display employee details in a numbered list: Employee Details
Employee Id: E001
Employee Name : Rita Greg
Employee Id: E002
Employee Name : Robert Brown
When you open this HTML document in a Web browser, you see the output shown in Figure 9-1. Next, create an XML document named Employees.xml in Notepad to describe the data in a structured manner as displayed in the preceding HTML document: E001
FIGURE 9-1 Output of the HTML code
317-346.qxd 2/24/03 10:51 AM Page 321
OVERVIEW OF XML
Chapter 9
Greg Rita E002 Brown Robert
NOTE Remember that XML is case sensitive. Therefore, the tag is not the same as the tag. Be careful when you code XML.
In the preceding code, the first line is an XML declaration statement that notifies the browser that the document being processed is an XML document. When you open this XML document in Internet Explorer, the document appears as shown in Figure 9-2. You’ll notice that the document in Figure 9-2 is displayed in a structured manner, in the form of a tree. Each tag that contains subtags can be expanded or collapsed. All XML documents are displayed in a similar manner.
FIGURE 9-2 Output of the XML code
321
317-346.qxd 2/24/03 10:51 AM Page 322
322
Project 2
XML DESIGNER: CREATING XML SCHEMAS
By now, the basic functionality of XML and its differences with HTML should be clear. Since XML is integrated in .NET, I’ll show you how to create an XML document in the .NET Framework using the XML designer. To create an XML document in the .NET Framework, follow these steps: 1. Create an ASP.NET application project by using Visual Basic.NET and name the project XMLDemo. 2. Choose Project, then Add New Item to open the Add New Item dialog box. 3. In this dialog box, select XML File in the Templates pane. 4. Enter the name of the file as Employees.xml and click Open. The file opens within the XML designer. At the bottom of the designer window two tabs are present: XML and Data. The XML view is used to directly edit the XML code, while the Data view displays the XML data represented by the XML document. You can edit the XML data directly in this view. The XML view is active by default. 5. In the XML view, write the XML code that you wrote using Notepad for the Employees.xml file earlier in this chapter. 6. Switch to the Data view. The data appears as shown in Figure 9-3. Is that all there is to XML in .NET Framework? No! XML has a lot more to offer. Microsoft XML in .NET Framework comes with its own set of specifications and components. You will now learn the basic XML-related specifications as laid down by the W3C.
FIGURE 9-3 The XML Data View in .NET Framework using ASP.NET
317-346.qxd 2/24/03 10:51 AM Page 323
OVERVIEW OF XML
Chapter 9
XML Specifications In this section, you will look at the basics of some of the common specifications related to XML. These specifications include: ◆ Document Type Definition (DTD). DTD documents specify the rules for XML documents that make it easier for everyone to understand the structure and logic of your XML documents. ◆ XML namespaces. When you define multiple elements in an XML document, you use the XML namespaces to avoid conflicting names and to assign a unique name to each element. ◆ Document Object Model (DOM). DOM enables navigation and modification in an XML document, including adding, updating, or deleting content of elements. This also allows you to access XML data programmatically. ◆ Extensible Stylesheet Language Transformations (XSL/T). XSL/Ts are style sheets provided by the W3C to format XML documents. ◆ XML Schemas. XML Schemas can be considered as a superset of DTDs and are also used to define the structure of XML documents. Now I will discuss these specifications in greater detail.
Document Type Definition (DTD) DTD represents a set of rules that define the structure and logic of XML documents. The documents that store these rules are called DTD documents and have the extension .dtd. To better understand the concept of DTD documents, compare them with the creation of tables in a database. When you create a table in a database system, you specify the columns, the data types for different columns, the validation rules for data within columns, and so on. Similarly, you can specify rules that can be used in XML documents, such as tags and attributes, by using a DTD document. DTD documents can be considered to be rulebooks for XML documents.
323
317-346.qxd 2/24/03 10:51 AM Page 324
Project 2
XML DESIGNER: CREATING XML SCHEMAS
TIP It’s not essential for you to create a DTD document for your XML documents. However, a DTD document can be important to users who need to understand the structure of your XML documents or who need to create an XML document similar to the one you’ve already created. These users can refer to your DTD document to understand the structure and logic of your XML documents.
AM FL Y
When you create a DTD document for an XML document, the XML document is checked against the rules specified in the DTD document. If the XML document adheres to all the DTD rules, the document is considered valid. Otherwise, the XML document fails to generate the desired output. To explain how to create a DTD, I’ll continue with the example of the employee structure. Type the following code in Notepad and save the file as Employees.dtd to create a DTD document that you will use later in this chapter.
TE
324
The DTD document declares five elements: Employees, Employee, Id, LastName, and FirstName. Each element declaration statement has three parameters: the keyword ELEMENT, the name of the element, followed by the content type of the element. Therefore, when you consider the preceding code, the first declaration creates an element called Employees, and defines the content type as (Employee)+.
NOTE The + symbol indicates that the Employees element can contain multiple Employee elements.
Similarly, the content type for the Employee element is declared such that it must contain three elements: Id, LastName, and FirstName. The Id, LastName, and FirstName elements can each contain character data. Character data is represented by the keyword (#PCDATA).
Team-Fly®
317-346.qxd 2/24/03 10:51 AM Page 325
OVERVIEW OF XML
Chapter 9
If you want to use the rules declared in a DTD document, you must include it with the XML document that you create. To include the DTD document in an XML document, use the following statement:
Now I will show you how you can include a DTD document in an XML code, and also the effect the DTD has on the XML document. Create an XML document in Notepad named EmployeeDTD.xml, and type the following code: E001 Rita Greg
When you view this XML document in a browser, the browser reports an error because the XML document isn’t valid. According to the DTD document, the element contains three elements: , , and . However, the XML document that you created doesn’t conform to this rule and, therefore, doesn’t pass the validation test.
NOTE When you view the file in a browser, you might actually see an XML-based tree structure. This is because MSXML is a DOM-enabled parser. The error will occur if you use XML DOM objects and set the validateOnParse flag to true in a script. Therefore, to access an XML document and to validate it, you need to use the DOM objects provided by MSXML. The following is a sample script that you can run and enter the name of the XML file that you want to validate. function validate() { var xmldoc = new ActiveXObject(“Microsoft.XMLDOM”); xmldoc.async = false;
continues
325
317-346.qxd 2/24/03 10:51 AM Page 326
326
Project 2
XML DESIGNER: CREATING XML SCHEMAS
NOTE xmldoc.validateOnParse=true; xmldoc.load(TxtXMLFileName.value); var error=xmldoc.parseError; transformedwindow=window.open(‘Transformed.htm’,’_new’,’location=0, status=1,toolbar=0,menuBar=0, scrollBars=0,directories=0,resizable=0,width=600,height=600’); if(error!=””) { transformedwindow.document.write(‘DTD Validator
Error Validating the document
’); transformedwindow.document.write(‘Error URL: ’ + error.url + ‘’); transformedwindow.document.write(‘Error Line: ’ + error.line + ‘’); transformedwindow.document.write(‘Error Position: ’ + error.linepos + ‘’); transformedwindow.document.write(‘Error Reason: ’ + error.reason + ‘’); transformedwindow.document.write(‘’); } else { transformedwindow.document.write(‘DTD ValidatorNo Error ’); transformedwindow.document.write(‘’); } } Enter XML Document Name:
You’ll learn about XML DOM later in this chapter.
317-346.qxd 2/24/03 10:51 AM Page 327
OVERVIEW OF XML
Chapter 9
XML Namespaces As you have seen, you can define your own elements to describe the data while creating XML documents. You can also use elements that you define outside your XML document, such as in a DTD document. However, defining multiple elements might create a problem: you might end up defining the same element twice. For example, when defining the data structure to present employee details, you might define the element twice, once to qualify the employee name and a second time to qualify the department name. This situation is not unlikely when you have a large number of elements to define. It leads to name collisions and your XML document cannot be processed for correct output. To avoid such situations, W3C recommends the use of XML namespaces. XML namespaces are a collection of unique elements identified by Uniform Resource Identifiers (URI) and are declared by using the keyword xmlns. To continue with the example at hand, you can declare an XML namespace for the element that defines the department name using the following statement: xmlns:DepartmentName=”http://www.dn.com/dn”
In this statement, DepartmentName is an alias for the element, and http://www.dn.com/dn is the URI. Later, when you want to use the element to qualify a department name, you must prefix it with the alias DepartmentName, as in the following statement:
NOTE When you specify a namespace URI, the browser does not search the URI or the documents at the specified URL. In fact, the URI just serves as a unique identifier.
XML Document Object Model To access and display XML data in your Web applications, you need to use the XML Web server control and set its specific properties at the design time. In certain situations, you might want to display the XML data based on some conditions. In such cases, you’ll have to access the XML data programmatically. To do that, you must employ the XML DOM. The DOM is an in-memory, cached tree
327
317-346.qxd 2/24/03 10:51 AM Page 328
328
Project 2
XML DESIGNER: CREATING XML SCHEMAS
representation of an XML document that enables the navigation and modification to a document including adding, updating, or deleting content of elements. The DOM represents data as a hierarchy of object nodes.
TIP The Microsoft .NET Framework SDK implements the W3C DOM (Core) Level 1, www.w3.org/TR/REC-DOM-Level-1/level-one-core.html, and the DOM Core, www.w3.org/TR/DOM-Level-2-Core/core.html.
At the top of the hierarchy lies the XML document. To implement XML DOM, the .NET Framework provides a set of classes, which enable you to access the XML data programmatically included in the System.Xml namespace. Some of the classes in the System.Xml namespace are as follows: ◆
XmlDocument.
◆
XmlDataDocument.
◆
XmlDocumentType.
◆
XmlNode. Supports methods for performing operations on the document as a whole, such as loading or saving an XML file.
◆
XmlTextReader.
◆
XmlTextWriter.
◆
XmlElement.
◆
XmlAttribute.
Represents a complete XML document. XmlDocument provides a means to view and manipulate the nodes of the entire XML document. The XmlDocument class has the System.Xml.XmlDocument namespace. Enables you to store and manipulate XML and relational data into a data set. This class is derived from the XmlDocument class. Represents the DTD used by an XML document.
Represents a reader that performs a fast, non-cached, forward-only read operation on an XML document. Represents a writer that performs a fast, non-cached, forward-only generation of streams and files that contain XML data.
XmlNode
Represents a single element from an XML document. Represents a single attribute of an element.
and XmlDocument have methods and properties to:
◆ Access and modify nodes specific to a DOM, such as attribute nodes, element nodes, entity reference nodes, and so on. ◆ Retrieve entire nodes, as well as the information the node contains, such as the text in an element node.
317-346.qxd 2/24/03 10:51 AM Page 329
OVERVIEW OF XML
Chapter 9
There are two other classes that are widely used with XML implementations. These are the XmlReader class and the XmlWriter class.
The XmlReader Class class is an abstract base class that provides non-cached, forward-only, read-only access to XML data. The XmlReader reads a stream or an XML document to check if the document is well made, and generates XmlExceptions if an error is encountered. The XmlReader implements namespace requirements documented as recommendations by the W3C. XmlReader
Since the XmlReader class is an abstract base class, it enables you to customize your own type of reader or extend the functionality of current implementations of other derived classes, such as XmlTextReader, XmlValidatingReader, and XmlNodeReader classes. The XmlReader has various properties and methods associated with it. It has methods to: ◆ Read XML content and extract data from complete XML documents, such as XML text files. ◆ Skip over elements and their content, such as unwanted records. ◆ Determine if an element has content or is empty. ◆ Determine the depth of the XML element stack. ◆ Read attributes of elements. The XmlReader has properties that return information, such as: ◆ The name of the current node. ◆ The content of the current node. Implementations of XmlReader enhance the base class functionality to extend support to various situational requirements. The common implementations of XmlReader can offer fast access to data without validation or complete data validation. The following list describes the some implementations of XmlReader. ◆
XmlTextReader Class.
◆
XmlNodeReader Class.
Reads data extremely fast. It is a forward-only reader that has methods that return data on content and node types. Has no DTD or schema support. Provides a parser over an XML DOM API, like the XmlNode tree. Takes in an XmlNode as a parameter and returns all
329
317-346.qxd 2/24/03 10:51 AM Page 330
330
Project 2
XML DESIGNER: CREATING XML SCHEMAS
nodes that it finds in the DOM tree. Has no DTD or schema validation support but it can resolve entities defined in DTD. ◆
XmlValidatingReader Class.
Provides a fully compliant validating or non-validating XML parser with DTD, XSD Schema, or XDR Schema support.
◆ Custom XML Readers. Allows developer-defined derivations of the XmlReader.
The XmlWriter Class is also an abstract base class and it defines an interface for creating XML documents. The XmlWriter provides a forward-only, read-only, non-cached way of generating XML streams, which help you build XML documents that conform to the W3C and Namespace recommendations. XmlWriter
The XmlWriter has methods and properties that allow you to: ◆ Create well-made XML documents. ◆ Specify whether the XML document should support namespaces. ◆ Write multiple documents to one output stream. ◆ Manage the output, determine the progress of the output, and close the output. ◆ Report the current namespace prefix. ◆ Write valid and qualified names. However, the XmlWriter does not check for: ◆ Invalid element and attribute names. ◆ Unicode characters that do not match the encoding. ◆ Duplicate attributes. The XmlWriter has one implementation, the XmlTextWriter.
Simple API for XML One of the main advantages of DOM is that it is a hierarchical representation of XML object nodes and enables modification of each node. But at times, this could act to your disadvantage, especially if your document is large.
317-346.qxd 2/24/03 10:51 AM Page 331
OVERVIEW OF XML
Chapter 9
When you use the DOM to manipulate an XML file, the DOM reads the file, breaks it up into individual objects, such as elements, attributes, and comments, and then creates a tree structure of the document in memory. The benefit of using the DOM is that you can reference and manipulate each object, called a node, individually. However, creating a tree structure for a document, especially a large document, requires significant amounts of memory. The Simple API for XML (SAX) is an interface that allows you to write applications to read data in an XML document. SAX2, the latest version of SAX, provides a simple, fast, low-overhead alternative to processing through the DOM. Unlike the DOM, SAX2 is events-based. This means that SAX2 generates events as it finds specific symbols in an XML document. One major advantage of SAX2 is that it reads a section of an XML document, generates an event, and then moves on to the next section. This kind of serial processing of documents enables SAX2 to use less memory than the DOM and, therefore, is better for processing large documents. SAX2 can create applications that abort processing when a particular piece of information is found. You can choose SAX over DOM in the following situations: ◆ When your documents are extremely large ◆ When you want to abort processing a document when a specific piece of information is found ◆ When you want to retrieve specific bits of information ◆ When you want to create a document structure with only high-level objects and not with low-level elements, attributes, and instructions as in the DOM ◆ When you cannot afford the DOM due to high memory requirements against low availability
Extensible Stylesheet Language Transformations As I have already discussed, the basic aim of XML is to describe structured data rather than to focus on the presentation of data. XML documents do not contain any tags that define the format of the data to be displayed. This fact has its unique advantages and helps XML documents remain platform independent. However, you can apply any format to the data and display the same data in multiple formats using special stylesheets.
331
317-346.qxd 2/24/03 10:51 AM Page 332
332
Project 2
XML DESIGNER: CREATING XML SCHEMAS
W3C has specified a stylesheet called Extensible Stylesheet Language Transformations (XSLT) specifically designed for XML documents. The goal of XSLT is to transform the content of a source XML document into another document that is different in format or structure, such as transforming an XML document into HTML for displaying in Web applications. In the .NET Framework, the XslTransform class, found in the System.Xml.Xsl namespace, is an XSLT processor that implements the functionality of this specification. To create an XSL stylesheet in the .NET Framework, use the XSL or XSLT file in the Add New Item dialog box. For example, the following code defines a stylesheet named Employees.xslt for the Employees.xml document:
Employee Id : Last Name : First Name :
In the preceding code: ◆ The element allows you to create a template to display the data in the required format. ◆ The element is used to perform a task repeatedly. ◆ The element is used to retrieve the data from individual elements.
317-346.qxd 2/24/03 10:51 AM Page 333
OVERVIEW OF XML
Chapter 9
After you create the .xslt file, include this file with your XML file to apply the format. To do this step, open the employees.xml file in the XML view and, after the first line, add the following line:
When you browse the employees.xml file in a browser, the output looks formatted and appears as shown in Figure 9-4. XSLT uses XPath to select parts of an XML document that are to be formatted. XPath is a query language used to navigate nodes of a XML document tree. The following is a list of classes commonly used when working with Xpath:
XSLT
and
◆ XPathNavigator. It is an API that provides a cursor style model for navigating over a data store. For editing the store, you need to use the XmlDocument class. ◆ IXPathNavigable. It is an interface that provides a CreateNavigator method to an XPathNavigator for the data store. ◆ XmlDocument. It enables editing of a document. It implements IXPathNavigable to allow editing of document scenarios where XSLT are subsequently required.
FIGURE 9-4 The Employees.xml file as displayed in the browser after including an XSLT
stylesheet
333
317-346.qxd 2/24/03 10:51 AM Page 334
Project 2
XML DESIGNER: CREATING XML SCHEMAS ◆ XmlDataDocument. It is a subclass of the XmlDocument class. It bridges the relational database and XML worlds by using a DataSet to optimize storage of structured data within the XML document according to specified mappings on the DataSet. It implements the IXPathNavigable class to allow document scenarios where XSLT can be performed over relational data retrieved from a database. ◆ XPathDocument. It provides a performance cache to optimize XslTransform processing and XPath queries. It implements IXPathNavigable.
XML Schemas
AM FL Y
◆ XPathNodeIterator. It provides navigation over an XPath nodeset. All XPath selection methods on the XPathNavigator return an XPathNodeIterator. Multiple XPathNodeIterators can be created over the same store each representing a selected set of nodes.
The XSD language enables you to define the structure and data types for XML documents. To understand the concept of schemas, I would again like to draw a comparison with a database system. You might know about database schemas that define and validate the tables, columns, and data types that make up the database. Like database schemas, XML Schemas also define and validate the content and structure of XML documents and can be used to maintain consistency among various XML documents. XML Schema files have the .xsd extension.
TE
334
NOTE The Schema element definition in an XML document must include the namespace: http://www.w3.org/2001/XMLSchema.
But DTDs are also used to define the structure of XML documents. The question that arises here is: how are XML Schemas different from DTDs? XML Schemas are not really different from DTDs; they only offer a greater functionality. XML Schemas can be considered to be supersets of DTDs. XML Schemas offer the following advantages over DTDs: ◆ DTDs help you specify whether an element can be empty or can contain character data or other elements. In contrast, XML Schemas enable you
Team-Fly®
317-346.qxd 2/24/03 10:51 AM Page 335
OVERVIEW OF XML
Chapter 9
to specify whether an element can contain an integer, float, or string value. ◆ Unlike DTDs, which have their own syntax, XML Schemas use the XML syntax, so you don’t have to learn a new syntax to create XML Schemas. XML Schemas contain attribute and element declarations and type definitions for elements. Two basic types of elements can be declared: simpleType element and complexType element. These element types can be used to define custom data types in addition to the built-in data types provided by XSD, such as integer and string. These two data types can be defined as follows: ◆ simpleType. A type definition for a value that can be used as the content (textOnly) of an element or attribute. This data type cannot contain other elements or have attributes. ◆ ComplexType. A type definition for elements that contain elements and attributes. This data type can contain elements and have attributes. The element declarations in a schema define the elements, their contents, and attributes that can be used, as well as the rules for their appearance in an XML document that uses the defined schema. An element declaration can contain either a simpleType or complexType element. If elements and attributes are defined within the complexType element, the number of elements can be controlled. You can use the minOccurs and maxOccurs attributes to define the number of occurrences of an element in an XML document based on the schema. The following list describes the elements with XSD: ◆ all. Allows the elements in the group to appear (or not appear) in any order in the containing element. ◆ any. Enables any element from the specified namespace(s) to appear in the containing complexType, sequence, all, or choice element. ◆ anyAttribute. Enables any attribute from the specified namespace(s) to appear in the containing complexType element. ◆ annotation. Defines an annotation. ◆ appinfo. Specifies information to be used by applications within an annotation element.
335
317-346.qxd 2/24/03 10:51 AM Page 336
336
Project 2
XML DESIGNER: CREATING XML SCHEMAS ◆ attribute. Declares an attribute. ◆ attributeGroup. Groups a set of attribute declarations so that they can be incorporated as a group into complexType definitions. ◆ choice. Allows one and only one of the elements contained in the group to be present within the containing element. ◆ ComplexContent. Contains extensions or restrictions on a complex type that contains mixed content or elements only. ◆ complexType. Defines a complexType, which determines the set of attributes and the content of an element. ◆ documentation. Specifies information to be read or used by users within the annotation element. ◆ element. Declares an element. ◆ extension. Contains extensions on complexContent or simpleContent, which can also extend a complexType. ◆ field. Specifies an XML Path Language (XPath) expression that specifies the value (or one of the values) used to define an identity constraint (unique, key, and keyref elements). ◆ group. Groups a set of element declarations so that they can be incorporated as a group into complexType definitions. ◆ import. Identifies a namespace whose schema components are referenced by the containing schema. ◆ include. Includes the specified schema document in the target namespace of the containing schema. ◆ key. Specifies that an attribute or element value (or set of values) must be a key within the specified scope. ◆ keyref. Specifies that an attribute or element value (or set of values) correspond with those of the specified key or unique element. ◆ list. Defines a simpleType element as a list of values of a specified data type. ◆ notation. Contains the definition of a notation. ◆ redefine. Allows simple and complex types, groups, and attribute groups that are obtained from external schema files to be redefined in the current schema.
317-346.qxd 2/24/03 10:51 AM Page 337
OVERVIEW OF XML
Chapter 9
◆ restriction (XSD). Defines constraints on a simpleType, simpleContent, or complexContent definition. ◆ schema. Contains the definition of a schema. ◆ selector. Specifies an XPath expression that selects a set of elements for an identity constraint (unique, key, and keyref elements). ◆ sequence. Requires the elements in the group to appear in the specified sequence within the containing element. ◆ simpleContent. Contains either the extensions or restrictions on a complexType element with character data, or contains a simpleType element as content and contains no elements. ◆ simpleType. Defines a simpleType, which determines the constraints on and information about the values of attributes or elements with text-only content. ◆ union. Defines a simpleType element as a collection of values from specified simple data types. ◆ unique. Specifies that an attribute or element value (or a combination of attribute or element values) must be unique within the specified scope.
Schema Object Model The Schema Object Model (SOM) provides a set of classes in the System. Xml.Schema namespace that is fully compliant with the W3C XML Schema recommendation specifications. These classes allow you to programmatically create a schema in memory that you can compile and validate. The SOM provides the following features: ◆ Loads and saves valid XSD Schemas to and from files. ◆ Provides an easy way to create memory resident schemas using strongly typed classes. ◆ Interacts with the XmlSchemaCollection class to cache and retrieve schemas. ◆ Interacts with the XmlValidatingReader class (through the XmlSchemaCollection class) to validate schemas against XML documents. ◆ Enables developers to build editors for creating and maintaining schemas.
337
317-346.qxd 2/24/03 10:51 AM Page 338
338
Project 2
XML DESIGNER: CREATING XML SCHEMAS
Schema Designer To understand the concept of XML Schemas in the .NET Framework, I’ll demonstrate the use of the XML designer to create an XML Schema for the Employees.xml document. You’ll work on the same project XMLDemo that you created earlier in this chapter. The XML Schema Designer provides a set of visual tools for working with XML Schemas and documents. The XML Designer supports the XSD language as defined by the WC3. The designer does not support DTDs or other XML Schema languages, such as XDR. The XML Schema designer provides three views that you can work with: ◆ Schema view. Provides a visual representation of the elements, attributes, and types for creating and modifying XML Schemas. In this view you can construct schemas and datasets by dropping elements on the design surface from either the XML Schema tab of the Toolbox or from Server Explorer. ◆ Data view. Provides a data grid that can be used to modify XML documents. In this view, you can modify the actual content of an XML file as opposed to tags and structures. ◆ XML view. Provides an editor for editing XML source code and provides IntelliSense and color coding, including complete Word and List members. To create a schema using the XML Schema Designer, open the project and follow these steps: 1. Open the Add New Item dialog box by choosing Project, then Add New Item. 2. Select XML Schema in the Templates pane, enter the name of the file, Employees.xsd, and click on OK. The designer opens in the Schema view. In this view, you can design the schema visually by using the Toolbox. The designer also provides the XML view that you can use to write the XML code to create the XML Schema. 3. Switch to the XML view and write the following code to define the structure of the XML data represented in the Employees.xml document:
317-346.qxd 2/24/03 10:51 AM Page 339
OVERVIEW OF XML
Chapter 9
In the preceding code, the following occurs: ◆ The XML Schema elements are defined in the XML Schema namespace. ◆ The element describes the data that it contains. ◆ The element can contain additional elements and attributes. 4. Switch to the Schema view. You see the schema as shown in Figure 9-5.
FIGURE 9-5 The Schema View of the Employees.xsd file
339
317-346.qxd 2/24/03 10:51 AM Page 340
340
Project 2
XML DESIGNER: CREATING XML SCHEMAS
Validating XML Data A well-formed XML document must meet all the syntactical requirements specified by the W3C and must conform to constraints defined by its DTD or schema that are used to define document structure, element relationships, data types, and content constraints. The XmlValidatingReader provides DTD, XDR, and XSD schema validation services by implementing the validity constraints defined by the W3C. The XmlValidatingReader class also enforces XML validation. Validation is performed in a forward-only manner over a stream of XML. The XmlValidatingReader also supports the ability to parse XML fragments with the XmlParserContext class.
NOTE Because the XmlValidatingReader is an implementation of the XmlReader class, it can take an XmlTextReader as an input. Any properties set on the supplied XmlTextReader also apply to the containing XmlValidatingReader.
To load an XmlValidatingReader as input to an XML document, the following code can be used. In this sample code, a document Employees is loading an XmlValidatingReader, vr, as input. Employee doc = new XmlDocument(); XmlTextReader tr = new XmlTextReader(“reader.xml”); XmlValidatingReader vr = new XmlValidatingReader(tr); doc.Load(vr);
In the preceding code, doc is an identifier for the XML document, tr is an alias for the XmlTextReader, and vr is an alias for the XmlValidatingReader. You use the Reader.
Load
method to load an XML Document with an
XmlValidating-
NOTE If the XmlValidatingReader generates errors, these validation errors and problems are reported through the ValidationEventHandler callback method. If no ValidationEventHandler is supplied, the first validation error is reported by raising an XmlException. If an XmlException is generated, the XmlValidatingReader cannot be restarted.
317-346.qxd 2/24/03 10:51 AM Page 341
OVERVIEW OF XML
Chapter 9
DTD Validation of an XML Document DTD validation is implemented using the validity constraints defined in the W3C. As I have discussed earlier, DTDs use a formal set of rules to describe the structure and syntax of compliant XML documents. DTDs specify content and values allowed for the XML document. XML documents are associated with and validated against the DTD defined in the declaration, which can be either an inline DTD or a reference to an external DTD file. For information on how to create a DTD and include it in an XML document for validation purposes, refer to the section titled “Document Type Definition (DTD)” earlier in this chapter.
XDR Validation of the XML Document XDR Schema validation is implemented using the validity constraints defined in the Microsoft XML Parser (MSXML) Schema specification. XDR Schemas are recognized by the use of the MSXML x-schema: namespace prefix. The following example shows an instance document validated against an XDR Schema. First, create a file named Employees.xdr using the following code:
341
317-346.qxd 2/24/03 10:51 AM Page 342
342
Project 2
XML DESIGNER: CREATING XML SCHEMAS
Then, create an XML file with the following code: Rita Greg 12 Edward Jones 15
This code is validated against the XDR you created earlier.
XSD Validation of the XML Document XSD validation is implemented using the validity constraints specified by the W3C. All XSD Schemas must include the namespace: http://www.w3c.org/ 2001/XMLSchema. The following example shows an XML document validated against an XSD Schema using the schemaLocation attribute. First, create a file named employee.xsd using the following code: Starting today Mars moves into Aries giving you six weeks when your self interests must take center stage as it’s time for you to shine. You’ll start to reassess your dreams and goals, and could find them wanting. Perhaps you didn’t factor in your spiritual life when contemplating the future. Take this opportunity to make more time for your Higher Power each day. This can include prayer, meditation, or just stopping to appreciate nature, that way your ego won’t become unbearable. A stop-go kind of day so pause for thought and tie up loose ends that could trip you up and think very carefully about your next move. Career has been a prominent focus these past two weeks, and you’re prepared to make some changes. Whether you want to increase or decrease your hours is up to you. It’s possible you’re thinking of changing jobs altogether. Honor your instincts, but don’t make any permanent moves in the near future. You need to reinvest in the past few weeks as you overlooked something which will prove invaluable to you when a murky situation arises. Mercury, your ruling planet, goes retrograde for the next three weeks, prompting you to reconsider previous options. Going on a long journey is certainly a good idea, but try not to leave until February 8th, or your progress will be constantly impeded by mix-ups. This is a good time to research discount air and hotel fares and make preparations.
827
823-840.qxd 2/24/03 11:20 AM Page 828
828
Part IX
BEYOND THE LAB
Hostile forces in your career emanate from a man who feels threatened by you. A showdown is imminent if you are to further your ambitions. Rearranging joint finances may be the best way to preserve harmony in a relationship. Consult an accountant or financial adviser to create a savings or current account that best suits your needs. In the meantime, don’t make any serious purchases until February 8th is gone, or you could get stuck with a non-returnable lemon. Fantastic energy from Mars injects you with the spirit of adventure travel, study or anything that stimulates you mind, body and spirit is a must. Your approach to relationships could stand some fine-tuning; experiment with different methods. Your strong personality is bound to intimidate shy, retiring types. Practice taking a low-key attitude with such folks. You’ll find they become much more responsive to your ideas. Give it a shot! If at first you don’t succeed try try again but not until after February 8th as any knock backs before are a blessing in disguise. Revising your daily routine is essential if you’re going to improve your health. Knowing you, it’s likely that you’ve taken on too many responsibilities over the past two weeks. Just because you’ve committed to certain projects doesn’t mean you can’t change your mind. Start paring down your schedule and sort out the wheat from the chaff. A sexy scenario develops in a close relationship as the next six brings you passions ever closer to the surface but be sure they don’t boil over. A creative project that has been giving you the ab-dabs seems ready for the trash heap. Before you do anything drastic, though, make a few alterations. One change or a wee bit of tweaking could lead to another, then another, until the
823-840.qxd 2/24/03 11:20 AM Page 829
MOBILE APPLICATIONS IN .NET
Chapter 24
entire work is transformed into a masterpiece. Sometimes you have to take one step backward to take two steps forward. Secrets and lies from a relative won’t be apparent until Feb until then make sure you are as transparent as possible in your own dealings. If your world is less than rewarding, you don’t have to panic; simply make some adjustments. Maybe you should look around for a new place. Perhaps all you need to do is remodel your routines. Think about getting rid of some inherited pieces that make you depressed or angry. Make the space around you a reflection of what you value most—oh and whilst you’re at it get your health checked especially if you’ve been feeling over tired. Be enterprising in everything you do from love to developing your personal talents and you can be sure before Easter you’ll have a hit on your hands. Messages, mail, and important papers have a way of getting lost as Mercury turns retrograde. Make a special effort to keep track of communications between now and February 8th. If something does go astray, don’t panic. It will turn up when you least expect it. In the meantime, busy yourself with issues that really concern you and your community. Before I forget, if you have an idea write down as it won’t come back into head in the same form. Money muddles must be sorted pronto and be warned of a man under your roof who needs putting in his place before he gets the upper hand. Finances however, need immediate action, which may mean an overdraft is likely if you’re not vigilant. Spend the next three weeks going through paperwork and receipts so you know where you stand. After reviewing your spending and budgets you’ll be shocked to see where you’ve been wasting precious resources. Over the next couple of weeks take it easy in all communications, double-check all info, facts, and data to avoid getting egg on your face.
829
823-840.qxd 2/24/03 11:20 AM Page 830
830
Part IX
BEYOND THE LAB
Try not to jump to conclusions, as many facts about your personal life will remain hidden for the next three weeks. People will act strangely, things will be misplaced, and a general sense of confusion will rein. That’s usual when Mercury is retrograde. The reasons for all these mix-ups will become apparent early next month. Sit tight! The stars wrest power from you as they come and go with all kinds of suggestions and opportunities think everything through before commitment. Confronting your secret motivations can be a painful but worthwhile exercise. You can be your own worst enemy at times. Admit your tendency toward self-pity is a destructive one, and vow to reform. If you’re really vigilant, you will become a better, brighter version of yourself in a matter of weeks.
To create the mobile application perform the following steps: 1. Select File, New, Project to open the New Project dialog box. 2. In the Project Types pane, choose Visual C# Projects. 3. In the Templates pane, choose Mobile Web Application. 4. In the Location box, enter the project name as MobileHoroscope and accept the default Web server as shown in Figure 24-2. 5. Click on OK to create the project. The WebForm1.aspx file opens in the design view. Visual Studio.NET creates a number of default files for the mobile Web application as displayed in the Solution Explorer window. The MobileWebForm1.aspx file is selected by default. In addition to the default files, Visual Studio.NET creates a blank mobile Web Form, Form1, in the design view.
Creating the Mobile Web Form for Users to Select a Zodiac Sign When a user connects to the application, the mobile Web Form will be displayed. The user can select a zodiac sign to get the horoscope or click on a Command to
823-840.qxd 2/24/03 11:20 AM Page 831
MOBILE APPLICATIONS IN .NET
Chapter 24
FIGURE 24-2 The New Project dialog box for MobileHoroscope application
request a form based on a range of dates. To create this mobile Web Form, perform the following steps: 1. Select the default mobile Web Form Form1 in the design view. Configure the form in the Properties window by specifying the ID property as frmSelectZodiac. 2. Now add a Label control from Mobile Web Forms tab of the Toolbox. Specify its ID as Label1 and its Text as Select your zodiac. 3. From the Mobile Web Forms tab of the Toolbox now add a SelectionList to frmSelectZodiac. In the Property window, specify the ID property as SelectionList1. In the Items property, click on the ellipsis button. The SelectionList1 Properties dialog box appears as shown in Figure 24-3. Click on the Create New Item button. In the Item Text pane specify your item as Aries and check the Selected check box. Now click on the Create New Item button again to enter your second item Taurus. Similarly, add all the items you want to appear in the drop-down list. You need to add the 12 zodiac signs that you want to appear in the drop-down list. After you have completed adding the items, click on Apply. Click on OK to close the dialog box.
831
823-840.qxd 2/24/03 11:20 AM Page 832
832
Part IX
BEYOND THE LAB
FIGURE 24-3 The SelectionList1 Properties dialog box
4. Now add a Command control and specify its ID as cmdHor and Text as Get Horoscope. 5. Add a Label to frmSelectZodiac and specify its ID as Label2 and its Text as Don’t know your zodiac? 6. Add a Command control specifying the ID as Command1 and Text as Click Here. When a user selects a zodiac sign and clicks on the cmdHor Command control, the horoscope corresponding to the zodiac sign should be displayed. To display the horoscope corresponding to the zodiac sign when a user selects a zodiac sign and clicks on the cmdHor Command control, double-click on the cmdHor Command control. Observe the event handler that appears in the class file MobileWebForm1.aspx.cs. private void cmdFor_Click(object sender, System.EventArgs e) { }
Now add the following code in the method as shown in the table. private void cmdHor_Click(object sender, System.EventArgs e) { XmlTextReader reader = new XmlTextReader(“C:\\Horoscope.xml”);
823-840.qxd 2/24/03 11:20 AM Page 833
MOBILE APPLICATIONS IN .NET
Chapter 24
reader.MoveToContent(); while (reader.Read()) { if (reader.HasAttributes) { reader.MoveToNextAttribute(); if(reader.Value==SelectionList1.Selection.Text) { lblHor.Text=reader.Value + “ (“; reader.MoveToNextAttribute(); lblHor.Text=lblHor.Text + reader.Value + “)”; reader.MoveToElement(); txtHor.Text=reader.ReadInnerXml(); } } } reader.Close(); ActiveForm=frmHoroscope; }
The preceding code creates an XmlTextReader instance variable, and using the XmlTextReader, the code sets the content of the file Horoscope.xml to the TextView control txtHor. If a user does not know his or her zodiac sign, he or she can click the Command1 Command control to access the form that displays the horoscope based on dates. For that, do the following: 1. Double-click on the Command1 Command control and add the following code to the Command1_Click event handler. private void Command1_Click(object sender, System.EventArgs e) { ActiveForm=frmHorByDate; }
When a user clicks on the played to the user.
Command1
control, the form
frmHorByDat
will be dis-
833
823-840.qxd 2/24/03 11:20 AM Page 834
Part IX
BEYOND THE LAB
Creating the Mobile Web Form to Display the Horoscope When a user makes a request for a horoscope based either on the zodiac sign or the range of date, the mobile Web Form will be displayed showing the horoscope the user requested. To create this mobile Web Form, perform the following steps: 1. Add a Form control from Mobile Web Forms tab of the Toolbox. Position it in the MobileWebForm1.aspx in the design view specifying the ID property as frmHoroscope.
AM FL Y
2. In the frmHoroscope form control, add the following mobile Web controls from the Mobile Web Forms tab of the Toolbox and configure their properties as shown in the table below. Table 24-1 Properties of Controls Controls
Properties
Label
ID=lblHor, Text= Label
TextView Command
TE
834
ID=txtHor, Text=TextView ID=cmdGoBack, Text=Back
3. Double-click on the Command control and add the following code to the cmdGoBack_Click event handler. private void cmdGoBack_Click(object sender, System.EventArgs e) { ActiveForm=frmSelectZodiac; }
The preceding code will display the form frmSelectZodiac when a user clicks on the Command control cmdGoBack after seeing his or her horoscope.
Creating a Mobile Web Form to Display a Range of Dates This form will display a list, named Selection List, consisting of a range of dates corresponding to the zodiac signs. A user will select a range of dates and click on the Command control to access the horoscope. For creating the mobile Web Form, perform the following steps:
Team-Fly®
823-840.qxd 2/24/03 11:20 AM Page 835
MOBILE APPLICATIONS IN .NET
Chapter 24
1. Add a Form control from the Mobile Web Forms tab of the Toolbox. Position it in the MobileWebForm1.aspx in the design view specifying the ID property as frmHorByDate. 2. In the frmHorByDate Form control, add the following mobile Web controls from the Mobile Web Forms tab of the Toolbox and configure their properties as shown in the following table. Table 24-2 Properties of Controls Controls
Properties
Label
ID=Label3 Text=Select the range of your date of birth
SelectionList
ID=SelectionListByDate
Command
ID=Command2 Text=Get Horoscope
In the SelectionList’s Items property, add the items you want to display in the list box. You will add the date ranges corresponding to each zodiac sign. 3. Double-click on the Command button and add the following code to the Command2_Click event handler. private void Command2_Click(object sender, System.EventArgs e) { XmlTextReader reader = new XmlTextReader (“C:\\Horoscope.xml”); //reader.WhitespaceHandling=WhitespaceHandling.None; reader.MoveToContent(); while (reader.Read()) { if (reader.HasAttributes) { reader.MoveToNextAttribute(); reader.MoveToNextAttribute(); if (reader.Value==SelectionListByDate.Selection. Text) {
835
823-840.qxd 2/24/03 11:20 AM Page 836
836
Part IX
BEYOND THE LAB
reader.MoveToFirstAttribute(); lblHor.Text=reader.Value + “ (“; reader.MoveToNextAttribute(); lblHor.Text=lblHor.Text + reader.Value + “)”; reader.MoveToElement(); txtHor.Text=reader.ReadInnerXml(); } } } reader.Close(); ActiveForm=frmHoroscope; }
The preceding code performs the same functionality as the code in the cmdHor_Click event handler. After creating the previous mobile Web Forms, in your mobile Web Forms page, your MobileWebForm1.aspx should look similar to Figure 24-4.
FIGURE 24-4 The MobileWebForm1.aspx
823-840.qxd 2/24/03 11:20 AM Page 837
MOBILE APPLICATIONS IN .NET
Chapter 24
Testing and Building the Mobile Application After you have created the XML file and the preceding Mobile Web Forms, you are ready to build and test your mobile application. To build and test your mobile application, perform the following steps: 1. Access the Build menu and click on Build MobileHoroscope. If your application has been successfully built, the output window will be as shown in Figure 24-5. 2. Test your application by typing the following in the address bar of your browser as shown in Figure 24-6: address—http://localhost/MobileHoroscope/MobileWebForm1.aspx
3. Select a zodiac sign in the displayed form and click on Horoscope. The horoscope corresponding to the zodiac sign you selected will be displayed to you as shown in Figure 24-7. 4. Click on Back to go back to the first form. 5. Now click on Don’t know your zodiac? to view the form that a user can use to access the horoscope based on date. Figure 24-8 shows the form that will be displayed.
FIGURE 24-5 The output window after building the MobileHoroscope application
837
823-840.qxd 2/24/03 11:20 AM Page 838
838
Part IX
BEYOND THE LAB
FIGURE 24-6 The address to load your application
FIGURE 24-7 The form that displays the horoscope to the user
6. Select a date range from the SelectionList and click on the GetHoroscope Command. You will be displayed the horoscope based on the range of dates you selected.
823-840.qxd 2/24/03 11:20 AM Page 839
MOBILE APPLICATIONS IN .NET
Chapter 24
FIGURE 24-8 The form that a user will use to select the range of dates
Summary In this chapter you have learned what a mobile application is. You learned: ◆ About the Microsoft Mobile Internet Toolkit ◆ How to create a Mobile application ◆ How to create a form that a user will use to select the zodiac sign ◆ How to create a form that displays the horoscope to the user Finally, you learned how to build your application and test its functionality in the browser.
839
823-840.qxd 2/24/03 11:20 AM Page 840
This page intentionally left blank
841-842.qxd 2/24/03 11:21 AM Page 841
PART
X Appendixes
841-842.qxd 2/24/03 11:21 AM Page 842
This page intentionally left blank
843-850.qxd 2/24/03 11:22 AM Page 843
Appendix A Upgrading/ Migrating from Visual Basic 6.0 to Visual Basic .NET
843-850.qxd 2/24/03 11:22 AM Page 844
Migration
AM FL Y
You might want to use a Visual Basic 6.0 application in the .NET environment. For example, you might have a Visual Basic 6.0 application that you want to integrate with other applications developed in the .NET environment. In addition, you might want to implement the enhanced features of .NET. To work with a Visual Basic 6.0 application in the .NET environment, you must upgrade the application by using the Visual Basic Upgrade Wizard. The Visual Basic Upgrade Wizard starts automatically when you open a Visual Basic 6.0 application in Visual Studio.NET.
TE
The following section details the steps to migrate a Visual Basic 6.0 application to the .NET environment: 1. Choose Start, Programs, Microsoft Visual Studio .NET, Microsoft Visual Studio .NET to open the Microsoft Development Environment as shown in Figure A-1.
FIGURE A-1 The Start Page window
Team-Fly®
843-850.qxd 2/24/03 11:22 AM Page 845
UPGRADING/MIGRATING FROM VB 6.0 TO VB.NET
Appendix A
2. Choose File, Open, Project to display the Open Project dialog box. 3. Navigate to the folder where you have stored the Visual Basic 6.0 application. (Here, it is D:\VBProj.) 4. Select the project file that you want to migrate to the .NET environment. (Here, it is Creditcard.vbp.) 5. Click on the Open button (in the Open Project dialog box). The Open Project dialog box closes and Page 1 of 5 of the Visual Basic Upgrade Wizard appears (see Figure A-2). 6. Click on Next to move to Page 2 of the Upgrade Wizard (see Figure A-3). This dialog box displays two radio buttons to specify whether the existing Visual Basic 6.0 application will be converted to an EXE or a DLL. (The Upgrade Wizard, by itself, detects if your application is an EXE or a DLL. Therefore, one of the buttons will be disabled.) 7. Click on Next to move to Page 3 of the Upgrade Wizard (see Figure A-4). You can specify the name of the project and the path where the .NET application needs to be stored. By default, the wizard specifies the name as Project1 and the folder name is the same as your working folder.
FIGURE A-2 Visual Basic Upgrade Wizard
845
843-850.qxd 2/24/03 11:22 AM Page 846
846
Part X
APPENDIXES
FIGURE A-3 The Choose a Project Type and Set Options screen
FIGURE A-4 The Specify a Location for your New Project screen
8. Edit the displayed path to suit your requirements, if necessary. (In Figure A-5, it is CreditcardProject.NET.)
843-850.qxd 2/24/03 11:22 AM Page 847
UPGRADING/MIGRATING FROM VB 6.0 TO VB.NET
Appendix A
FIGURE A-5 Page 3 of 5 of the Upgrade Wizard
9. Click on the Next button. A dialog box is displayed that prompts the user to create a folder if the folder does not exist, as shown in Figure A-6. 10. Click on the Yes button. Page 4 of Upgrade Wizard appears, as shown in Figure A-7. This page informs you that the Wizard is ready to upgrade your application. 11. Click on the Next button. Page 5 of Upgrade Wizard appears, as shown in Figure A-8. The upgrade then proceeds to completion, as shown in Figure A-9. After the upgrade is complete, the migrated project (CreditcardProject) is displayed in the Visual Basic.NET window. The project is also added to the Solution Explorer window (see Figure A-10).
FIGURE A-6 The Warning dialog box
847
843-850.qxd 2/24/03 11:22 AM Page 848
848
Part X
APPENDIXES
FIGURE A-7 Page 4 of 5 of Upgrade Wizard
FIGURE A-8 Page 5 of 5 of Upgrade Wizard
843-850.qxd 2/24/03 11:22 AM Page 849
UPGRADING/MIGRATING FROM VB 6.0 TO VB.NET
FIGURE A-9 Page 5 of 5 of Upgrade Wizard
FIGURE A-10
The Visual Basic.NET window
Appendix A
849
841-842.qxd 2/24/03 11:21 AM Page 842
This page intentionally left blank
851-868.qxd 2/24/03 11:23 AM Page 851
Appendix B Migrating from VC++ 6.0 (unmanaged code) to VC++.NET (managed extensions)
851-868.qxd 2/24/03 11:23 AM Page 852
ith the advent of new technology, companies are constantly faced with the dilemma of missing out on the new features of the product if they don’t migrate or, on the flip side, investing a huge amount of time and money in migrating to the new environment. The decision to migrate is often weighed in terms of long- and short-term benefits and the final decision is made only after all options have been thoroughly checked.
W
Microsoft introduced the concept of managed extensions with the release of the .NET Framework to meet this demand. Packaged along with the .NET Framework is an application called managed extension, which allows you to retain pure C++ and MFC code and yet leverage all the advantages of the .NET Framework. With the introduction of managed extensions, you can continue to use applications that are based on unmanaged code and run outside the CLR, which includes applications that are developed using MFC. You also have the option of creating applications that are based on managed extensions and make use of the .NET Framework class libraries and run in the CLR environment. This appendix discusses the considerations to be kept in mind for using managed code. It briefly discusses the advantages of using managed code and then finally moves on to discuss the steps to create a pure managed extension application and another application that combines managed and unmanaged extensions.
Considerations for Using Managed Code Consider the situation of an online banking application that has been coded using the good old MFC classes. The application would have been thoroughly tested and would be significantly stable in performance. Now consider a situation where the development team wants to further enhance the functionality of this application and while doing so wants to make best use of the features that are provided by the .NET environment. In this situation, you have the following options: ◆ Retain the original code of the application and then add code to make best use of the new features provided by the environment
851-868.qxd 2/24/03 11:23 AM Page 853
MIGRATING FROM VC++ 6.0 TO VC++.NET
Appendix B
◆ Rewrite the entire code of the application in the new development environment While the second option is a time- and resource-consuming activity, the first option provides you with the best of both worlds. You retain your sturdy MFC code and then add new functions that leverage the .NET environment. Managed extensions are C++ extensions that can be used to write .NET applications in Visual C++. As mentioned in the previous section, managed extension applications can leverage the strength of both managed and unmanaged code. In the following sections, I will discuss some advantages of using managed extensions.
Advantages of Using Managed Extensions The advantages of using managed extensions are numerous. In this section, I will discuss some of the key factors: ◆ Managed code is executed in the CLR environment and therefore benefits from using all the features of the CLR. Some important features of CLR include cross-language integration, improved garbage collection, and memory management. ◆ Applications that are developed using managed extensions can interoperate with the other .NET languages. This means that you can develop applications using managed extensions and then use the functionality provided by these applications in another application that can be developed either using Visual C# or Visual Basic.NET. ◆ Exception handling in managed extensions is much more developed. Exception handling can be carried out by using the Try and Catch block of statements. When an application throws an exception, the exception handler for the same is implemented by the runtime. Managed extensions use the System::Exception class for handling exceptions and this class can be used to trace the function that raised the exception. While the use of managed extensions provides a number of advantages, you need to make a judicious decision on when you should create managed extension applications. You should use managed extensions in the following situations: ◆ You want to migrate your existing C++ applications to the .NET framework rapidly. This essentially helps you combine managed and
853
851-868.qxd 2/24/03 11:23 AM Page 854
Part X
APPENDIXES
unmanaged code in the same application and reduces the effort required in developing the application from scratch. ◆ You want to access the .NET Framework classes from within your unmanaged application. ◆ You want to reuse the functionality of an existing C++ application from within any .NET compatible language. This is useful if you have components that have been developed in C++ and you want to reuse this functionality in a Visual C# or Visual Basic.NET application.
Managed Types
AM FL Y
Having discussed the basics of managed extensions, the next section discusses some of the managed types available.
Visual C++ provides two managed types—gc types and value types. The gc types use the CLR runtime heap for execution. As a result, all garbage collection is performed on the runtime heap. On the other hand, value types are allocated on the call stack and the CLR doesn’t act on them. The following code samples illustrate the usage of managed string arrays.
TE
854
char display __gc[ ]; int num1, num2 , num3; display = new char __gc[10]; Console::WriteLine(“Enter first number”); num1=Convert::ToInt32(Console::ReadLine()); Console::WriteLine(“Enter second number”); num2=Convert::ToInt32(Console::ReadLine()); num3=Convert::ToInt32(num1)+Convert::ToInt32(num2); Console::WriteLine(Convert::ToString(num3));
As you can see from the code snippet given above, the __gc keyword is used to declare a managed array. This array is allocated memory on the runtime heap. Some other managed types that are available are listed below. ◆ Managed arrays. Can be created using the __gc keyword. char display __gc[]; display = new char __gc[10];
◆ Assemblies and namespaces. Can be accessed using the #using statement.
Team-Fly®
851-868.qxd 2/24/03 11:23 AM Page 855
MIGRATING FROM VC++ 6.0 TO VC++.NET
Appendix B
◆ Property. Is a data member that is implemented using the pair of get() and set() functions. A property that has only a get function is a readonly property, while a property that has both get() and set() functions is a read-write property. The following section discusses the steps to create a managed application and implement properties.
Creating a Managed Application In this section, I will walk you through the steps to create a managed application. 1. Choose File, New, Projects. The New Project dialog box is displayed. 2. From the Project Types list, select Visual C++ Projects. 3. From the Project Templates list, select Managed C++ Application. Figure B-1 displays the New Project dialog box. 4. Click on OK. 5. In the Solution Explorer, you can view two files, AssemblyInfo.cpp, which contains details about assemblies, and .cpp, which contains the actual code for the application.
FIGURE B-1 The New Project dialog box
855
851-868.qxd 2/24/03 11:23 AM Page 856
856
Part X
APPENDIXES
The following code creates a class called MyString. It stores the string entered by the user and performs other string-related functions. The code has a default and overloaded constructor. #include “stdafx.h” #using #include using namespace System; // This is the entry point for this application __gc class MyString { private: String *str; int length; public: MyString() { str = new String(NULL,0); length= 0; } MyString(String *tempstr) { length = tempstr->get_Length(); str = new String(NULL,0); str= tempstr;
} __property void set_Display() { Console::WriteLine(“String is”); Console::WriteLine(str); Console::WriteLine(“Length is”); Console::WriteLine(length); } __property int get_Length()
851-868.qxd 2/24/03 11:23 AM Page 857
MIGRATING FROM VC++ 6.0 TO VC++.NET
Appendix B
{ return length; } __property int get_Compare(String *tempstr) { if(str->Compare(str, tempstr)==0) return 1; else return 0; } }; int _tmain(void) { // TODO: Please replace the sample code below with your own. MyString *FirstString = new MyString(“Hello”); FirstString->set_Display(); if(FirstString->get_Compare(“Hello”) ==1) Console::WriteLine(“Equal”); return 0; }
The functions in the code and their explanations are provided in Table B-1. Table B-1 Functions in the Code Function Name
Description
MyString()
Is the default constructor
MyString(String * )
Is the overloaded constructor
set_Display
Is the property that is used to display the content of the MyString class
get_Length
Is a property that is used to return the length of the string
get_Compare
Is a property that compares the content of the string with the string that is passed as a parameter
857
851-868.qxd 2/24/03 11:23 AM Page 858
858
Part X
APPENDIXES
Adding Managed Code to an Application In cases where you want to add managed code to an existing application, you need to change the project settings so that the compiler can identify that your code needs to be compiled for the managed environment. After changing the project settings, you can write managed code in your application so that it can be executed by the CLR. When you change the project settings, you make the /clr switch available for compiling your code. The /clr compiler option compiles your code into an application that requires the CLR for its execution. In addition to enabling the /clr switch, you need to disable the switches that are incompatible with the /clr switch.
Changing Project Settings I will now discuss the steps involved in changing the project settings for the application that needs to be compiled for the managed environment. 1. Open the application that needs to be compiled for the managed environment. In this case I am using an MFC application called MyApp. 2. Open Solution Explorer by selecting the View @--> Solution Explorer menu option. 3. Right-click on the name of the project in Solution Explorer and select Properties on the shortcut menu. The Application Property Pages dialog box appears (where Application is the name of your project). 4. Select the C/C++ option from the Configuration Properties panel in the dialog box. The suboptions of the C/C++ option are now visible. 5. Select the General suboption from C/C++. The My app Property Pages dialog box as it appears after selecting the required options is shown in Figure B-2. 6. Select the Assembly Support (/clr) option for the Compiled As Managed property of the application.
851-868.qxd 2/24/03 11:23 AM Page 859
MIGRATING FROM VC++ 6.0 TO VC++.NET
Appendix B
FIGURE B-2 The My app Property Pages dialog box
The /clr switch is now made available for your application. Now, when you run your application, it is run by the CLR. The compilation switches, / ZI, /RTC1, and /Gm, are not compatible with the /clr switch. The following list describes these switches in detail. ◆ The /ZI switch builds a single program database to store debug information of your program. This avoids redundant information and saves disk space. ◆ The /RTC1 switch checks your code for runtime errors, such as loss of data when it is assigned to a variable of lower capacity. ◆ The /Gm switch enables minimal rebuild, in which only the source code that is changed after the last compilation is recompiled. All the three preceding switches need to be disabled in your managed application. The following steps show you how to disable the three switches: 1. To disable the /ZI switch, select the Disabled option for the Debug Information Format property. The /ZI switch is disabled. 2. To disable the /RTC1 switch, select the Code Generation suboption on the C/C++ option in the My app Property Pages dialog box. 3. Select the Default option for the Basic Runtime Checks property.
859
851-868.qxd 2/24/03 11:23 AM Page 860
860
Part X
APPENDIXES
4. To disable the /Gm option, select the No option for the Enable Minimal Rebuild property of your application. The My app Property Pages dialog box as it appears after changing the required options is shown in Figure B-3. 5. Click on Apply and then click on OK to save your changes and close the My app Property Pages dialog box. The application can now be executed in the managed environment.
Adding the Code The application that you are adding code to is an application that draws geometric figures. It provides the following functionality: ◆ Drawing a line ◆ Drawing a rectangle and rounded rectangle ◆ Drawing an ellipse In the current application, all these graphic objects are drawn in red. The code for the existing application is given in Listing B-1.
FIGURE B-3 The My app Property Pages dialog box after disabling the /RTC1 and /GM
switches
851-868.qxd 2/24/03 11:23 AM Page 861
MIGRATING FROM VC++ 6.0 TO VC++.NET
Listing B-1 Code for the Existing Application // The Application class header file: MyWindow.h #pragma once #include “afxwin.h” class CMyWindow : public CWinApp { public: BOOL InitInstance(); }; // The Application class cpp file: MyWindow.cpp #include “mywindow.h” #include “MyFrame.h” BOOL CMyWindow::InitInstance() { CMyFrame *MyFrameObject; MyFrameObject = new CMyFrame; m_pMainWnd=MyFrameObject; MyFrameObject->ShowWindow(SW_SHOWMAXIMIZED); return TRUE; } CMyWindow ApplicationObject; // The Dialog class header file: Mydialog.h #pragma once #include “afxwin.h” #include “resource.h” class CMyDialog : public CDialog { public: CMyDialog():CDialog(IDD_DIALOG1) { } void OnOK(); DECLARE_MESSAGE_MAP() };
Appendix B
861
851-868.qxd 2/24/03 11:23 AM Page 862
862
Part X
APPENDIXES
// The Dialog class cpp file: Mydialog.cpp #include “mydialog.h” BEGIN_MESSAGE_MAP(CMyDialog,CDialog) ON_COMMAND(IDOK,OnOK) END_MESSAGE_MAP() void CMyDialog::OnOK() { EndDialog(TRUE); } // The Frame class header file: MyFrame.h #pragma once #include “afxwin.h” #include “resource.h” class CMyFrame : public CFrameWnd { protected: CMenu *m_MainMenu; CBrush *newBrush, *oldBrush; bool flag; int shape; //1=line, 2=rect, 3=round rectangle //4 ellipse POINT p1, p2; public: CMyFrame(void); ~CMyFrame(void); void ExitApplication(); void DrawLine(); void DrawRect(); void DrawRoundRect(); void DrawEllipse(); void OnLButtonDown(UINT flags,CPoint Point1); void OnLButtonUp(UINT flags,CPoint Point2); DECLARE_MESSAGE_MAP() }; // The Frame class cpp file: MyFrame.cpp #include “myframe.h” #include “MyDialog.h” CMyFrame::CMyFrame(void) {
851-868.qxd 2/24/03 11:23 AM Page 863
MIGRATING FROM VC++ 6.0 TO VC++.NET
Create(NULL,”Sample Window”); m_MainMenu= new CMenu; m_MainMenu->LoadMenu(MAKEINTRESOURCE(IDR_MENU1)); SetMenu(m_MainMenu); } CMyFrame::~CMyFrame(void) { } BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd) ON_COMMAND(ID_FILE_EXIT,ExitApplication) ON_COMMAND(ID_INSERT_LINE,DrawLine) ON_COMMAND(ID_INSERT_RECTANGLE,DrawRect) ON_COMMAND(ID_INSERT_ROUND_RECTANGLE,DrawRoundRect) ON_COMMAND(ID_INSERT_ELLIPSE,DrawEllipse) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() END_MESSAGE_MAP() void CMyFrame::OnLButtonDown(UINT flags,CPoint Point1) { if (flag==true) p1=Point1; } void CMyFrame::OnLButtonUp(UINT flags,CPoint Point2) { if (flag==true) { CClientDC MyDC(this); newBrush = new CBrush; oldBrush = new CBrush; newBrush->CreateSolidBrush(RGB(255,0,0)); oldBrush=MyDC.SelectObject(newBrush); switch(shape) { case 1: MyDC.MoveTo(p1); MyDC.LineTo(Point2); flag=false;
Appendix B
863
851-868.qxd 2/24/03 11:23 AM Page 864
Part X
APPENDIXES
break; case 2:
CurDC.Rectangle(p1.x,p1.y,Point2.x,Point2.y); flag=false; break; case 3:
CurDC.RoundRect(p1.x,p1.y,Point2.x,Point2.y,17,17);
AM FL Y
flag=false; break;
case 4:
CurDC.Ellipse(p1.x,p1.y,Point2.x,Point2.y);
flag=false; break;
default:
TE
864
CurDC.MoveTo(p1); CurDC.LineTo(Point2); flag=false;
} CurDC.SelectObject(oldBrush); } } void CMyFrame::ExitApplication() { exit(0); } void CMyFrame::DrawLine() { flag=true; shape=1; } void CMyFrame::DrawRect() { flag=true; shape=2; }
Team-Fly®
851-868.qxd 2/24/03 11:23 AM Page 865
MIGRATING FROM VC++ 6.0 TO VC++.NET
Appendix B
void CMyFrame::DrawRoundRect() { flag=true; shape=3; } void CMyFrame::DrawEllipse() { flag=true; shape=4; }
In the code that is being added to the application, these geometric figures will be drawn using a random color, so that the graphic is drawn in a new color each time. I will now discuss the steps to do the same. 1. Open the MyFrame.cpp file and add the following lines of code: using namespace System; __gc class Mydraw { public: int GetNumber(int a) { System::Random *rnd; rnd= new System::Random(); return rnd->Next(a); } };
In the preceding code snippet, the __gc keyword in the class declaration indicates that garbage collection will be performed for the class and, as a result, memory management is performed automatically. In the code, the using namespace System directive imports the System namespace into your application. You can use the methods and classes of this namespace after specifying this directive. In the GetNumber() function, you create an instance of the Random class of the System namespace. The Next() function generates a random number that is less than the parameter supplied to the function. The function returns the randomly generated number.
865
851-868.qxd 2/24/03 11:23 AM Page 866
866
Part X
APPENDIXES
2. After specifying the preceding code, you will need to change the code of the OnLButtonUp() function. The code for the OnLButtonUp() function follows: void CMyFrame::OnLButtonUp(UINT flags,CPoint Point2) { if (flag==true) { CClientDC CurDC(this); newBrush = new CBrush; int num1, num2, num3; Mydraw* drawing = new Mydraw; num1 =drawing->GetNumber(256); num2 =drawing->GetNumber(256); num3 =drawing->GetNumber(256); newBrush = new CBrush; oldBrush = new CBrush; newBrush>CreateSolidBrush(RGB(num1,num2,num3)); oldBrush = new CBrush; newBrush->CreateSolidBrush(RGB(255,0,0)); oldBrush=CurDC.SelectObject(newBrush); switch(shape) { case 1: CurDC.MoveTo(p1); CurDC.LineTo(Point2); flag=false; break; case 2:
CurDC.Rectangle(p1.x,p1.y,Point2.x,Point2.y); flag=false; break; case 3:
CurDC.RoundRect(p1.x,p1.y,Point2.x,Point2.y,17,17); flag=false;
851-868.qxd 2/24/03 11:23 AM Page 867
Appendix B
MIGRATING FROM VC++ 6.0 TO VC++.NET
break; case 4:
CurDC.Ellipse(p1.x,p1.y,Point2.x,Point2.y); flag=false; break; default: CurDC.MoveTo(p1); CurDC.LineTo(Point2); flag=false; } CurDC.SelectObject(oldBrush); } }
3. Compile and build the application. To summarize, managed extensions are C++ extensions that can be used to write .NET applications in Visual C++. Managed extension applications can leverage the strengths of both managed and unmanaged code. Some of the key advantages of using managed extensions are: ◆ Managed code is executed in the CLR environment and, therefore, benefits from using all the features of the CLR. Some important features of CLR include cross-language integration, improved garbage collection, and memory management. ◆ Applications that are developed using managed extensions can interoperate with the other .NET languages. This means that you can develop applications by using managed extensions and then use the functionality provided by these applications in another application that can be developed either using Visual C# or Visual Basic.NET. ◆ Exception handling in managed extensions is much more developed. Exception handling can be carried out by using the Try and Catch block of statements. When an application throws an exception, the exception handler for the same is implemented by the runtime. Managed extensions use the System::Exception class for handling exceptions and this class can be used to trace the function that raised the exception.
867
851-868.qxd 2/24/03 11:23 AM Page 868
This page intentionally left blank
869-882.qxd 2/24/03 11:23 AM Page 869
Appendix C ATL for VC Programmers
869-882.qxd 2/24/03 11:23 AM Page 870
he Internet boom has been pretty dramatic. It all started with Web sites that displayed static content on Web pages by using the plain vanilla HTML tags. However, the static nature of these Web pages couldn’t address the needs of users and they also couldn’t hold the customers’ attention for long. As a result, there was a need for interactivity in these Web pages.
T
The developers now have available a pool of technologies that can be used to develop Web applications. The choice of which technology best suits their requirements is largely dependent on the platform they are developing for and the ease of use of the technology. Another important factor is the performance that is expected from the Web application. Technologies that are based on languages that are compiled, such as CGI applications developed using C and C++, give a better performance as compared to those based on scripting languages, such as ASP and CGI scripts. Conversely, Web sites that use scripting-based technologies are more easily maintained. Compiled technologies, such as CGI, have been around for a long time and are used widely on servers based on operating systems, such as Unix. However, on Microsoft Windows platforms, process overheads associated with each CGI call make CGI applications non-scalable. Additionally, in a CGI application, requests from the client are passed to the CGI application as a set of environment variables. The CGI application uses these variables as input and generates output in the HTML format. As a result, a user can interact with an application by simply using HTML. Microsoft developed ISAPI, which is an API that is specifically designed for the Microsoft IIS and provides interactivity to applications. However, developing ISAPI applications by using Visual C++ is difficult for building anything but very simple sites. Microsoft did try to make the creation of ISAPI applications easier by adding an MFC-based wizard for ISAPI extensions, but didn’t include built-in support for database access and standard Web features, such as session management and cookies, were missing.
869-882.qxd 2/24/03 11:23 AM Page 871
ATL FOR VC PROGRAMMERS
Appendix C
To overcome the drawbacks of ISAPI applications, Microsoft introduced Active Template Library (ATL) Server. In this appendix, you will learn about ATL Server and how it addresses the issues discussed here.
NOTE You can create DLLs called ISAPI Extension DLLs that contain the functionality desired of a Web application. ISAPI extensions are of two types: ISAPI filters and ISAPI applications. ISAPI filters process all incoming client requests but are not explicitly invoked by the client. ISAPI applications are used to provide the same functionality as CGI applications. You invoke an ISAPI application just as you invoke a CGI application using a URL. Even though the architectures of ISAPI and CGI vary significantly, ISAPI applications provide dramatic performance improvements as compared to CGI.
What Is ATL Server? An ATL Server is a library of C++ classes that simplifies the development of Web applications and Web services through compiled code. The ATL Server is based on the ATL library that was originally designed to create lightweight COM components. The main components in the ATL Server architecture are the Web server (IIS), an ISAPI extension DLL, one or more Web application DLLs, and Server Response Files (SRFs). I will now discuss the role of each of these components in processing a client request. ◆ The ISAPI Extension DLL. This DLL contains the default functionality for handling client requests, which is passed on by the Web server and will not be changed. ◆ Web application DLL. This contains methods that will be called from the SRF, such as methods for generating dynamic content and connecting to a database. ◆ SRF. SRF are text files containing static HTML code for the static portions of a Web page and special tags that invokes request handler methods from within the Web application DLLs. The following code is a sample SRF:
871
869-882.qxd 2/24/03 11:23 AM Page 872
872
Part X
APPENDIXES
{{handler application.dll/Default}} This is a test {{Hello}}
As you can see from the preceding code, an SRF is an HTML file with special tags, which are to be processed by the Web application DLL. Now, I will discuss the elements of the preceding code. Consider the second line of the code. {{handler application.dll/Default}}
This line specifies the name of the Web application DLL, application.dll, with which the ISAPI DLL interacts to process the requests. The term following the name of the DLL, /Default, indicates the class containing the request handling methods that are invoked by the SRF to handle client requests. Here, Default indicates that the class marked with the default attribute in the application DLL contains the request handling methods. Next, consider the following line of code: This is a test: {{Hello}}
The {{Hello}} tag is a placeholder, which specifies that a request handler method is to be invoked at this point. At run time, this placeholder is substituted by the output of the request handler method. SRF also supports some of the basic programming constructs, such as ments and loops. {{if
condition}}
{{else}} {{endif}} {{while}} {{endwhile}}
if
state-
869-882.qxd 2/24/03 11:23 AM Page 873
ATL FOR VC PROGRAMMERS
Appendix C
I will now discuss the request handler that is defined within the Web application DLL.
Request Handlers A Web application DLL can have any number of classes, and each of these classes can have any number of request handler methods, but only one of them can be a default class. A class is declared as a default class by using the Default attribute just before the class declaration, as indicated in the following code: [ request_handler(“Default”) ] class CATLSample1Handler { }
All ATL Server request handler classes have to be derived from the class CRequestHandlerT. This class contains methods to access the HTTP request and response streams and methods for initialization and validation. A request stream contains the data sent to the Web server by the client using either the POST() or the GET() methods. The Web server uses the response stream to send data back to the client. The [request_handler(“Default”)] attribute generates an entry in the ATL Server map associating this class as the default handler. An ATL Server map is used to relate the replacement tags in SRFs to its corresponding request handler methods. All requests without a named handler are directed to the default class. After you enter the placeholders in the SRF files, you will have to create an ATL Server map in the DLL to map a tag with its request handler method. The mapping can be done using MFC-style macros or it can be done using attributes, which the ATL Server wizard also uses by default. The code for creating an ATL Server map using macros instead of attributes is as follows: BEGIN_REPLACEMENT_METHOD_MAP(CATLSample1Handler) REPLACEMENT_METHOD_ENTRY(“Hello”,OnHello) END_REPLACEMENT_METHOD_MAP()
The following code illustrates the use of attributes to create an ATL Server map: [ tag_name(name=”Hello”) ] HTTP_CODE OnHello(void)
873
869-882.qxd 2/24/03 11:23 AM Page 874
Part X
APPENDIXES
{ m_HttpResponse GetVariable (“LoginName”, &varObj);
One significant advantage of ATL Server is the way in which it handles threading. IIS maintains an internal thread pool, which is used to service requests. When there are more requests than the available threads, IIS queues up the request. If the load is too heavy, it may even reject requests. However, when you use ATL Server, any request for an SRF is passed on to the ISAPI extension, which maintains its own thread pool, therefore, freeing IIS. The CISAPIExtension class has a function GetNumPoolThreads() that can be overridden to change the number of threads in the extension’s thread pool. This function returns an integer indicating the pool size. The Server Wizard can also add support for increasing performance of a site by using caching of pages, data source, or binary data. You have classes, which simplify sending mails through the application. You can add performance counters that allow monitoring of the Web application using the Windows System Monitor.
Creating an ATL Server Application Before I discuss the steps involved in creating an ATL Server application, I will examine the sequence of steps that are followed when a client application interacts with an ATL Server application. The following list describes the interactions that take place between a client and an ATL Server application: ◆ The client requests a resource. This request contains the name of the file that needs to be displayed. ◆ This request is received and processed by the Web server. The Web server determines the extension of the file that has been requested. If the
869-882.qxd 2/24/03 11:23 AM Page 877
ATL FOR VC PROGRAMMERS
Appendix C
file extension is .srf, the Web server passes the request to the ISAPI extension that has been designated for handling client requests. ◆ The ISAPI extension interacts with the application DLL that has been specified in the .srf file to retrieve the required data and send it to the client. When you create a project by using the ATL Server Project template, Visual Studio.NET adds two applications to your project, the Web application and the ISAPI extension, which redirects requests to your Web application. In the following example, I will use the ATL Server Project template to create a new ATL Server project. To create a new project, perform the following steps: 1. Select the File, New, Project menu option. The New Project dialog box appears. 2. In the New Project dialog box, select the Visual C++ Projects category from the list of project types. The templates in the Visual C++ Projects category appear in the Templates list. 3. Select the ATL Server Project option from the list of templates. 4. Specify the name of the project as MyATLServer1 in the Name text box. The completed New Project dialog box is shown. 5. Click on OK to create the new project. When you click on OK, the ATL Server wizard launches. The ATL Server Project Wizard comprises five screens. By default, the Overview screen of the wizard is open. 6. Click on Finish to retain the default options and create your application. In this project, you will retain the default settings for the project. However, I will briefly examine the purpose of the other screens of the wizard. ◆ Project Settings. The Project Settings page allows you to create a Web application DLL and/or an ISAPI extension DLL. The Web application DLL contain the request handlers for the SRF files to be serviced. The virtual root is the folder under inetpub/wwwroot (the default Web site folder of the local IIS installation) where the DLL files and the SRF
877
869-882.qxd 2/24/03 11:23 AM Page 878
878
Part X
APPENDIXES
files will be deployed after each build. Deploying involves copying the respective files and registering the DLLs. ◆ Server Options. This page shows all services that can be provided by the ISAPI extension DLL. Based on the service required, you can select the appropriate check box. The wizard automatically generates the code required to implement that service to the ISAPI extension DLL file. The various caching features help to increase the performance of a Web application. The predefined performance counters enable you to evaluate performance of your Web application using the performance monitor. The session state services enable you to store session data in an ODBCcompliant database. ◆ Application Options. Use the Application Options screen to include validation and stencil support in your application. When you check the Validation support option, the wizard adds the ValidateAndExchange() method to the default request handler class. Similarly, when you check the Stencil processing support option, the wizard adds the sample code that illustrates the usage of attributes to handle requests. ◆ Developer Support Options. This page has options to add comment entries indicating the task to be done, add support for attributes, and add support for customized assert and trace handling. If you are not familiar with attributed coding, which is new in Visual C++ .NET, and prefer not to using it, you can clear the Attributed code check box. However, remember that attributed coding is a feature that simplifies C++ coding a lot. The ATL Server Project Wizard creates an ATL Server application for you. After you perform the preceding steps, the ATL Server Project creates a number of files for your project. The project created by the wizard comprises two applications, ATLServer1 and ATLServer1Isapi. I will now discuss some important files of these applications.
The ATLServer1 Application The ATLServer1 project is the ATL Server Web application. This project includes the following files: ◆ ATLServer1.h and ATLServer1.cpp. The ATLServer1.h and ATLServer1.cpp files implement the functionality of the ATL Server
869-882.qxd 2/24/03 11:23 AM Page 879
ATL FOR VC PROGRAMMERS
Appendix C
Web application. These files include a default request handler for your application. As you add code to your application, you can add more request handlers to your application in these files. ◆ ATLServer1.srf. The ATLServer1.srf file is the main server response file for your application. The Web server first invokes this file when a client requests resources from your application. The SRF file contains the HTML code for displaying a Web page and the data tags to retrieve data from the Visual C++ .NET application.
The ATLServer1Isapi Application The ATLServer1Isapi application contains the ISAPI extension for your application. The ISAPI extension is responsible for routing requests from clients to the ATL Server application. The important files generated for the ATLServer1Isapi application are given in the following list: ◆ ATLServer1Isapi.cpp. The ATLServer1Isapi.cpp contains the code that is compiled into the ISAPI extension when you build your project. This file also includes code for exception and trace handling for your ATL Server application. ◆ ATLServer1Isapi.def. The ATLServer1Isapi.def file contains three default functions that are exported to your ISAPI extension: HttpExtensionProc(), GetExtensionVersion(), and TerminateExtension(). The HttpExtensionProc() function provides the entry point for your application, the GetExtensionVersion() function registers the ISAPI extension version information with IIS, and the TerminateExtension() function unloads the ISAPI extension from IIS.
The Complete Code for the Application The following code sample creates a “World Timer” that displays the time in different time zones. The interface design of the application is shown in Figure C-1. The tags in the application are listed in Table C-1.
879
869-882.qxd 2/24/03 11:23 AM Page 880
880
Part X
APPENDIXES
FIGURE C-1 The SRF screen design Table C-1 Tags in the SRF File Tag Name
Description
GMT
Displays the Greenwich Mean Time
PST
Displays the Pacific Standard Time
CST
Displays the Central Time
IST
Displays the Indian Standard Time
The code for the ATLServer1.h file is given in Listing C-1. Listing C-1 Code for the ATLServer1.h File // ATLServer1.h : Defines the ATL Server request handler class #pragma once [ request_handler(“Default”) ] class CATLServer1Handler { private: // Put private members here protected:
869-882.qxd 2/24/03 11:23 AM Page 881
ATL FOR VC PROGRAMMERS
Appendix C
// Put protected members here public: // Put public members here HTTP_CODE ValidateAndExchange() { // TODO: Put all initialization and validation code here // Set the content-type m_HttpResponse.SetContentType(“text/html”); return HTTP_SUCCESS; } protected: // Here is an example of how to use a replacement tag with the stencil processor CString GetTimeSpan(int hr, int min) { CTimeSpan time = CTimeSpan(0,hr,min,0); CTime mytime = CTime::GetCurrentTime(); mytime=mytime + time; CString displaystring = mytime.Format(“%H:%M”); return displaystring; } [ tag_name(name=”GMT”) ] HTTP_CODE OnGMT(void) { m_HttpResponse