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

Rapid C# Windows Development potx

141 346 0

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

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Rapid C# Windows Development
Tác giả Joseph Chancellor
Trường học Lulu.com
Chuyên ngành Computer Science / Software Development
Thể loại Sách hướng dẫn
Năm xuất bản 2006
Định dạng
Số trang 141
Dung lượng 3,42 MB

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

Nội dung

To do this, you simply click the option to add a data source to your project, point it to your database, and then add the tables, views, and stored procedures that you want to use.. Alth

Trang 3

Rapid C# Windows

DEVELOPMENT

Visual Studio 2005, SQL Server 2005,

& LLBLGen Pro

Quickly Build Robust, Database-Driven Applications

Joseph Chancellor

© Joseph Chancellor 2006

Trang 4

All rights reserved No part of this book may be reproduced, stored in a database of any kind, or

transmitted in any way, form, or means without consent of the author, except for brief quotations for reviews or articles.

The information in this book is provided without any express or implied warranty The author, publisher, and any distributor are not responsible for any damages or loss arising directly or indirectly from the use of this book.

Cover and Book Design: Joseph Chancellor

Visual Studio NET 2005, SQL Server 2005, ClickOnce, Visual C#, and IntelliSense are trademarks of the Microsoft Corporation.

LLBLGen and LLBLGen Pro are trademarks of Solutions Design.

Trang 5

Table of Contents

1: Introduction 1

Commanding the Army 1

Prerequisites 2

O/R Mappers 4

Strongly-Typed Objects 5

Native Language Filter Construction 7

Strongly-Typed DataSets vs LLBLGen Pro 8

N-Tier Application Design 11

Stored Procedures, Inline, and Dynamic SQL 11

Data Type Conversion 14

Visual Studio Advantages 14

Summary 14

2: The O/R Mapper 17

Preparing the database 17

Our schema AdventureWorks 18

LLBLGen Pro Objects 18

Scanning the Schema 19

Creating Entities 21

Entity Options 22

Adding Views 26

Creating Typed Lists 28

Adding Stored Procedures 30

Self Servicing vs Adapter 31

One Class vs Two Classes 32

Generating the Code 34

3: Solution Setup 37

Creating the solution 37

Adding references 39

App.config settings 40

LLBLGen Pro Project Overview 41

4: MDI Parent Form 43

MDI Parent 43

5: Simple Forms 49

Calling a Stored Procedure 49

Alternative Approach Using Entities and Relationships 54

Using Typed Views 58

Using Views as Entities 63

Using Typed Lists 64

Summary 64

6: Search Form 65

Order Search Form 65

7: Edit Form 75

Entity Extensions 75

Form Layout 76

Saving Entity Data 81

Creating New Entities 82

Deleting an Entity 83

8: Validation 85

Trang 6

9: Transactions 95

Preparing for the Unexpected 95

Isolation Levels 97

10:Tuning 101

Enhancing Performance 101

SQL Server Profiler 101

LLBLGen Pro Tracing 105

Simple Prefetching 106

Complex Prefetching 107

Multi-threading 108

Code Cleaning 112

11:Deployment 115

Measure Twice, ClickOnce 115

Certificates 116

Strong Name Key 117

ClickOnce Configuration 117

Deployment 121

Installation 121

12:Regenerating Code 123

Inevitable Changes 123

Minor Changes 123

Major Changes 129

13:Appendix 1 133

14:Afterword 135

Trang 7

“Never put off until run time what can be done at compile time.”

David Gries, Compiler Construction for Digital Computers

Commanding the Army

After a long and bloody fight for the territory of ancient China, Liu Bang finally prevailed over his rivals Born from a peasant family, Bang became the first emperor of the Han Dynasty Known as a bold and arrogant man, he discussed his recent military successes with his finest general.

“How many soldiers could a person like myself command?” the Emperor asked confidently.

“Your Majesty could command but 100,000 men” the general stated matter-of-factly.

“Then how about you?” the Emperor asked.

“In my case,” the general replied, “the more, the better.” The Emperor laughed with surprise.

“If that is so, then why are you my subject?” the Emperor asked.

“Your Majesty’s talent lies not in the commanding of troops,” the wise general replied “Your Majesty’s talent lies in the commanding of generals.”

As a software developer, you also command a vast army of systems and architecture with almost limitless possibilities.But unfortunately for the developer, the technologies change almost hourly Unlike the armies of yesterday, the code-warrior of today is likely to find his or her weapons obsolete and battle plans insufficient to face new challenges thatdid not even exist last week

The concept for this book arose from a set of new programming tools and techniques that are not yet widelyadopted in the developer community Much of the reason for this oversight is a lack of understanding, and it is theaim of this book to help correct that deficiency These tools are very similar to the Chinese general in the Han

Dynasty: they are ruthlessly effective at what they do, and with them you can literally save hours, days, and weeks ofdevelopment time and code maintenance Do not make the mistake of becoming a micro-managing Emperor: you donot need to do it all yourself You are not trying to directly command the most troops (or personally write the mostlines of code) You are trying to win the war! And you are about to take a major step forward

Through the exercises in this workbook, you will learn how to use C# with Visual Studio NET 2005, SQL Server

2005, and an invaluable tool called an O/R Mapper (in this case, LLBLGen Pro) to rapidly develop database-drivenapplications You will gain an understanding of the benefits of using these technologies and you will see the completeprocess from start to finish, including scanning the database schema, generating code, adding business logic, andbuilding the user interface We will also cover validation, transactions, performance tuning, multi-threading, anddeployment While there are books, websites, and documentation that cover all of these technologies individually, wewill aim in this book to demonstrate how they can be used together as a rapid and robust solution, giving the

developer a practical walk-through with a multitude of explanations, diagrams, and screenshots

There are countless other methods and languages that a programmer could use to meet his or her database

application needs However, the methods in this book are expedient and have been proven to work Judge for

yourself as we walk through building a Windows application together

1

Trang 8

Who is this book for?

• Beginners who have some experience programming in C# and are familiar with basic programming

terminology

• Intermediate developers who want to learn new techniques to shorten their development time

• Technology strategists who are investigating this approach in order to choose a platform for a project

• Those who want to put together a quick-and-dirty proof of concept for a database-driven application

• Those who have some familiarity with SQL programming (You do not need to be an expert, but you do need

a basic understanding of the SQL syntax to use and understand the generated framework.)

• Those wishing to learn cutting edge development skills and techniques

• Small development teams Using these methods, even a single developer can make a powerful database-drivenapplication and deploy it to their organization in a short amount of time No large budget or department ofdevelopers required

Who isn’t this book for?

• Non-Windows developers

• Developers who are completely unfamiliar with object-oriented programming We are not going to explain allthe details of OOP and you may not understand the concepts or code if object-oriented programming iscompletely new to you

• Developers with no SQL programming experience While LLBLGen Pro will help you compensate for

weakness in SQL, you may have a difficult time understanding and using the framework to write queries ifyou have no understanding of SQL syntax Fundamentally, LLBLGen Pro is a wrapper (and more) for SQL,and knowing the basics will ensure that you can take full advantage of the tools

• Those who are so familiar with SQL that they think in stored procedures and refuse to learn new techniques You will want to avoid the temptation to just write a stored procedure instead of figuring out a way to use the

generated framework Like anything else, learning these new techniques takes time Be patient, and you willachieve the results you want

How to read this book

This book is a practical walk-through that will build a sample application—step-by-step—with directions,

screenshots, and code samples The book is intended to provide all the information necessary for a beginner to fullylearn and grasp the tools In order to gain maximum benefit, be sure to follow along with the sample application,performing the directions on your machine as explained in the text However, if you are an intermediate user morefamiliar with the underlying concepts, you may elect to simply read the chapters and examine the code samples untilyou understand what is presented Optionally, you can create your own project while reading through the book,using the concepts presented, and making substitutions where necessary to apply it to your database schema andmake it fit your application requirements

Prerequisites

In order to fully utilize this book, you will need:

Visual Studio NET 2005 (highly recommended)

Currently in full release as of November 2005, you can buy this software from Microsoft at

http://msdn.microsoft.com/howtobuy Visual Studio NET 2005 has a variety of versions and prices Look for a

