780 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET
Design
During this phase, the functionality to be implemented and the technology to be used are determined. As per the requirement, the component has to be hosted on servers that are being upgraded to .NET; hence, it was decided that the component would be created as a .NET assembly. Additionally, because the component has to be accessed from the kiosk application built using Visual Basic 6.0, it was
decided to use the COM-NET Interoperability (also referred to as COM Interop) services.
So, next I will discuss the design of the login screen of this application.
Y As you are aware of, in this phase, you alsoLdesign the screens of your application.
F M enter his or her login nameAand password. The screen also contains links for a
The login screen of the Art-Shop kiosk has two text boxes in which a visitor can
New User button and a Change Password button. Clicking on these buttons takes the user to the appropriate screens.
E contains text boxesTwhere the visitors can enter their data, such as their name,
A first-time user of the kiosk can register on the New User screen. The screen
address, ZIP code, login name, password, and e-mail address. Out of the details that they enter, the name, login name, and password are mandatory fields. After entering the details, they should click on the Submit button to register themselves.
The Change Password screen allows an existing user to change his or her password. To change the password, the visitor has to enter his or her login name, the previous password, and the new password.
Construction
During this phase, the NewTech team will construct the application. The primary tasks that the team needs to perform are the following:
Create a .NET-based assembly
Create the user interface by using Visual Basic 6.0
Testing
The team decided to test the component by accessing it from a Visual Basic 6.0 application.
Team-Fly®
IMPLEMENTATION OF COM AND .NET INTEROPERABILITY Chapter 26 781
You are now familiar with the requirements that the team is addressing. Next, you will proceed to create the .NET-based assembly (.NET component). The tasks that you need to perform are the following:
Create the Customer table that will store the details of the visitors
Create the Login assembly that will validate the login activity
Finally, test the component from within a Visual Basic 6.0 client
Creating the Customer Table in the
ArtShop Database
The Customer table will contain information about the visitors who register themselves. The following are the steps to create the Customer table.
1.Add a Customer table to the ArtShop database. Run the SQL Server Enterprise Manager. Add a new table Customer and create the fields shown in Figure 26-1.
2.Create the fields with the appropriate data type and size shown in Figure 26-1.
3.Set the Identity property of the CustID field to yes.
4.Set the LoginName field as the primary key field for the table.
FIGURE 26-1The Design Table dialog box of the Enterprise Manager
782 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET
Creating the Login Assembly
Next, you will create the basic assembly using the Managed Extensions Class Library Wizard. The steps to be followed are as follows:
1.Start Visual Studio.NET and create a new Visual C++.NET project. Select ATL Project as the project type.
2.Enter the project name as LoginComp, as shown in Figure 26-2, and enter the path. Click on the OK button.
FIGURE 26-2The Visual C++ New Project dialog box
Once the project has been created, you will find that the IDE has created the basic shell of an assembly. You will find the following code in the file Logincomp.h. I have highlighted the lines of code that are relevant to this discussion in bold
// LoginComp.h
#pragma once
using namespace System; namespace LoginComp
{
public __gc class Class1
{
IMPLEMENTATION OF COM AND .NET INTEROPERABILITY Chapter 26 783
//TODO: Add your methods for this class here. };
}
Change the name of the class from Class1 to Login.
The assembly should be able to do the following:
Validate a login
Allow a new user to register
Allow an existing user to change his/her password
To accomplish this, you need to add three methods to the class. The following are the methods and their signatures:
Method 1:
int addUser(String *CustName, String *Address, String *ZipCode, String
*LoginName, String *Password,String *Email);
The addUser method will accept strings containing a user’s name, address, ZIP code, login name, password, and e-mail address. It will return 0 if the user was added successfully and 1 if the user already exists.
Method 2:
int updatePass(String *login, String *oldPass, String *newPass);
The updatePass method accepts three strings, which contain an existing user’s login name, existing password, and the new password. It will return a 0 if the password was changed successfully.
Method 3:
String * getPass(String *name);
The getPass method accepts a user’s login name and returns the password stored in the database. You will use this method to validate a user login.
Add the declarations of these three methods (highlighted in Bold) to the file
LoginComp.h:
namespace LoginComp
{
public __gc class Login
784 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET
{
public:
// TODO: Add your methods for this class here.
String * getPass(String *name);
int updatePass(String *login,String *oldPass, String *newPass);
In the next section, you will look at accessing data from an SQL Server database using the SQL Server .NET data provider.
Accessing Data Using the SQL Server .NET Data
Provider
You will be using a data provider to connect to the database. To begin with, some of the concepts of ADO.NET that you learned in Chapter 13 need to be revisited.
The .NET data provider is used to connect to a database and execute commands. When a command returns results, they are placed in a DataSet object and exposed to the program. You can use two types of data providers, the SQL server .NET Data Provider and the OLE-DB.NET Data Provider.
The SQL server .NET data provider is lightweight and fast, because it connects directly to SQL Server and is designed to work with SQL Server. It does not have any intermediary layers, such as ODBC or OLE-DB calls. Most data providers expose the following objects:
Connection. Used to create a connection with a data source
Command. Used to execute queries and stored procedures
DataReader. Used to read data from the data source
DataAdapter. Reads data from a data source and populates a DataSet object that can be used to alter or update data in the database
IMPLEMENTATION OF COM AND .NET INTEROPERABILITY Chapter 26 785
Next, you will see how to use these objects to create the Login component. To use the provider, you need to add the following declarations to the LoginComp.h file:
#pragma once
#using <mscorlib.dll>
#using <System.dll> #using <System.Data.dll>
using namespace System; using System::String;
using namespace System::Data;
using namespace System::Data::SqlClient;
Implementing the Methods
First, I will discuss the implementation of the addUser method. The method will insert a new record in the Customer table. It will return 0 if the new record is added and 1 if there is already a record with the same login name or if some other error occurred.
The steps involved are as follows:
1.Create and initialize an SqlConnection object.
2.Create a Command string.
3.Declare and initialize a DataAdapter object.
4.Execute the command.
To create and initialize the connection object, we will use the following code:
In the preceding code, the set_ConnectionString method accepts three parameters:
The name of the server: Data Source=SERVER1
The name of the database: Intial Catalog = ArtShop
The type of authentication: Integrated Security=SSPI
786 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET
Once the SqlConnection object has been initialized, you need to invoke the Open method to establish the connection. This is achieved by the following code:
SConn->Open();
The next step is to create and initialize a string that will contain the command to be executed. You will be using the Concat method of the String object to construct the command string:
String *strCmd;
strCmd=”insert into Customer(CustName,Address,ZipCode,LoginName,Password,Email) values(‘“ ;
The last step is to execute the command, which is done using the following code:
dataAdapter->UpdateCommand->ExecuteNonQuery();
The next method to be implemented is the updatePass method. The updatePass method accepts three parameters: the login name for which the password has to change, the current password, and the new password.
int Login::updatePass(String *login,String *oldPass, String *newPass)
IMPLEMENTATION OF COM AND .NET INTEROPERABILITY Chapter 26 787
To implement this method, create a new SqlConnection object and initialize the connection string using the set_ConnectionString method and then open the connection. Then, retrieve the values to construct the command strings:
Moving on, you will implement the third method, getPass. The getPass method uses code similar to the preceding two examples to create the connection object. However, since the task of this method is to accept a login name and return the corresponding password, it does not use a DataAdapter class. Instead, it uses the DataReader class. To show how we can use an object of the type DataReader like a read-only cursor, we will retrieve the complete content of the table and look for the login name:
sCommand->set_CommandText(“select LoginName, Password from Customer”);
SqlDataReader *dataReader;
try{
dataReader=sCommand->ExecuteReader();
788 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET
Once the content of the table is retrieved, scroll through the DataReader object for a login name matching the one passed as the parameter. If found, return the corresponding password; otherwise, return NoUser. The following code snippet illustrates this logic:
The following is the complete code for the Login class. Since the Login class is a part of the LoginComp namespace, you need to add a using declaration.