Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Monday, July 18, 2011

Remote Debugging .NET Applications

From the past few days I have been stuck in resolving a bug which cropped up in one of my applications after it went to Production. The worst part was that it was a machine-specific issue and we couldn't reproduce it in any of our development systems. While trying to find a solution for this, I came across the concept of Remote Debugging.

Remote debugging is debugging a remotely running application through a development environment running on a system other than the one running the app. This is done by connecting the remote system to the system containing the development environment (in turn the debugger) through Sockets. Theoretically this is achieved in two steps -

  • The remote computer would open a socket and listen to debug instructions through it. These instructions are feed to the application that is being debugged and the application responds appropriately
  • The debugger would connect to the socket opened by the remote system and send instructions through it

Remote debugging can be used in many live situations. Examples include -

  • Debugging a machine specific issue which can't be reproduced on systems running the development environment (my exact requirement :))
  • Debugging applications which can run only on the server machine due to dependent third party libraries that cannot be used in the development machine

In this blog post, I will be focusing on Remote Debugging .NET applications through Visual Studio 2010. The screen shots correspond to a simple .NET application which would popup a MessageBox on a button click. Get the code here.

Configuring the Host Computer

The host computer is the computer containing the development environment. This is the system running Visual Studio 2010. To enable Remote Debugging, make sure the following ports are open on the host computer -

Ports
Protocol
Description
135
TCP
Required
500, 4500
UDP
Required if your domain policy requires network communication to be performed through IPSec

IPSec (Internet Protocol Security) is a protocol suite for securing IP communications authenticating and encrypting each IP packet of a communication session. Read more about IPSec here. However I am not going cover IPSec in this post.

