318 75 5MB
English Pages 970 Year 2002
TE AM FL Y
.NET Framework Professional Projects
This page intentionally left blank
Angshuman Chakraborti Uday Kranti Roopendra Jeet Sandhu WITH
.NET Framework Professional Projects
©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
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.
This page intentionally left blank
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.
This page intentionally left blank
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
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®
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
This page intentionally left blank
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
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
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
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
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
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
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
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®
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
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
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
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
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.
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.
PART
I
.NET Framework Overview
This page intentionally left blank
Chapter 1 .NET Vision and Design Goals
T
AM FL Y
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.
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®
.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
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
.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
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
.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
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,
.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
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-
.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
.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®
.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
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:
.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
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.
.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
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-
.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
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
.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
.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®
.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
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!
Chapter 2 The .NET Family
W
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. 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.
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
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.
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
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
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
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®
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
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.
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
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.
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
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
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
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.
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
.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®
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
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.
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
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.
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
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
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
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.
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
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®
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
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.
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
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
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
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#
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
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.
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
.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®
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
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.
Chapter 3 Introduction to the .NET Framework
I
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. 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.
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
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
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
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.
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
.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®
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
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.
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
Array, Int32, Exception, GC,
System.Collections
Contains types that help manage collections of Objects
Object, Buffer, Byte, Char, String ArrayList, BitArray, 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
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
FileStream, MemoryStream,
ByteStream, File, 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
ChannelServices, IMessage, ImessageSink
Contains types that provide security features
Principal, Util,
RemotingServices,
Permissions, Policy, 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.
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
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.
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
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
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
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
Supported
Not supported
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
Default properties for objects Declaring structures
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®
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
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
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
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.
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
This page intentionally left blank
PART
II Professional Project 1
This page intentionally left blank
Project 1 Database Integration with .NET
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®
Chapter 4 Project Case Study
F
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. 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.
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
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.
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
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.
Chapter 5 Introduction to ADO.NET
A
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. 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-
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
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®
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
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.
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
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
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
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.Sqland System.Data.OleDb.parameter or return values of the Command object, you need to close the DataReader object after using the DataReader object.
Client
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.
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
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
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
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®
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
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
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 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.” DataView
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
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.
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
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
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
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
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
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.
Creating Datasets
AM FL Y
Now that you are familiar with the types of datasets, I will discuss the methods of 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®
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
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
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
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.
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
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-
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
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
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
Project 1
DATABASE INTEGRATION WITH .NET
◆
DataSet object.
◆
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.
◆
DataView object.
◆
DataViewManager object. You use a DataViewManager object to obtain a customized view of the data and relations in a DataSet object.
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.
You can bind a control, such as a TextBox control, to a column in a DataTable 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®
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
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:
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
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()
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
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.
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
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.
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
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®
Chapter 6 Creating a Windows Application in Visual Basic Using ADO.NET to Implement Database Connectivity
I
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. 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.
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
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.
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
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
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
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
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
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®
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
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.
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
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.
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
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
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
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
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
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®
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
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
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 webserver. The string 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. 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
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
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
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”
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
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
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
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®
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
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 ‘
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
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.
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
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
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
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
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
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
txtContract
System.Windows.Forms.TextBox
Display author contract type
Label1-Label10
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
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®
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
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.
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
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
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
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
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
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
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
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®
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
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”
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
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 ‘
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
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)
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
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
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
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®
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
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.”
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
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.
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
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
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
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.
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
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®
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
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” ‘
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
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
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
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
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.
This page intentionally left blank
Chapter 7 Creating a Windows Application in C# Using ADO.NET
I
C# Basics
AM FL Y
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.
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®
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
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-
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
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
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
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.
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
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.
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
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®
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
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.
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
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
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
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
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
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;
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
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®
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
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”));
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
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”,
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
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));
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
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) {
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
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®
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
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.
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
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
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
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 ,” +
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
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
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
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®
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
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();
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
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[] {
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
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 //
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
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
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
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®
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
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; //
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
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)”;
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
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,
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
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”,
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
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®
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
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;
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
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;
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
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.
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
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 (); }
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
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®
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
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 ///
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
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”;
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
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 ();
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
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
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
TE
AM FL Y
This page intentionally left blank
Team-Fly®
Chapter 8 Transactions in .NET— Overview and Implementation
T
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. 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
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
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.
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
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.
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
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.
PART
III Professional Project 2
TE
AM FL Y
This page intentionally left blank
Team-Fly®
Project 2 XML Designer: Creating XML Schemas
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
Chapter 9 Overview of XML
E
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.
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
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
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