Tip: DirectorySeparatorChar

by Donn Felker 29. July 2007 11:02

If you look at most file access code you'll see the following somewhere:

string filePath = myDirectory + "\\" + myOtherDirectory + "\\" + myfile;

Developers will build their file paths with hard coded values such as "\\". This isn't the best way to accomplish things. For example, what happens if your code needs to get run on Mono? *NIX paths are different than that of Windows. When I see a string literal with a directory separator in it, or even in a constant, I cringe. How do we get around this? Easy...

Enter DirectorySeparatorChar

In the .NET Framework, in the System.IO Namespace in the Path class you'll find a public static field by the name of DirectorySeparatorChar.

Here's what it does: In a Windows and Mac environment it will return the backslash character. In a *NIX environment it will return a slash "/".

No more hard coding separator characters!

You would now build the same path above, like this:

string filePath = myDirectory + Path.DirectorySeparatorChar + myOtherDirectory + 
                 Path.DirectorySeparatorChar + myfile;
The code is now much more stable and is much easier to adapt to a *NIX type of environment.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Ubuntu and Virtual PC 2007 Mouse Issues

by Donn Felker 27. July 2007 16:15

ubuntulogo I recently ran into an issue while installing Ubuntu to test Mono.

Apparently when you install Ubuntu 7.04 on Virtual PC 2007 the system doesn't recognize the mouse. MAJOR SUCKAGE. Luckily I found a link that helped me through this and eventually got my mouse working for Ubuntu on VPC 2007.

This is mainly a post to log it for my own purposes, but hopefully it helps you as well. A big thanks to the guys who figured this out.

Links

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Mono | Virtual PC

Returning XML Data as a Record Sets through the CLR in SQL Server 2005

by Donn Felker 26. July 2007 12:10

The Problem

I needed to write something like this ...

SELECT * FROM CustomerTest WHERE Customer_Id = 1;

The data returned needed to return the row as well as the data inside of the XML Column in that row, in the same set. (The data in the XML column needed to be returned as sets of records as well.) The XML Contained was simple XML that looked like this:

(click for larger image)

xmlExample

The XML Column was called "Extra_Info". This is where the above XML was stored.

image

Ok, lets get to the point... here's what its supposed to look like when the query is run:

(click for larger image)

image

A little more about the problem domain..

Awhile back I had a client who wanted to store data in an XML Field, but the XML for each row could be extremely different in each row. One row might have a XML Document that has 1 set of data, while the next might have 10. These XML documents that were being stored did not share a common schema -- not at all. But we needed to return the data in an SQL Query or SPROC that would allow the user to view the data as if it were tables in the database.

Solution

So how do we do that with one Query?

Easy - SQL CLR Integration.

We can create a CLR Stored Procedure to do this for us.
Here are the steps the CLR SPROC will go through to return the data.

  1. Query the DB for the record.
  2. Get the XML from the column.
  3. Load the XML into a DataSet object.
  4. Send the original record results of the row to the client.
  5. Create record sets off of the DataSet using SqlDataRecord object.
  6. Send each record back to the client.

Code time baby...

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;
using System.Collections.Generic;
using System.Data.Common;
using System.Xml;