version that includes C# and that allows you to develop class libraries and Windows applications (You can use older

versions of Visual Studio, but you will miss some of the newer, time-saving features Refer to Figure 1.1 for a detailed

2

Trang 9

comparison of the versions of Visual Studio NET 2005 available and the versions which include the features

necessary to take full advantage of this book.)

SQL Server 2005 (or other compatible database required)

In this book we will be building database-driven applications with SQL Server 2005 Microsoft offers a variety of SQLServer products—including a limited version that is available for free—and developer versions that accompanyspecific versions of Visual Studio NET 2005

Please note that we will not be covering the creation of your database or designing your schema We are assumingthat you have already developed your database or already have a database available Instead of SQL Server 2000/2005,you can also use previous versions of SQL Server, Microsoft Access, Firebird, Oracle, or MySQL, and for the mostpart, the process will be the same Note, however, that SQL Server 2005 was used exclusively in the creation of thisbook Therefore, if you use other database applications, your results may vary

LLBLGen Pro (required)1

Version: 1.0.2005.1.

LLBLGen Pro is an O/R mapper This tool will take an existing database schema and generate a data access tier (andmore!) in a matter of seconds LLBLGen Pro is available from http://www.LLBLGen.com for about $270 USD (EUR229) and can be used by your entire development team Although the product is an extra item to purchase, it is aninvaluable tool for developers working with databases (a fully-functional 30 day demonstration version is also

available and will allow you to work through the exercises in this book) Keep in mind that there is a free version ofLLBLGen available, but we will not be using it because it uses stored procedures exclusively and only does a fraction

of what the current version will do The original version was entirely reengineered, rewritten, and released as

1) Please note that the products discussed in this book are recommended on their merit alone; the author is not employed by Solutions Design (the creators of LLBLGen Pro) or any other software company, and does not receive any kind of commission or compensation from any of these companies.

Trang 10

LLBLGen Pro You will not be able to follow any of the code samples in this book without the retail version of

LLBLGen Pro

You may be asking yourself, “Aren’t those programs expensive? Why not do it by hand?” Our answer is “Theseprograms save time!” We prioritize speed (but not at the expense of reliability or maintainability) and, therefore,recommend to you that you consider how much time and energy these programs can save you and not only the prices

of the products Looking at the projects developed in this book will serve as a good example (Figure 1.2) While youcould write the same Windows application by hand without Visual Studio, the automation that Visual Studio affordscan be tremendous In our example application alone, about 68% of the code in the Windows application project isgenerated automatically Most of this code is written as elements in the GUI are configured visually; only 32% of thecode was completely written by hand And the differences are even more pronounced using LLBLGen Pro in theapplication’s class library, which contains the business logic and data access layer (these terms are discussed later) Inthis project, over 98% of the code is automatically generated What the developer adds by hand amounts to a mere1,139 lines of code—less than 2% (Keep in mind that this application is in the beginning stages of development, andthat for this reason you will be adding much more custom code.) Another benefit of the code written by Visual Studioand LLBLGen Pro is that it is well commented, well spaced, and easy to read, adding to the line count of generatedcode The main point here, however, is that with these tools you can take a great leap forward on Windows projectsand projects that use databases Automating repetitive code is a major part of rapid development, and it is worthpaying for

Now, let’s take a look at the other concepts and principles that make this method of development a desirablechoice

O/R Mappers

An O/R Mapper creates classes defining objects that correspond to the structure of your database Every row becomes

an entity and every table becomes an entity collection The fields of the database table become public properties of theentity object The framework also builds in constructors and other useful methods to find entity objects, set theirproperties, and save them back to the database with just a few lines of code

4

Figure 1.2 Lines of code generated/automated versus hand-coded in each project in this book

Figure 1.3 Two related database tables

Trang 11

If you are unfamiliar with O/R Mappers, take a look at Figure 1.3 Here are two tables from a database The tables are

named Individual and AddressBook and you will notice a relationship between the two.

After running an O/R Mapper on this schema, you will get a class library that you can immediately begin

referencing in your projects To use a row from this database, you could write the following code in your project(Example 1.4)

Example 1.4 O/R generated code example

Let’s walk through this code step-by-step The code in Line 2 automatically retrieves the Individual record with an

IndividualID of 23 and loads it into a custom object called an IndividualEntity (this name comes from the original

table) As you can see in Line 3, all of the fields of the original table are properties that can be accessed and changed2

In Line 4, a related record in the AddressBook table was accessed and a property changed And in Line 5, you see how easy it is to save those changes back to the database Notice that all of these actions can be performed without writing

any other extra code by hand, anywhere else The generated code from the O/R Mapper handles all of the steps that you

would normally have to code yourself, saving you from having to:

• Find the database server

• Log in and open a connection to the database server

• Select the particular database containing the information you want

• Find the correct table

• Find the correct row

• Read all the values for that row

• Convert every type of value from its SQL data type into the NET data type while checking and handling thepossibility of a null value

• Present those values in a strongly-typed format, so the consumer knows exactly what kind of object to expect(string, integer, array, etc.) and there are no surprises at run-time

• Create a container to temporarily hold the values while they are being modified

• Retrieve data from another row in a related table

• Manage which values have changed and make appropriate INSERT’s, UPDATE’s, and DELETE’s in the

appropriate tables in the database to reflect those changes

• Close the connection

Whew! That’s a lot of time saved! And that’s just the beginning

For those who are not familiar with all of the aspects of programming, let’s elaborate on what it means to bestrongly-typed and why strongly-typed objects are so helpful to developers

Strongly-Typed Objects

A major feature of using an O/R Mapper to auto-generate your code involves the use of strongly-typed objects Instead

of exposing simple and generic properties and methods, your generated code should expose specific objects you willactually be using

To understand the advantages of working in this manner, consider this analogy When Bob goes home every dayfrom work, he puts his keys on the table, drops his briefcase on the floor, and heads straight to the kitchen to makehimself dinner Every day, Bob does the same thing: he grabs a frozen dinner from the freezer and pops it in the

2) More specifically, all columns in the table can be read and columns that are non-key, non-calculated fields can be changed These concepts are explained later.

5

Trang 12

microwave Bob has performed these actions so often that he does not really think about doing them each day He justopens the freezer, grabs something, and sticks it in the microwave We could express this particular freezer-to-

microwave exchange in C# as the following:

whether he will find stuffed animals in the fridge, pop-tarts in the DVD player, or razor-sharp toys peppered along the

staircase Bob would be wise to check exactly what it is he is pulling out of the freezer before he sticks it in the

microwave Now here is the same code improved by using a more specific object

We have improved this code by using a FrozenDinner object Now, if we try to grab something from Bob’s freezer that

is not a FrozenDinner, we will get an error when we try to cast it We could improve this even further by checking the type of the object before we cast it and accounting for the possibility of a non-FrozenDinner object If we used the as

keyword instead of casting the object, we would eliminate the chance of a casting exception, but then we would need

to check for a null FrozenDinner object before trying to cook it

In the NET world, this kind of situation is very common when you access data from external sources One of the

more common objects you will use is a DataTable In NET, DataTable objects are wonderful objects and extremely flexible But when you read data from a database into a DataTable and you need to get specific with the contents of a particular field on a particular row, the NET framework only gives you an object of type … well … object A plain

object is about as generic as you can get, and the NET framework does this intentionally to give you maximum

flexibility But if you assume that that object is a string, and will always be a string, you are entering the world of

assumptions—and code that is built on assumptions is brittle and unpredictable If you accidentally change the name

of a column in your database or reverse the order of columns in a set of records, you are asking for trouble Minorchanges can doom your code, and the worst part is that you will not know things have gone wrong until your code isrunning and the code fails miserably simply because what you always assumed would be a string happened to be aninteger or a boolean

Now let’s return to Bob’s frozen dinner for a moment We would eliminate a lot of guessing and unnecessarily

complex code if the method that gave us the frozen dinner simply returned an object of type FrozenDinner and not an object of type object That would save us the trouble of casting it and accounting for all the possibilities of a non-

FrozenDinner object Consider this final version of C# code:

In the real world, our database solution might entail extending a DataTable and specifically defining the type of every

column It might also entail creating a custom class and writing methods that read the data from the database table