You can check if the ports are open by using the telnet command at command prompt (telnet isn't installed by default on Windows 7. Install it from the "Turn Windows features on or off" section in the Control Panel).

Configuring the Remote Computer

To configure the remote system for debugging, either download and install the Microsoft Visual Studio 2010 Remote Debugger or copy the folder Remote Debugger from the Visual Studio install path, which is typically C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE. The Remote Debugger is available for three configurations - x86, x64 and ia64.

Visual Studio takes the .pdb files for debugging from the remote system for managed code. So copy the .pdb from the bin/Debug folder of the project to the remote system. Put this folder on share so that Visual Studio can access it later.

To enable Remote Debugging, make sure the following ports are open on the host computer -

Ports
Protocol
Description
135, 139, 445
TCP
Required
137, 138
UDP
Required
500, 4500
UDP
Required if your domain policy requires network communication to be performed through IPSec
80
TCP
Required for Web Server debugging

That's it; both the host and remote computers are up and ready for Remote Debugging.

Start the application on the remote system if it isn't running already. Also start the Visual Studio Remote Debugging Monitor on the remote system using the msvsmon.exe from the appropriate configuration folder in the Remote Debugger directory (The screenshot uses the x86 version).

Open the code in Visual Studio on the host system and select "Attach to Process". Typically Visual Studio identifies the .pdb file of the remote system if it can. If it doesn't, open the Modules screen from Debug -> Windows -> Modules. Check the Symbol Status of the .exe file which is being debugged and if it shows "Cannot find or open the PDB file" right-click on it and select "Load Symbols From" and specific the share path through the "Symbol Path".

Specify the breakpoints in the code and they would hit appropriately. There are two major bottlenecks in Remote Debugging -

  • The code from which the executable was built should be available at the time of debugging
  • The above mentioned ports should be open for debugging. Most of the developers wouldn't have administrative privileges on the client systems, so they would require people with sufficient privileges to open up these ports. However several organizations wouldn't prefer opening up ports for incoming connections

Before I conclude, here's an article from MSDN on how to Set Up Remote Debugging. Visit it if you would like a deeper insight into Remote Debugging.

Sunday, January 30, 2011

Introducing ADO.NET Entity Framework

This is the third and final part of my ORM series in which I am going to introduce the ADO.NET Entity Framework, an in-built Object Relational Mapping model of the .NET Framework.

Similar to the previous post, this one also covers the same four principles -

  • Configuring a .NET project for the ADO.NET Entity Framework
  • Inserting data from Objects directly
  • Retrieving data using Object Lists an LINQ
  • Changing the Database Management System

Though the screen-shots and the example codes emphasize on C#, the principles are same for all the .NET languages.

Requirements to run the example in this article - Visual C# Express, SQL Server Express and MySQL. Download Visual C# Express here, SQL Server Express here and MySQL here.

Configuring a .NET project for the ADO.NET Entity Framework

To configure a .NET project to work with the ADO.NET Entity Framework, an Entity Data Model is added to the project. The Entity Data Model is primarily a schematic representation of the database tables stored as a XML file. Each of these tables is converted into a class and foreign key relationships between these tables are maintained as Lists inside the objects.

Visual Studio provides a Wizard to create Entity Data Models. Right click on the project and select New Item from the Add menu. Choose the ADO.NET Entity Data Model template from the chooser. There are two approaches available to build the Entity Data Model - Database First Approach and the Model First Approach.

In the Database First Approach, the Entity Data Model is generated from existing table structures. The wizard allows the developer to setup a connection by providing the Database Server name and the Database name. The wizard also allows developers to choose tables, views and stored procedure that are to be a part of the Entity Data Model.

In the Model First Approach, the Entity Data Model is created from scratch and the database tables are generated based on this model.

Once the wizard completes, a designer opens up which shows a schematic representation of the generated .edmx file. This file contains the table mappings as a XML along with a code behind file with a .Designder.cs extension for the auto-generated classes corresponding to the tables. However a drawback with the Entity Data Model is that it combines all the classes into a single file which makes manual maintainence a little difficult.

I used the Database First approach to create the sample application to insert and retrieve data. You can get the MySQL and SQL Server scripts along with the Visual Studio solution here.

Inserting data from Objects directly

The Entity Model generates a class which inherits from ObjectContext. This class acts as a data manager to connect to the Database Management System to retrieve, insert, update and delete records.

ADO.NET Entity Framework maintains the records of the table as a List of objects. To insert new records into the table, create new objects, add them to the appropriate lists and then save the changes using a ObjectContext instance. The following piece of code shows how objects can be persisted -

using (Context context = new Context())
{
// Create the object
context.Objects.Add(object);
context.SaveChanges();
}

ADO.NET Entity Framework does a wonderful job while storing objects with foreign key dependencies. These dependencies are maintained using lists as objects and while storing these records, the appropriate identity keys are inserted into the child tables. However this feature is limited to a few DBMS like SQL Server.

Retrieving data using LINQ and Object Lists

The ADO.NET Entity Framework retrieves data from the back-end tables in the form of object lists. So accessing records is as simple as iterating through these lists.

using (Context context = new Context())
{
foreach (Object object in context.Objects)
// use the object appropriately
}

Since data retrieval is in the form of lists, developers can piggy-back on an other .NET framework feature - LINQ (Language Integrated Query). LINQ makes conditional querying of data a lot easier.

using (Context context = new Context())
{
var objects = from object in context.Objects where "condition" select object;
// use the objects
}

Changing the Database Management System

Before changing the DBMS of the Entity Model, it is important to understand how the ADO.NET Entity Framework stores the connection strings and the mapping between classes and the back-end tables. The connection string is stored in the App.Config file of the project and the table mappings are stored as a XML in the form of the .edmx file as mentioned earlier.

Unfortunately the ADO.NET Entity Framework varies it's implementation with the DBMS. Because of this modifying the XML manually isn't easy. For Example, ADO.NET Entity Framework does not support foreign key constraints in the form of lists for DBMS like MySQL.

The sample application contains another Entity Model which connects to a MySQL Server containing similar tables. To use MySQL with the ADO.NET Entity Framework, an connector is needed. The MySQL Connector/NET is available here.