public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void TestProcedure(SqlInt32 recordId)
    {
        DataSet dataset = null; 

        using (SqlConnection connection = new SqlConnection("context connection=true"))
        {
            string xml = string.Empty;
            using (SqlCommand command = new SqlCommand("SELECT * FROM dbo.CustomerTest WHERE Customer_Id = @recordId"))
            {
                command.Parameters.Add(new SqlParameter("@recordId", recordId));
                command.Connection = connection;
                if (connection.State != ConnectionState.Open)
                {
                    connection.Open();
                }

                using (DbDataReader reader = command.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        xml = reader["Extra_Info"].ToString();
                        
                        // Load in the XML. 
                        XmlReader xmlReader = new XmlTextReader(xml, XmlNodeType.Document, null);
                        dataset = new DataSet();
                        dataset.ReadXml(xmlReader);
                    }

                }
                SqlContext.Pipe.ExecuteAndSend(command);

            }

            
        }

        if (dataset != null)
        {
            foreach (DataTable table in dataset.Tables)
            {
                // Set up the record 
                List<SqlMetaData> metaData = new List<SqlMetaData>();
                foreach (DataColumn column in table.Columns)
                {
                    metaData.Add(new SqlMetaData(column.ColumnName, SqlDbType.Variant));
                }
                SqlDataRecord record = new SqlDataRecord(metaData.ToArray());

                // Mark the begining of the result-set.
                SqlContext.Pipe.SendResultsStart(record);

                foreach (DataRow row in table.Rows)
                {
                    foreach (DataColumn column in table.Columns)
                    {
                        record.SetValue(table.Columns.IndexOf(column), row[table.Columns.IndexOf(column)]);
                    }

                    // Send the row back 
                    SqlContext.Pipe.SendResultsRow(record);
                }
                // Mark the end of the result-set.
                SqlContext.Pipe.SendResultsEnd();
            }
        }

    }

}
Code Review

The sproc is created with the code above.

If we find a record we load the xml into a variable and then load the DataSet with the XML using the ReadXml Method of the DataSet.

if (reader.Read())
{
  xml = reader["Extra_Info"].ToString();
                      
  // Load in the XML. 
  XmlReader xmlReader = new XmlTextReader(xml, XmlNodeType.Document, null);
  dataset = new DataSet();
  dataset.ReadXml(xmlReader);
}

Next, we loop through each data table and each record in the data table to create a SqlDataRecord. To build an SqlDataRecord we need a Record definition.These record definitions are defined as SqlMetaData objects. Therefore we need populate an array of SqlMetaData objects by looping through the columns to get the column information. At this point we're building the columns in which the data will exist in.

// Set up the record 
List<SqlMetaData> metaData = new List<SqlMetaData>();
foreach (DataColumn column in table.Columns)
{
  metaData.Add(new SqlMetaData(column.ColumnName, SqlDbType.Variant));
}
SqlDataRecord record = new SqlDataRecord(metaData.ToArray());

From here, we will build the actual records. This is done by the following method:

  • Inform the context that we're going to begin sending a record by using the SendResultsStart method of the Pipe class.
  • When a record is built, we want to send it to the client by calling the SendResultsRow method. This sends the row to the client. We will do this for each record built.
  • After the records have been sent we want to tell the client we're done sending records for this set. We do this by calling the SendResultsEnd method.

This happens for each DataTable in the DataSet. And then finally the results are sent back to the client.

Resolution