and add it to the properties of the custom class Repeating this process by hand, for every table, stored procedure, and

6

Trang 13

view in your database, while a wonderfully effective programming practice, would take you the rest of your natural life.

Just consider how long it would take to manually write a new method for every kind of object Bob might possiblywant to take from his freezer Unfortunately, these painfully slow methods of development are very common Butthere are several ways to automate this process, which we will discuss in a moment

The other general principle related to strongly-typing worth mentioning is that compile-time errors are always

preferable to run-time errors And of course, having no errors is the most desirable! Until computers begin to write

their own code without human input there will always be errors of

one kind or another But not all errors are created equal

Compile-time errors, which arise during compilation, are easier to fix

because they happen 100% of the time If you have one of these,

you cannot compile your application no matter how many times

you try You must fix the problem before continuing On the other

hand, a run-time error which arises as the application is running

will compile 100% of the time, but may only occasionally throw an error while executing These kinds of errors are

harder to test and harder to catch because they are inconsistent and only occur when a particular function is called

and when specific conditions are met.

Now, consider the three different frozen dinner code examples mentioned earlier In the first example, we willnever get any kind of error when compiling or executing (which is good), but unfortunately for Bob’s household, wecould end up with strange items in the microwave (not good) In the second example we have prevented putting non-

FrozenDinner objects in the microwave We will have no compilation errors (good), but have a real chance of run-time

errors if the object in the freezer is not a frozen dinner (not good) In the last example we get the possibility of

compile-time errors if we code incorrectly (very easy to fix), no run-time errors (very good!), and still no strangeobjects in the microwave (what we hoped for) Although there are many ways to solve this problem, the third method

is the most reliable, error-free solution

Native Language Filter Construction

A new feature in the latest version of LLBLGen Pro is native language filter construction In past versions of LLBLGenPro, creating a SQL query programmatically required excessive verbosity, as you can see in Example 1.8 Each part of

a query in this example is represented by objects which must be instantiated and combined in ways that are notnecessarily intuitive nor easy to read While these early versions were effective, they demanded that the developer taketime to be completely comfortable with the syntax

PredicateExpression MyPredicate = new PredicateExpression();

MyPredicate.Add(AW.Data.FactoryClasses.PredicateFactory.CompareValue(

EmployeeFieldIndex.HireDate,ComparisonOperator.GreaterEqual,

HireDateAfter));

MyPredicate.Add(AW.Data.FactoryClasses.PredicateFactory.CompareValue(

EmployeeFieldIndex.SalariedFlag,ComparisonOperator.Equal,

true));

Example 1.8 Old way of creating predicates

In the newest version of LLBLGen Pro, however, queries can be constructed in an intuitive manner more consistentwith normal C# syntax Consider Example 1.9 , where the same predicate has been written in native language Theend result is more readable code and less time spent learning the syntax

1

2

3

IPredicate MyPredicate =

(EmployeeFields.HireDate >= HireDateAfter) &

(EmployeeFields.SalariedFlag == true);

Example 1.9 Creating predicates with natural language construction

Compile-time errors are always preferable to

run-time errors

7

Trang 14

Native language filter construction in C# is a helpful and time-saving new feature in LLBLGen Pro, and throughoutthis book, we will use this technique in code examples.

Strongly-Typed DataSets vs LLBLGen Pro

Let's take a brief look at the code generating tools integrated into Visual Studio and how they compare to LLBLGen

Pro Visual Studio allows you to auto-generate a strongly-typed DataSet that mirrors your database’s schema As you

might expect, this approach takes existing data objects and extends them, specifying the columns and data typesexplicitly To do this, you simply click the option to add a data source to your project, point it to your database, and

then add the tables, views, and stored procedures that you want to use Visual Studio will generate an XSD file (Figure

1.10) that will contain descriptions of all the database objects and their properties

In Figure 1.11, you can see the Northwind database schema as viewed through the DataSet Designer in Visual

Studio Visual Studio will even add the relationships between the tables automatically

8

Figure 1.10 A strongly-typed DataSet in a C# Windows project

Figure 1.11 A look at the schema of a strongly typed DataSet

Trang 15

To utilize this DataSet you can simply use a TableAdapter, which is an object that is used to retrieve data from the database in order to fill the DataSet If you open the XSD file in Notepad, you can see the underlying structure of the

DataSet (Figure 1.12) Notice that SQL statements are included in the description of this DataSet Each table

description contains the specific SQL statement necessary to perform a SELECT, INSERT, UPDATE or DELETEaction

Although both the LLBLGen Pro method and Visual Studio's strongly-typed DataSet objects are solutions that

provide a data access layer, they are fundamentally different approaches Let’s take a look at some of the reasons whyLLBLGen Pro is the more usable of the two methods

Strongly-typed DataSet advantages: Using strongly-typed DataSet objects is a good technique that implements a

number of our best practices First, you can quickly and easily reap the rewards of using strongly-typed objects and

have assistance in creating your SQL statements and stored procedures The strongly-typed DataSet also automates the

process of consuming the data in your C# code; thus, both the query-generating and consuming features save time

The custom DataSet can also be referenced across your projects, becoming a handy and reusable data access layer A

key advantage of this method over LLBLGen Pro is that you do not need any other third-party software: this

functionality is built into Visual Studio

Strongly-typed DataSet disadvantages: Users of strongly-typed DataSet objects encounter several setbacks, all of

which LLBLGen Pro helps address:

Query limitation: This disadvantage stems from the fact that SQL statements used by strongly-typed DataSet objects are created when the DataSet is designed, not when it is used With LLBLGen Pro objects, however,

the SQL code is generated as the object is used You can find the SQL statements by looking inside the

DataSet's XSD file, but in looking through the code that LLBLGen Pro produces you will find no SQL

statements anywhere The LLBLGen Pro dynamic query engine for SQL Server creates the statements only

when the data is retrieved from the database Because the SQL statements are all created when the DataSet is

defined, if you need a new query that has not been defined in advance, you will always need to redesign your

DataSet by adding the new query before you can consume it elsewhere in your code With LLBLGen you can

create and consume the query in your C# code by using the LLBLGen Pro framework—all without changingthe underlying data layer You would only need to change your data layer (by regenerating your code) if youmade changes to your schema or you add a new type of database object

• Difficulty propagating schema changes: When you do make changes to your schema, strongly-typed

DataSet objects do not provide a built-in method for propagating schema changes to your DataSet definition

and updating your SQL statements You would need to delete the corresponding DataSet table,re-add it from

the database, and then re-create all of the custom SQL queries that you had defined for that table (since onlyone query is added by default) Fundamentally, there is no built-in way for Visual Studio to refresh your

DataSet schema with changes from your database's schema If you forget to drop and add each table that

changed, or refresh the list of columns that have new names or data types, your code will mysteriously begin

9

Figure 1.12 A peek inside a strongly-typed DataSet definition file

Trang 16

to throw exceptions LLBLGen Pro makes it easy to bring those changes to your code without losing any ofyour customization In Chapter 12, you will see how LLBLGen Pro automatically scans your entire databaseand automatically makes the necessary changes to your project for you.

Limited data layer functionality: In order to traverse many-to-many relationships between tables, DataTable

objects require you to use intermediate tables LLBLGen Pro allows you to traverse relationships between

Entities more easily than you can using DataTable objects You actually can traverse a many-to-many

relationship by skipping over the intermediate table—an action that is not possible with a strongly-typed

DataSet.

No help with business logic layer: A strongly-typed DataSet does not help you with your business logic

layer LLBLGen Pro can optionally create a business logic layer shell that saves you the trouble of creating oneyourself We will use this method in our walk-through

• Requirement of adapters in order to get data: In order to retrieve data for your strongly-typed DataSet, you

must first create a TableAdapter object If you use the self-servicing template when generating LLBLGen Pro code, you do not need any extra object like a NET TableAdapter to retrieve data It is as if your DataRow

objects fill themselves with data automatically-and this means you have to write fewer lines of code

• No support for custom SQL queries: Even with the Visual Studio automated tools, you will still need to getyour hands dirty writing SQL: some queries are too complex to use Query Manager The LLBLGen Proframework allows you to generate complex queries and replace the logic of many stored procedures withoutwriting any SQL yourself

These features make LLBLGen Pro a compelling choice for database access But by now, you may be wondering toyourself, “If O/R Mappers are so great, why isn’t Microsoft using this approach?” In fact, Microsoft is working on

it right now Originally, Microsoft was developing a project they dubbed “ObjectSpaces,” which was a method ofrepresenting relational data as objects This project was eventually assimilated into new projects not yet completed3.One of those projects is named WinFS, which will contain technology that is similar to O/R Mappers Quentin Clark,the project management team leader for WinFS, stated in his blog, “We are in the process of building-out the nextversion of ADO.NET to have new features that provide a data model, object-relational mapping, and flexible queryinfrastructure The new data model is about entities, and the WinFS data model of Item types is built on that

model.”4 WinFS has been under development since 2002 and is currently in Beta 1 The final release date for WinFS is

uncertain, but it will certainly be after the next version of Windows (Vista) is released.

The other main project from Microsoft is named LINQ, which stands for Language INtegrated Queries According

to the Microsoft Developer Network LINQ is “a codename for a set of extensions to the NET Framework that

encompass language-integrated query, set, and transform operations It extends C# and Visual Basic with nativelanguage syntax for queries and provides class libraries to take advantage of these capabilities.”5 LINQ will allow thedeveloper to use queries written in C# statements against many different kinds of objects loaded into memory Thescope of this project is much wider than sorting relational data: LINQ commands can sort data regardless of itssource At the moment, it is impossible for the developer to accomplish this alone Most of the time sorting andfiltering operations are relegated to the database LINQ will allow many of those operations to occur in the C# codewhere the NET code is running instead of in the database where SQL Server is running LINQ will work with

LLBLGen Pro generated code and therefore will be of great benefit to the developer when it is finally released

In addition to LINQ, Microsoft is creating a project specifically aimed at relational data, called DLINQ DLINQ is

an O/R mapper for Microsoft that will generate classes corresponding to your database’s tables and will use lazyloading (or “deferred query execution,” in Microsoft’s terminology) to dynamically generate SQL to retrieve, modifyand delete data The DLINQ project is simply a light-weight, Microsoft-built O/R Mapper At the 2005 MicrosoftProfessional Developers Conference, Microsoft gave a demo of the project to attendees Because the DLINQ project isstill in development, it currently offers far fewer features than LLBLGen Pro and will probably require several moreversions before it has a similar set of features to what LLBLGen Pro has today

The good news is that you do not have to wait for Microsoft to release WinFS, LINQ, or DLINQ in order to takeadvantage of O/R Mapping LLBLGen Pro is already available and has proved to be a mature and stable product

Trang 17

N-Tier Application Design

Programmers who create any kind of large programming project know the importance of keeping code organized Tier application design helps you separate your code into logical layers Generally, you would have a data-accesslayer, a business logic layer, and a user interface layer; some developers use more layers and some use less Hereare the details about what each layer would contain in this three layer design:

N-Data access layer: This section contains all the code necessary to execute SELECT, INSERT, UPDATE and

DELETE statements in the database, access views, run stored procedures, and convert between database data typesand the data types of your programming language

Business logic layer: This section would contain code that implements the rules of your business This is aboveand beyond simple database access For instance, code in this layer might validate the various parts of an order beforethe order is saved into a database or define the process for handling an order once it is saved into the database

User interface layer: This layer contains code that puts data into specific controls in order to display it for yourusers Hopefully, it contains only what is user-interface specific In the NET world, web application controls aredifferent from windows application controls, so this code cannot necessarily be re-used between different kinds ofapplications

The advantages of the three-tier design are the following:

• Using a three tier method, you would be able to change your application to a completely different user

interface without losing the other two layers of your code

• Business rules are saved in a central location If you decide to change the process for validating an order, youonly have to change it in one place

• If you change your database (from SQL Server to Oracle, for example), you would theoretically be able to

change only the data access layer and not the rest of your application Unfortunately, in most of the situationsthis is not a practical reality, as database-specific code has a way of creeping up to the user interface layer.While these methods are acknowledged best practices, most developers find that they do not have the time to designthe application this way; rules are violated frequently out of the need to just get the product out the door However,LLBLGen Pro helps accomplish the ideal design in the following ways:

• LLBLGen Pro will completely auto-generate the data access layer You do not need to do any hand-coding inthis layer

• LLBLGen Pro will optionally generate a business logic layer shell for you to get started with your businesslayer You do not have to understand the intricacies of inheritance and making custom classes to take

advantage of business logic classes; in LLBLGen Pro these classes are intuitively organized, powerful, andinfinitely extendable

• LLBLGen Pro collections and entity objects are bindable, making them extremely easy to add to NET

controls This can reduce the size of your UI layer

• Changing the database application and the data access layer without affecting the business logic and UI layers

is actually possible with LLBLGen Pro If you migrated your database schema and stored procedures to a newdatabase application, refrained from using any database-specific features (there are not that many) and your

schema matched exactly, you could actually re-generate your LLBLGen Pro data access layer and not make

any other changes to your application!

Stored Procedures, Inline, and Dynamic SQL

To help you understand how LLBLGen Pro works, let's take a look at how database information is integrated into a.NET application There are several different methods you can use to access data in your SQL Server database fromyour code These methods are inline SQL, stored procedures, and dynamic SQL

11

Trang 18

Inline SQL: This is the most common method of database access seen in most tutorials, but it is by far the worst

method Inline SQL is illustrated in Example 1.13

SqlConnection conn = new SqlConnection(connection);

SqlDataAdapter adapter = new SqlDataAdapter();

adapter.SelectCommand = new

SqlCommand(“SELECT * FROM Orders WHERE OrderID=” + tbInput.Text, conn);

adapter.Fill(dataset);

return dataset;

Example 1.13 Inline SQL example

From a security standpoint, a user could enter any kind of data into an input field and have it concatenated directlyinto the SQL statement This presents an alarming security risk You do not want users executing arbitrary code inyour database Hackers who are familiar with SQL injection attacks6 can alter the above query to do about anythingthey want it to do

Also, from a maintainability standpoint, if you decide to change the name of the Orders table to Order, you do not

have any way to propagate this change to your data layer While the code will always compile correctly, it will throw

an exception when the query executes and the Orders table is not found

Stored procedures: Most security experts recommend using stored procedures exclusively for database access.From a security perspective, stored procedures are immune to SQL injection attacks, since parameters entered into astored procedure cannot change the query itself

From a maintainability standpoint, you do not have SQL strings inside of your code when you use stored

procedures, but you will still have stored procedure names in your code If you decide to rename a stored procedure,just like in the above example, you will not automatically propagate the stored procedure name change to your code.The code will compile correctly, but will throw an exception when it is executed and the stored procedure is notfound

The stored procedure method is also a management challenge due to the difficulty of maintaining a vast library ofstored procedures The previous version of LLBLGen Pro relied on auto-generated stored procedures to carry out theSELECT, INSERT, UPDATE, and DELETE operations For each table, there were 5 stored procedures generated (oneextra for selecting all the records) In essence the auto-generated stored procedures and custom stored procedurescreate another layer of code that must be maintained Maintaining code in SQL server can be much more difficultthan in Visual Studio for several reasons: the lack of IntelliSense, a difficult debugging environment, cryptic (andunhelpful) error messages, and the inability to organize similar functions into logical objects

Yet another disadvantage of stored procedures is that most C# code that calls a stored procedure returns an

un-typed DataSet or DataTable This again creates the problem of not knowing 100% of the time what kind of object will

be inside each column and row Although the code will compile, when executed it may throw exceptions if differenttypes of data are in different places

From a permissions standpoint, stored procedures do offer tighter security You can allow users access to only thestored procedures, and they would not be able to access the underlying tables to do any other kinds of changes (i.e.,change the structure of the table) Setting permissions with dynamic SQL (discussed in the next section) is a littlemore complex because you need to set SELECT, INSERT, UPDATE, and DELETE permissions individually on thetables themselves

Another commonly cited advantage of stored procedures over other SQL statements is performance The

architecture of SQL Server is believed to speed up stored procedures by precompiling the query when it is created.However, MSDN documentation7 states the following:

SQL Server 2000 and SQL Server version 7.0 incorporate a number of changes to statement processing that extend many of the performance benefits of stored procedures to all SQL statements SQL Server 2000 and SQL Server 7.0 do not save a partially compiled plan for stored procedures when they are created A stored procedure is compiled at execution time, like

6) For more information about SQL injection, see http://msdn.microsoft.com/msdnmag/issues/04/09/SQLInjection/ or query Google for “SQL injection attacks”

7) See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/architec/8_ar_da_0nxv.asp or query Google for “SQL Server” and

“statement processing”.

12

Trang 19

execution plan reuse to all SQL statements.

The newer versions of SQL Server blur the lines between stored procedures and other SQL statements from a

performance standpoint The same query will be cached regardless of whether it is a stored procedure or a SQL

statement SQL statements also have the advantage of varyingwhereas the logic of a stored procedure is fixed While changing thestructure of the query means that a dynamic query will not takeadvantage of the caching feature the first time it is executed (butwill on subsequent executions), the dynamic query has thecapability of altering to fit the exact need The SQL statementtherefore could give the developer an opportunity to solve aproblem more efficiently than an existing stored procedure might.Keep in mind, though, that neither method is better than the other

all of the time; both techniques have strengths and weaknesses The main point here is that stored procedures do not always have a strong performance advantage over SQL statements

The last disadvantage of stored procedures is that complex procedures can get very ugly very quickly The ability

to do a complex search with many different optional parameters, optional joins, and a variety of sorting methodswould be exceptionally difficult with just one stored procedure

Dynamic SQL: The least common and probably least understood method of database access is Dynamic SQL With

this method, a custom component automatically generates the proper SQL statements for you as you use the object.Many developers do not even know this option exists, and understandably so If you do not have time to codeaccording to the best practices, you certainly will not have time to write your own component that generates SQLstatements automatically The good news is that you do not have to The developers of LLBLGen Pro have made thecomponents for you, and their components are smart enough to speak to a number of different databases You canthink of them as universal translators for databases This frees you up to interface with the components in a generic,non-database-specific manner

If you follow the development of Internet applications, the transition to dynamic SQL will seem quite natural Just

as HTML and JavaScript code in many of today’s web applications is not always written by hand, but instead

encapsulated into ASP.NET server controls which generate the correct code automatically, so new objects are

generating SQL to speak to databases, freeing the developer from having to write all this extra code manually

As the queries are generated, instead of concatenating SQL statements together, these queries become

parameterized, just like stored procedures This process also makes these statements immune to SQL injection

attacks Thus, with dynamic SQL, developers can get the security advantages of stored procedures without the hassle

of maintaining another layer of code in your database

In addition, to help with maintaining your code, LLBLGen Pro generates the equivalent of a master index to all theobjects in your database and all of their fields, saving you from having to hard-code strings in your code with tablenames, stored procedure names, and field names These enumerators and other LLBLGen Pro objects allow you to

consume data in a way that will not compile when the schema changes and you have refreshed the data access layer;

therefore LLBLGen Pro helps prevent schema changes from causing unanticipated exceptions in your code when it isexecuted

Complex querying is also much easier with dynamic SQL than stored procedures A dynamic query can grow toinclude joins where necessary or can alternatively use a variety of branching logic, optional parameters, and anypossible sorting option in the same method You have near-infinite flexibility with dynamic SQL, limited only by yourown ingenuity and creativity

For database access, dynamic SQL is powerful, under-used and often misunderstood as a method of talking toyour database By the end of this book, you will be an expert user of this type of access and you will enjoy all of theadvantages of this method over less efficient inline SQL and stored procedures methods

Stored procedures do not

always have a strong

performance advantage

over SQL statements.

13

Trang 20

Data Type Conversion

Another problem that arises when talking to databases involves the conversion of database values into their NET

counterparts In the database world, a column of type integer can contain a whole number (like 5) or be null (if the

schema allows) In previous versions of the NET framework an integer would throw an exception if its value was null(or unassigned) When you read values from a database, you would have to account for the possibility of a null value

in your class library This accounting could take a lot of extra code to handle the type conversions and creates moreopportunities for mistakes In version 2.0 of the NET framework, Microsoft addresses this difficulty with the addition

of nullable types8 These types make it much easier to handle null values in NET than previous versions

LLBLGen Pro has used its own solution to the nullable dilemma from the beginning of the NET framework inorder to shield the developer from having to manage this complexity In LLBLGen Pro, the SQL data is automaticallyconverted to NET objects in the Data Access Layer with default values A null integer would become a NET integerwith a value of 0 For many situations, the minute difference between null and zero is unimportant However, forthose occasions when you actually care about whether the original value was zero or null, you can call a specificfunction that will tell you this value With LLBLGen Pro, if you need to assess nulls, you can handle them, but nullswill not keep you from getting your project done

Visual Studio Advantages

With every version of Visual Studio, Microsoft adds new features that often become essential for developers Here aresome of the best features from previous versions and the 2005 version:

• IntelliSense: Once you use IntelliSense you will never want to go back! If you have never used it, think of it

as automatic spell checking, grammar checking and word completion With IntelliSense, you simply writebetter code, in less time, and with fewer mistakes

• Debugging: Visual Studio has some of the best debugging tools around to help you figure out what is goingwrong with your code and to see what is happening step-by-step

• Design-time binding to your custom objects: You will probably want to use the the built-in binding

support to set up your controls visually With the advantage of a DataGridView you can add columns based

on the properties of the objects the control will contain before you even have to write a line of code

• New! One-click Deployment: Now, you can deploy your application to a file share or FTP site inside VisualStudio When the application is run, if there is a newer version available, your users will be prompted toinstall the update One-click deployment gives windows applications almost as much ease of deployment asweb applications!

Summary

For summary, here are the reasons the combination of LLBLGen Pro, SQL Server 2005, Visual Studio 2005, and theassociated techniques is so powerful:

• N-Tier design: Using N-Tier design is an effective way to break your code into layers that accomplish

different tasks and is easily reusable

• Customizable business layer templates: LLBLGen Pro generates templates for you to customize with youown code, so you do not have to create your own files, classes, or namespaces; you can start customizingimmediately LLBLGen Pro also generates classes to add your own custom validation logic as well

• Reusable core code: If you decide to switch to a web application, you can use the same generated classes andbusiness logic All you need to do is change the UI-specific code This book will show you how to develop sothat the maximum amount of your custom code is reusable

8) For more information about using nullable types in C#, see http://msdn.microsoft.com/vcsharp/2005/overview/language/nullabletypes/

14

Trang 21

• Consistent and bug-free code: If twelve different programmers make your data-access code, they are

probably not going to be 100% consistent with naming conventions and structure, not to mention humansare guaranteed to make mistakes Generated code is 100% consistent and reliable

• Strongly-typed code that allows fewer errors: Almost all the code generated for you is strongly-typed,

which means that errors are discovered when the code is compiled—before it is run

• Lightweight and powerful code: While it is possible to generate strongly-typed DataSet objects in Visual Studio, LLBLGen Pro code is smaller, cleaner, and infinitely more powerful Like DataSet objects, all generated

Entity and EntityCollection objects are bindable And with new features in Visual Studio NET 2005, you do

more binding visually.

• Easier and less error-prone schema changes: Schema changes are a hassle because it takes time to figure outhow the changes will affect existing code and logic, both inside and outside the database With the O/RMapper, changes to the schema are updated into the generated code, and you immediately see where

breaking changes have occurred

• Database independent code: LLBLGen Pro abstracts your database from your application, so you are notlocked into one database application This flexibility means that you could switch to a completely differentdatabase with minimal to no impact on your custom code If you stick to functionality common to all

databases, you will not need to change a thing

• Visual workspace: Much of the work in Visual Studio can be done visually, without having to code by hand.The visual nature of these tools saves you time and frustration, and the results are much more predictable.Visual Studio NET 2005 adds even more visual features, and we will show you how to take advantage of thisnew functionality

• Powerful pre-built controls: With every new version of Visual Studio, the controls get better and better As

you learn how to use Visual Studio 2005’s bindable objects and DataGridView controls, you will be able to

present your data more professionally and efficiently