Once deployed, the sproc (which I've named "TestProcedure") will show up under the StoredProcedures area of SQL Server, as shown here:

image

And now you have a stored procedure that will return results of the row as well as the data that is in the XML column, all in the same result set.

Uses: You could use this as an extensibility point in your application  by allowing users to add custom fields to the application at run time and then storing the application fields and field data in an XML file which is stored in an SQL Server column. Think of it as a database inside of a database. You could then use it to query the row/column to get the results into a readable form for Crystal or Reporting Services.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | ASP.NET | SQL Server

HOW TO: Display Required Field Validators at Page Load

by Donn Felker 20. July 2007 11:01

Sometimes when a page loads you'll want the user to be able to see the which fields are required. This is normally done by presenting an asterisk next to the fields that need to be populated/selected.

The RequiredFieldValidator does not automatically perform validation upon load, but here's some code that will allow you to do so:

I usually put this in the OnPreRender event handler as at that point everything is done processing on the page.

foreach (IValidator validator in Validators)
{
    if (validator is RequiredFieldValidator)
   {
     validator.Validate();
   }
}

This will ensure that the page's required field validators are validated when the page loads. Therefore giving the user the insight into the required fields.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

ASP.NET AJAX Always Visible Control Frustrations

by Donn Felker 17. July 2007 08:47

Unfortunately I don't have time to go through and figure out why the Always Visible control wont work with a user control. Although I assume it has something to do with the HTML DOM. Some relationship in there is probably hard coded or assumed.

Here's what I was trying to do:

I want to have an always visible control that had some items in it (lets say a bunch of links). I wanted that to be in a user control. I wanted that user control to be the "always visible" control. So I set the TargetID to the user control and ... NO DICE. Doesn't work. I get a cannot load behavior ID or something like that. Its a JavaScript error, and I could figure it out if I had time, but unfortunately the project I'm on doesn't permit.

I even attempted to get around this by putting all of the ASP.NET AJAX into a user control and then add the user control to the page. NOPE, didn't work.

Solution

This is kind of a hacky solution, but it works. You can get this to work by putting all of your controls into a user control. Then wrap your user control in a panel. Like so:

<ajaxToolkit:AlwaysVisibleControlExtender
    ID="avce" runat="server"
    VerticalSide="bottom"
    TargetControlID="scrollingPanel"
    VerticalOffset="10"
    HorizontalSide="Right"
    HorizontalOffset="10"
    ScrollEffectDuration=".1" />
<asp:Panel runat="server" ID="scrollingPanel">
    <uc1:MyUserControl ID="myUc" runat="server"  />
</asp:Panel>

This will allow you to still use a user control, but in my opinion, its kind of hacky. If and when I find time to work around this I'll post an update. If anyone else knows of a fix, please let me know.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

AJAX | ASP.NET

ASP.NET Projects Take Forever To Load in Internet Explorer

by Donn Felker 8. July 2007 23:47

I recently had a problem that plagued me the last couple of weeks.

Problem: When I pressed F5 or CTRL + F5 or even "View in Browser" from Visual Studio (in an ASP.NET project) Internet Explorer would load. If I had any breakpoints set, the debugger would break, and then I could continue after debugging (or, if I didn't debug the project would continue to load as normal -- in Internet Explorer). Once the project continued to load in Internet Explorer (IE), IE would HANG.

I'm not talking a 5-10 second load. I'm talking 2-3 minutes!! After the initial load, the application would load as expected. I could hit refresh, everything and it would load as expected. Unfortunately this isn't a feasible solution when I need to debug on a normal basis and I cannot be waiting 2-3 minutes for the debugger to start.

The weird about this is... if I opened IE and went to ANY WEBSITE the site would load instantly. The problem was only with ASP.NET projects, making me thing it had to do with the local cassini web server.

Resolution: After some reading, I came to the conclusion that it could be related to a proxy server. I took a look, NOPE, no proxy server here. So then I started poking around with the system. There were no event logs for anything relating browser or .NET issues. I could not find anything related to this issue, other than a couple people having the SAME exact problem.

On a fluke I decided to hit F5, and then while the enormous load time was taking place I started FireFox. I copied the URL from IE (which looked something like: http://localhost:49696/default.aspx) and then posted it into the address bar of FireFox and hit Enter. To my amazement, the page loaded immediately. But  IE was still hanging, and waiting.

After changing some settings in the Internet Options panel of IE I decided to reset IE's settings (see below).

After resetting everything, everything started working again. I'm not sure what setting had started this behavior, but I do know that something in my Internet Settings got changed. Over the next week I'm going to attempt to recreate the issue, and if I'm able to, I'll post the solution here.

But if you're having this same problem, reset your settings in IE!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

ASP.NET | Productivity | Visual Studio 2005

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

Donn Felker

Senior Consultant
MCTS
ScrumMaster
Agile Practitioner

About Me | Books I Recommend

Gotta Pay The Bills


Tag cloud

    Popular Posts

    RecentComments

    Comment RSS

    Calendar

    <<  December 2008  >>
    MoTuWeThFrSaSu
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    View posts in large calendar