• Easy deployment: The newest version of Visual Studio has useful deployment options that make a Windowsapplication as easy to deliver to clients as a web application Client machines check for new versions of thesoftware automatically, greatly reducing the burden on the developer

In the next chapter, we will take a look at what an O/R Mapper is and how you use it to generate your data accesslayer and business layer

15

Trang 23

The O/R Mapper

2

The O/R Mapper

“Sharpening the ax will not delay the work of cutting the wood.”

Chinese proverb

Chapter Goals

• Prepare the database

• Get acquainted with LLBLGen Pro object types

• Create a new LLBLGen Pro project and scan your schema

• Add database objects and configure them

• Discuss code generation options

• Generate your data access layer and business logic layer

As mentioned earlier, it is beyond the scope of this book to help you in designing a schema from scratch But there arethings that you can change in your schema to make sure you get the maximum possible benefit from the O/R Mapperand spend the least amount of time writing custom code, which we will cover in the next section

Preparing the database

Here are the tasks you need to perform on your schema before you begin development on your application:

Clean up your database Delete unused stored procedures, views, and tables You do not have to add these items

to your generated framework, but having to scroll through an unnecessarily long list is not a good use of your time.Tidy up your database beforehand for maximum efficiency

Give your tables non-prefixed, singular names based on their real-world counterparts: Do not use names like

“LD5_223” or “TBL_Orders” Name the table with order data Order, not Orders, as you want to be using an

OrderEntity, not an OrdersEntity Your code will be much more readable if your tables are named well.

Put Primary Keys on all your tables: An O/R Mapper cannot find the row if it does not know its uniquelyidentifying information Even if it is just an auto-numbering ID field, go ahead and give your tables primary keys.Remember not to overlook fields that are unique and might serve as a natural primary key, as you want to preventduplicate data wherever possible with good schema design

Define all your relationships in advance: An O/R Mapper can detect the relationships between tables and let you

traverse these relationships quickly and easily, but only if you define the relationships in your database For maximum

effectiveness make sure that all of your table relationships are defined before using the O/R Mapper If your schema isalready set and you cannot change it, you can tell LLBLGen Pro about the relationship even though it does not exist inthe database However, if at all possible, it is highly recommended to define all relationships in your database ahead oftime

Normalize to your heart’s content: Most of the time when you design a schema, you have to balance

normalization and usability If you split everything off in separate tables to keep from repeating data, nobody is going

to want to use your database because they will not be able to find any of the information! You do not want users tohave to pull five tables together just to figure out a customer’s email address! However, when you use an O/R Mapper,

it does not matter whether you have 5 tables or 50, they are all generated into their own objects, and, most

importantly, they are connected together with relationships Instead of having a meaningless integer when you read acolumn that contains a foreign key, you can move across to the row in that table to look up the name without any

17

Trang 24

extra hassle If you tend to be conservative with your schema, consider doing more normalization than you mightordinarily do

Remember that nothing can fix bad database design: Instead of assigning auto-numbering ID fields to everytable, think through the data that the table will contain and use primary keys that will ensure you do not end up withduplicate data A little foresight will save you from having to spend days cleaning up data due to poor schema design

Our schema AdventureWorks

Once you have finalized your schema, you are ready to use LLBLGen Pro to create your data access and business

logic layers For the purposes of this book, we will be using the AdventureWorks example database included with SQL Server 2005 Microsoft finally replaced the Northwind database with an example that is more up-to-date and has much

better schema design! We will only be working with a few of the tables from this database—not the entire database.Figure 2.1 is a diagram of the tables we will be using in our example application

LLBLGen Pro Objects

Before we use LLBLGen Pro, let’s take a look at what this tool will provide us Here are the classes we will be gettingautomatically as we scan our schema and generate our code

Entities: For every table you add to your project, LLBLGen Pro will generate a specific entity class to represent thattable Each instantiated entity corresponds to one row in a specific table in your database For example, in the

AdventureWorks schema, LLBLGen Pro would create an object type called EmployeeEntity One EmployeeEntity object

18

Figure 2.1 AdventureWorks schema

SpecialOfferProduct

PK,FK2,I2 SpecialOfferID PK,FK1,U1,I2 ProductID I1 rowguid

Individual

PK,FK2,I1 CustomerID FK1 ContactID

EmailPromotion

Phone

PasswordHash PasswordSalt

U2 AdditionalContactInfo

I1 rowguid ModifiedDate

Employee

PK,I4 EmployeeID I2 NationalIDNumber FK2 ContactID I1 LoginID FK1,U1 ManagerID Title BirthDate MaritalStatus Gender HireDate SalariedFlag VacationHours SickLeaveHours CurrentFlag I3 rowguid ModifiedDate

SalesOrderDetail

PK,FK1,I2 SalesOrderID PK,I2 SalesOrderDetailID

CarrierTrackingNumber

OrderQty FK2,U1 ProductID FK2 SpecialOfferID UnitPrice UnitPriceDiscount LineTotal I1 rowguid ModifiedDate

MaxQty

I1 rowguid ModifiedDate

PK,I3 SalesOrderID RevisionNumber OrderDate DueDate

ShipDate

Status OnlineOrderFlag I2 SalesOrderNumber

PurchaseOrderNumber AccountNumber

FK7,U1 CustomerID FK3 ContactID

FK8,U2 SalesPersonID FK9 TerritoryID

FK1 BillToAddressID FK2 ShipToAddressID FK4 ShipMethodID

FK5 CreditCardID CreditCardApprovalCode FK6 CurrencyRateID

SubTotal TaxAmt Freight TotalDue

Comment

I1 rowguid ModifiedDate

PK,I3 CustomerID

FK1,U1 TerritoryID

I1 AccountNumber CustomerType I2 rowguid ModifiedDate

Address

PK,I3 AddressID I2 AddressLine 1

I2 AddressLine 2

I2 City FK1,U1,I2 StateProvinceID I2 PostalCode I1 rowguid ModifiedDate EmployeeAddress

PK,FK1,I2 EmployeeID PK,FK2,I2 AddressID I1 rowguid ModifiedDate

PK,FK3,I2 CustomerID PK,FK1,I2 AddressID FK2 AddressTypeID I1 rowguid ModifiedDate

Trang 25

The O/R Mapper

would represent one row in the Employee table We can create a new row, retrieve an existing row, update a row, or delete it by interacting with this EmployeeEntity object Each column in the Employee row is exposed as a property of the EmployeeEntity object LLBLGen Pro refers to these properties as fields

Collections: For every entity class, LLBLGen Pro also creates an entity collection An entity collection contains entity objects, just like a table contains rows From the Employee table in the AdventureWorks database, LLBLGen would create an EmployeeCollection that holds EmployeeEntity objects These collection classes eliminate the need for

DataTable objects and are both strongly-typed and bindable Instead of running a stored procedure and getting a DataTable, you can create criteria using the LLBLGen Pro framework and retrieve a collection of entities that match

your criteria

Entity relationships: Built into each entity are all relationships in the database involving that table These

relationships help you navigate between related tables Using an EmployeeEntity, you can immediately retrieve the related ContactEntity (using the 1:n relationship between the Employee table and the Contact table) or a

AddressCollection (using the m:n relationship through the EmployeeAddress table) You will either get a single entity or

an entity collection depending on the type of relationship This built-in property saves you the trouble of navigating

to that table and filtering out the unnecessary rows yourself

Typed views: Views in the database can be wrapped as strongly-typed DataTable objects This means that

LLBLGen Pro will create a new class that inherits from a NET DataTable that will specifically define the contents of

every column in that view Typed views are read-only A new feature in the latest version of LLBLGen Pro also allowsyou to add a view from the database as an entity as well as a typed view We will discuss the differences between thesetwo methods in later chapters

Typed lists: Typed lists are the only objects created by LLBLGen Pro that do not correspond one-to-one withdatabase objects When you generate your code, you have the option of creating your own strongly-typed lists of

columns from either one table or multiple tables We could, for example, create a list from the Employee and Contact tables, but only use the columns BirthDate, FirstName, and LastName We could add the criteria “Gender = F”, and fill

our typed list with only these rows Typed lists are handy when you need very specific information that does notnecessarily correspond to a single table/entity or you only want to grab a subset of information for a given set oftables Like typed views, typed lists are read-only

Stored procedure caller classes: Stored procedures that you select will be wrapped in a layer of code, makingthem easy to access This can make the migration to LLBLGen Pro much easier, as you can gradually wean yourself offunnecessary stored procedures without having to migrate all at once While the parameters of the stored procedure

are strongly-typed, remember that the result set is still an untyped DataSet Despite this disadvantage, if you only used

LLBLGen Pro to expose your stored procedures in your data access layer with a consistent naming scheme, it wouldstill save you hours of development time

Now that we have a good idea of what items we can have generated with LLBLGen Pro, let’s look at the schemascanning and code generating process

Scanning the Schema

Scanning your database schema is relatively straightforward The designers of LLBLGen Pro helped make this process

a point-and-click affair

„ Simply open LLBLGen Pro and go to File > New Project

„ (Figure 2.2) Fill in the name of the project (“AW.Data”), your name, and a location to store the file We

recommend saving the file in My Documents\Visual Studio 2005\Projects\AW.Data since this location is also where

you will be generating your code

„ Select SQL Server 7/2000/2005 Driver (SqlClient) as the database driver.

„ Enter the name of your SQL Server and click Connect.

„ Select the AdventureWorks Database.

„ Leave the checkboxes under the “Elements to read from the database schemas” heading as they are, with Tables,

View, and Stored Procedures selected.

„ Click Create to start the process of reading your database’s schema.

19

Trang 26

During this process, the application is reading your schema and saving the information into your project file Onceyou have finished this scan, you do not have to be connected to your database in order to complete the code

generation process The only time you will need to connect to the database again is if you make schema changes andneed to regenerate your code Working in this disconnected manner is both convenient and expedient

Once the scanning process has completed, you should see a screen like the one in Figure 2.3 From here we willadd objects from the database and configure them

20

Figure 2.3 LLBLGen Pro main project screen

Figure 2.2 New LLBLGen Pro project options

Trang 27

The O/R Mapper

Creating Entities

The first set of items we need to add to our project are entities We now need to tell LLBLGen Pro exactly which tablesfrom our database we would like to use

„ (Figure 2.4) Right-click on Entities in the left bar, and select Add New Entities Mapped on Tables from Catalogs(s).

The Designer lets you select from a list of all the tables in your database At this step, you will generally want to add

all the tables you think you might ever access Only leave a table out if you have a specific reason not to include it or

you know for certain you will never use it When you select tables, LLBLGen Pro will examine all the relationshipsbetween the tables and create methods to navigate between the entities The more tables you add, the more

relationships LLBLGen Pro will find—including relationships you had not anticipated!

„ For this walk-through, select only the tables listed in Table 2.5 Adding tables is as simple as checking the boxes (Figure 2.6) and clicking Add to project when you are done You will see the tables we just added under the

Entities node (Figure 2.7).

Table 2.5 List of tables to add as entities from the AdventureWorks database

Figure 2.4 Adding entities to the project

Trang 28

Entity Options

Now let’s take a look at all of the options that you can configure for every entity in your project

22

Figure 2.6 Table selection screen

Figure 2.7 Newly added entities

Trang 29

The O/R Mapper

„ Right-click on the Address entity and select Edit/Properties.

From the entity edit screen (Figure 2.8) you will be able to set specific names for each property and relationship.Because each column in the table becomes an entity property with the same name, as long as you named your

database fields well, you should not need to change anything here This list will also tell you the database type of eachcolumn and the corresponding NET type that the column will become in your class LLBLGen Pro also detectswhether or not the column is read-only, the length of the field, and whether or not it can be null Through this cross-checking process, the data layer can catch some errors even before the data is saved in the database

„ Select the Fields on relations tab.

(Figure 2.9) This screen shows a list of all the detected relationships for this entity and the name of the property thatyou use to access the related entity or entity collection For each relationship, you will see the name of the relationship(field name), the two tables that the relationship exists between, and the type of relationship (1:1, 1:n, m:1, m:n) For

this entity there are 14 different relationships! The name given to this field name/property is based on the name of the table on the other side of the relationship For the first relationship in the list, the name is StateProvince

Notice that the 4th relationship in this list, ContactCollectionViaSalesOrderHeader, is a many-to-many relationship that we probably would not have created on our own It traverses the SalesOrderHeader table and allows us to retrieve

a collection of Contacts directly from an Address These extra relationships are helpful additions that do not cost you

any extra time, but that might come in handy later when you are trying to solve a specific problem

„ Select the Relations tab.

The Relations tab allows us to look specifically at the relationship objects themselves (Figure 2.10) Having our

relationships already defined in our database certainly makes our job easier since we do not have to define themmanually

23

Figure 2.8 Entity edit screen

Trang 30

This tab will be important if you want to use a particular relationship that does not exist in your database's schema;

you can manually add new relationships here by clicking Add new custom 1:1/1:n/m:1 relation or Add new custom m:n

relation.

24

Figure 2.9 Entity relationships mapped as fields setup screen

Figure 2.10 Entity relationships setup screen

Trang 31

The O/R Mapper

„ Select the Fields on related fields tab

This tab allows you to have a field from a related entity visible as if it were part of this entity For example, in the

Address table, we have a foreign key that points to a row in the StateProvince table Normally, if we want to know the

name of the state or province we have to look it up However, if we map the name of state or province as a field in our

Address entity, we will have easy access to the value without traversing a relationship to another entity (Note: When using fields mapped to related fields it is important to use Prefetching, which is discussed in Chapter 10).

„ Add the following fields on related fields to the Address entity from the StateProvince table by clicking on Add

new, and selecting the correct field from the Mapped on field list: StateProvinceCode, Name, and CountryRegionCode

(Figure 2.11)

Also, make the following changes to the employee entity:

„ From the main project screen, right-click on the Employee entity, and select Edit/Properties.

„ Select the Fields on relations tab.

„ Change the Employee field name to “Manager”.

„ Change the Employee_ field name to “Manages”.

25

Figure 2.11 Fields on related fields edit screen

Trang 32

Adding Views

Now, we will choose the views in our database to add to our project For now, we will be working with one viewprimarily As we mentioned earlier, with LLBLGen Pro, you can consume a view in two ways First, you can add aview as a typed view

„ From the main project screen, right-click on Typed Views and select Add New Typed Views from Catalog.

We are presented with a list of all the views in our AdventureWorks database (Figure 2.12)

„ Select vIndividualCustomer and click Add to project.

„ Right-click on the vIndividualCustomer that was just added and select Edit/Properties.

(Figure 2.13) The only items you will customize with a typed view are the name of typed view and the field names Ifthese items were poorly named in the database, correct them here

„ Change the name of the view to CustomerView.

The other way of using a typed view is to add it as an entity By adding it as an entity, you will end up with a

collection instead of a typed DataTable You also have the capability of adding relationships to other entities, which

will make filtering rows easier Let’s add the same view as an entity as well

„ Right-click on Entities and select Add New Entities Mapped on Views From Catalog(s) (Figure 2.14).

„ Select the vIndividualCustomer view and select Add to project.

„ Right-click on the new vIndividualCustomer entity and select Edit/Properties.

„ Change the name of the entity to CustomerViewRelated.

26

Figure 2.12 Typed view selection screen

Trang 33

The O/R Mapper

„ On the Entity Fields tab, select the CustomerID row, and check the boxes for Is Readonly and Is part of the primary

key (Figure 2.15).

„ On the Relations tab, click the Add new custom 1:1/1:n/m:1 relation (Figure 2.l6).

„ Select Primary key side, and select SalesOrderHeader as the related table.

„ Make sure both the Primary Key field name and the Foreign Key field name are displaying CustomerID.

Adding the relation will make it possible to retrieve a row in this view directly from an order in the SalesOrderHeader

table

27

Figure 2.14 Adding a view as an entity

Figure 2.13 Typed view field names edit screen

Trang 34

Creating Typed Lists

Now we will create a typed list

„ From the main project screen, right-click on Typed Lists and select New Typed List.

„ Enter the name “CustomerList” and click OK.

28

Figure 2.15 Entity field configuration screen for view mapped as an entity

Figure 2.16 Adding a relationship to a view mapped as an entity

Trang 35

The O/R Mapper

(Figure 2.17) You are presented with a list of all the entities in your project From the list of entities, you can chooseone or more entities to add to your typed list You will then edit the entire list of columns from all the tables you haveselected in order to include only the columns that you want to appear in your typed list

„ Select the Customer entity, and click the Add>> button

29

Figure 2.17 Typed list configuration screen

Table.Field Name Field Alias

Trang 36

You can only add entities to the list that are related Now that you have chosen one entity, the other unrelated entities

in will be grayed-out These tables will define the source from which we will select the columns we want

„ In the order that they are listed, add the following tables: Individual, Contact, CustomerAddress, Address Type,

Address, StateProvince, CountryRegion.

Now we can select the specific columns that we are interested in We will be choosing columns in such a way that the

result will be similiar to the columns in the vIndividualCustomer view.

„ Click on the Fields mapped on entity fields tab, and select the columns according to Table 2.18, making name

changes where indicated As you check the box next to the list of available field names, they are added to thecollection at the bottom of the form (Figure 2.19) These name changes are necessary since there are multiplefields with the column name “name”, and each field name in the typed list must be unique

That is all there is to creating a typed list Our effort will produce a strongly-typed DataTable with these 16 columns.

We can create any criteria that we like when we use this list, but the rows that are returned will always contain these

16 columns Because we know the exact schema of the result set, a typed list gives us an advantage over a storedprocedure No surprises at run-time!

Adding Stored Procedures

Now we will add a stored procedure to the project

„ From the main project screen, right-click on Retrieval Stored Procedure Calls and select Add Stored Procedure Calls

„ Select UsbGetEmployeeManagers and UsbGetManagerEmployees and click Add to Project.

„ Right-click on UsbGetEmployeeManagers and select Edit/Properties

(Figure 2.20) In the edit screen of a stored procedure, you can change the stored procedure’s name or the names ofthe parameters Again, if these names were poorly labeled in the database, take time to correct them here Note thatchanging parameter names here only changes how the stored procedure is referenced in your generated code

Changing the name in your LLBLGen Pro project does not actually change the stored procedure’s name in yourdatabase

30

Figure 2.19 Typed list field selection screen

Trang 37

The O/R Mapper

We have finished adding database objects to our LLBLGen Pro project and now we are ready to generate our code.Before doing so, let’s look at the different code generation options available

Self Servicing vs Adapter

LLBLGen Pro offers two different template groups to select when generating code: Self-Servicing and Adapter In theSelf-Servicing template group, entity objects are responsible for their own persistence (saving their own changes tothe database) The entity class itself contains logic to know which fields were updated and where to find the database,

table, and row necessary to persist itself All you need to do is call the Save() method As you navigate the

relationships of the objects, the data is retrieved from the database as it as needed, without your explicit direction.This is referred to as lazy loading Lazy loading is useful because it abstracts the specific database call from the upperlayers of code However, when it is used incorrectly data access can execute in a grossly inefficient manner (manysmall queries to your database instead of one large query) If you pay attention to how the data is being retrieved asyou use the object you can use a process called prefetching to consolidate database queries and increase performance.Prefetching is discussed in Chapter 10

Using the Self-Servicing template group is similar to an office environment where coworkers are empowered andexpected to know what needs to be done to do their individual jobs You do not need to tell them the all the details.Just point them in the right direction, and they will work out the details on their own

The Self-Servicing template is strongly entity-focused You can see what using the self-servicing code is like whenfetching an order in Example 2.21

Example 2.21 Self-servicing code example

In the above example, as soon as the entity in instantiated in Line 1, all the data is fetched from the database andloaded into the object In Line 2, we can immediately begin using or updating the entity’s properties To save the

changes back to the database, we simple call the Save() method in Line 3

The Adapter template group uses an object called a DataAccessAdapter to interact with the database Instead of

database queries happening behind the scenes automatically, every database transaction will be explicitly called

through the DataAccessAdapter object In this way, the DataAccessAdapter is similar to the built-in TableAdapter object

in NET With this adapter, you have more control over the database connection and can choose when to open it,how long it remains open, and when to close it

31

Figure 2.20 Stored procedure parameter list

Trang 38

The Adapter template group is more like a classroom, where the teacher is firmly in control and tells the studentsexactly what to do Students are not empowered to simply “take care of themselves” The students follow the teacher'sspecific instructions.

The Adapter template group has the advantage of fine-grained control over every database query In addition, italso supports multiple database types and multiple databases If your data needs are complex, the Adapter templategroup might be your only option The Adapter template organizes code around an object that provides data servicesand is independent of the entity objects themselves In Example 2.22, we use an Adapter code to fetch an order

DataAccessAdapter Adapter = new DataAccessAdapter();

ContactEntity MyContact = new ContactEntity(34);

Adapter.FetchEntity(MyContact);

MyContact.FirstName = tbFirstName.Text;

Adapter.Save(MyContact);

Example 2.22 Adapter code example

With Adapter code, we can instantiate the Entity in Line 2, but until we call the FetchEntity() method in Line 3, the data will not be loaded into the object from the database We must use the DataAccessAdapter to read and update the

• Bundles persistence inside entity objects

• Allows data to load itself automatically as it is needed without explicit commands

• Does not require extra objects to perform data access

• Only works for a single database type and a single catalog

• Can be used easily and intuitively

Adapter

• Exposes persistence as a service

• Allows finer database control Each database query is explicit

• Can target multiple databases and catalogs

• Requires an extra object and a few more lines of code

One Class vs Two Classes

(Self-Servicing only)

If you use the Self-Servicing template, another decision you will need to make is whether to use a one-class scenario

or two class scenario In a general scenario (one class), only one set of entity classes are created If you need toextend the generated framework, you can place your custom code inside of the generated classes between specialmarkers to ensure that it will not be overwritten if the code is regenerated Outside of using special markers, youronly other option would be simply to create your own set of custom classes that use the generated framework You

might create an AddressManager class that consumes all the entities associated with placing an order (Figure 2.23)

A better option in certain situations is to use a two-class scenario In this case, two sets of entity classes arecreated The first type is known as the base type and is exactly the same as the entity class in the one-class scenario,but with a different name The extra entity class is an empty class that inherits from the base class You can use thisshell as an instant business layer for all of your custom code This class is kept completely separate from the generatedcode and will never be overwritten when the code is regenerated, so you will not lose your changes Figure 2.24 is an

9) While template modification is outside the scope of this book, LLBLGen Pro customers can freely download the LLBLGen Pro Software Development Kit (SDK) from Solutions Design to get tools and instructions for creating templates and adding custom code to existing templates.

32

Trang 39

The O/R Mapper

example of a two class scenario In this setup, you can place your business logic inside the AddressEntity object,

instead of writing your own “manager” classes Entity classes inherit all the functionality of the base classes, but arenever overwritten when the code is regenerated The two class scenario is highly recommended to fulfill the N-tier best practice in the least amount of time

33

Figure 2.23 General scenario (one class) diagram

Figure 2.24 Two Class scenario diagram

Trang 40

Generating the Code

We are now ready to generate the code for our selected database objects

„ Click on the Project menu and select Generate.

The code generation screen with the 4 main options that you will set for your project is shown in Figure 2.25

„ In the Generator configuration to use option, select Self Servicing, two class scenario (Full) VS.NET 2005.

The Full option in the Two Class Scenario will generate what is necessary to start the project the first time It will

create both the base classes (data layer) and the inherited classes (business layer)

After generating the first time, you would select Servicing, two class scenario (Base Classes Only) for subsequent code

generation tasks Regenerating your code is covered in Chapter 12 Whenever you regenerate your code, it is alwaysadvised that you make a backup copy of your code or check it in to source control before you start, just in case youmake the wrong selection You will never lose your custom code if you make a backup beforehand

„ In the Template set to use option, select C# template set for SQLServer.

„ In the Root namespace option, enter “AW.DATA”.

The namespace decision is important: you cannot change this option without regenerating your code! Thenamespace is so heavily embedded in your classes, it would take you days to change it manually Choose a logicalnamespace that fits in well with your company’s namespace conventions

34

Figure 2.25 Generator configuration screen

Ngày đăng: 16/03/2014, 03:20

TỪ KHÓA LIÊN QUAN