<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TheCodeMonk &#187; .Net Code</title>
	<atom:link href="http://thecodemonk.com/category/net-code/feed/" rel="self" type="application/rss+xml" />
	<link>http://thecodemonk.com</link>
	<description>Random Thoughts of a Software Development Professional</description>
	<lastBuildDate>Mon, 02 Aug 2010 13:35:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Global Application Settings Override (Now with examples!)</title>
		<link>http://thecodemonk.com/2010/07/29/global-application-settings-override-now-with-examples/</link>
		<comments>http://thecodemonk.com/2010/07/29/global-application-settings-override-now-with-examples/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 03:08:50 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[VB.Net]]></category>
		<category><![CDATA[Windows Deployment]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/?p=57</guid>
		<description><![CDATA[My previous posting about TableAdapter connection strings was a pretty big hit with a lot of people. It&#8217;s still being referenced on the MSDN forums from time to time when someone needs a solution to the problem of having a connection string for a TableAdapter in the app.config that they need to override at runtime. [...]]]></description>
			<content:encoded><![CDATA[<p>My <a href="http://thecodemonk.com/2008/02/18/tableadapter-connection-strings/">previous</a> posting about TableAdapter connection strings was a pretty big hit with a lot of people. It&#8217;s still being referenced on the MSDN forums from time to time when someone needs a solution to the problem of having a connection string for a TableAdapter in the app.config that they need to override at runtime.</p>
<p>Since that post was in VB.Net and over 2 years old now, I&#8217;ve decided to resurrect it and work up a quick sample project with both C# and VB.Net code. Someone had request C# and I have no idea why I didn&#8217;t include it when I did that post, but better late than never!</p>
<p>Click <a href="http://thecodemonk.com/wp-content/uploads/2010/07/SettingsOverrideSample.zip">here</a> for the sample solution. (VS2010) If you don&#8217;t have that version of visual studio, you can download the express version from Microsoft, or just open the projects individually in VS2008.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2010/07/29/global-application-settings-override-now-with-examples/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Wrap your ASP.Net session state into a more meaningful object.</title>
		<link>http://thecodemonk.com/2009/12/08/wrap-your-asp-net-session-state-into-a-more-meaningful-object/</link>
		<comments>http://thecodemonk.com/2009/12/08/wrap-your-asp-net-session-state-into-a-more-meaningful-object/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 23:15:25 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/?p=51</guid>
		<description><![CDATA[I&#8217;ve tried to eliminate as much session state as possible as I know that it can cause some issues, especially in a server farm environment. However, there are quite a few times that I just need to have it, and I really doubt this small application is going to be hosted in a farm environment. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve tried to eliminate as much session state as possible as I know that it can cause some issues, especially in a server farm environment. However, there are quite a few times that I just need to have it, and I really doubt this small application is going to be hosted in a farm environment. This application is connected to a WCF service, and I really needed to eliminate round trips without using caching since some of this data is somewhat time sensitive, but it still needs to be available across a few page views. Instead of hitting the WCF service numerous times, I save the data in session state.</p>
<p>The way most people seem to have done session state (at least in just random searches on the internet and in sample code), you see this:</p>
<pre name="code" class="C#:nogutter">
  HttpContext.Current.Session["SomeData"] = myData;
</pre>
<p>There is nothing wrong with this. It works. Is it maintainable? Sort. Is it a potential problem? YES! What happens if you do this somewhere:</p>
<pre name="code" class="C#:nogutter">
  myData = HttpContext.Current.Session["SomData"];
</pre>
<p>Obviously you are going to get a null object back and possibly an error depending on other factors. You will probably find the problem during your automated tests (you do have automated tests right?) or at minimum find it during your own testing. The problem is, sometimes things like this will slip past if they are in infrequently used parts of a system that no one bothers to check for 3 or 4 versions that pass.</p>
<p>So in searching around I found various posts on how to wrap your session state into a more manageable object so that typos don&#8217;t creep up and bite you on the backside. Some of the examples went way over what I needed to do and some were way too simple to make sense for me.</p>
<p>So here is what I did (if I happened to have stolen your code, sorry, but it happens in software).</p>
<p>First I created my Current Session class to store everything and I made it static since Session itself is a static object.</p>
<pre name="code" class="C#:nogutter">
  public static class CurrentSession
  {
    private static HttpSessionState LiveSession
    {
      get { return HttpContext.Current.Session; }
    }
  }
</pre>
<p>This simple gives me a class that has access to the current session through a private variable called LiveSession.</p>
<p>Inside this class, I created another class for the CurrentUser since I needed to track the current logged in user (this user has data from the web service, so I&#8217;m not using asp.net authentication methods).</p>
<pre name="code" class="C#:nogutter">
    public static class CurrentUser
    {
      public static bool IsLoggedIn
      {
        get
        {
          bool? logIn = GetUserItem<bool?>(UserData.LoginState);
          if (!logIn.HasValue) logIn = false;
          return (logIn.Value);
        }
        set { SetUserItem<bool>(UserData.LoginState, value); }
      }

      public static FamilyData CurrentFamily
      {
        get { return (GetUserItem<FamilyData>(UserData.Family)); }
        set { SetUserItem<FamilyData>(UserData.FamilyInfo, value); }
      }

      private static T GetUserItem<T>(UserData key)
      {
        T data = (T)LiveSession[Enum.GetName(typeof(UserData), key)];
        return (data);
      }

      private static void SetUserItem<T>(UserData key, T data)
      {
        if (data == null)
          LiveSession.Remove(Enum.GetName(typeof(UserData), key));
        else
          LiveSession[Enum.GetName(typeof(UserData), key)] = data;
      }

      public enum UserData
      {
        Family,
        LoginState
      }
    }
</pre>
<p>Now, some explanation and why I did it the way I did. I could have just made my public variable have the getter and setter access the Session object directly. My typo chances would have been minimized by the fact that it&#8217;s only in two spots that I need to type it, but there is still a chance. So I created myself an enum that I can use to specify which sets of data I am saving or retrieving. I use the enum&#8217;s string value as the session object name, so all I have to do is make sure my enums never use the same name. In my RLC (Real Life Code) I use much longer enums, like CalendarFilterMonth or CalendarFilterDay, for example. In the above example, I use LoggedInUserFamily in place of just Family. While it may be long, intellisense always gets it right for me with just a few keystrokes.</p>
<p>The GetUserItem and SetUserItem simple save and retrieve from the LiveSession object. I use Type generics to tell the functions what type I am saving and retrieving for ease of use. My type casting never has to be done now. I tell it what I want and that&#8217;s what I will get in return.</p>
<p>The best part about this, is to add more, all I need to do is copy and paste a property and change a few of the options, maybe add an enum, and now I&#8217;m done. I don&#8217;t have to worry about typo&#8217;s and I can organize my session object however I want.</p>
<p>To use it, I just do this anywhere in my application:</p>
<pre name="code" class="C#:nogutter">
  if (!CurrentSession.CurrentUser.IsLoggedIn)
     RedirectToLogin();
  else
     if (CurrentSession.CurrentUser.CurrentFamily.NeedsProfileUpdate)
        RedirectToUpdate();
</pre>
<p>Since NeedsProfileUpdate is part of my FamilyData class, I can access that directly!</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2009/12/08/wrap-your-asp-net-session-state-into-a-more-meaningful-object/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>First usage of WCF and specified fields.</title>
		<link>http://thecodemonk.com/2009/04/27/first-usage-of-wcf-and-specified-fields/</link>
		<comments>http://thecodemonk.com/2009/04/27/first-usage-of-wcf-and-specified-fields/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 19:33:52 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[WCF]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/?p=37</guid>
		<description><![CDATA[I hadn&#8217;t done much in the past with WCF. We had built our web service with the classes .Net 2.0 form of web services and it worked well. Then one day I realized that we had no built in security other than SSL. Since we had added a lot more things to it that could [...]]]></description>
			<content:encoded><![CDATA[<p>I hadn&#8217;t done much in the past with WCF. We had built our web service with the classes .Net 2.0 form of web services and it worked well. Then one day I realized that we had no built in security other than SSL. Since we had added a lot more things to it that could do some damage if a hacker found the service address, I decided to add some basic security. Needless to say, it&#8217;s not as easy as it looks with straight web services.</p>
<p>After doing some searching, I found a few examples of using WCF and implementing custom username authentication, which is exactly what I wanted to do. </p>
<p>Getting WCF set up and running was quite easy. Porting over our web service code just meant creating my ServiceContract and DataContracts and then recompiling. I also had to set my SQL to Linq datacontext serialization mode to Unidirectional. After coding up my custom username authentication and testing it, things were going along quite smoothly.</p>
<p>Everything I had experienced with Linq to SQL serialization still applied to WCF. Relationships had to have the parent set to internal access instead of public. I did also find that the relationships seemed to need a One-To-Many in order to work right. If it was a Many-To-One or a Many-To-Many, it wasn&#8217;t being sent from the WCF service to the client. Since I was in a hurry, I left that issue on the back burner and worked around it. If I five more into it, I will post about it here.</p>
<p>The one thing I had not counted on, was the fact that if you have any fields (properties) marked as being nullable, the Add Service wizard in Visual Studio 2008 will also add a boolean field called fieldSpecified. So if you have a nullable field for, say, PhoneNumber, you will have that and PhoneNumberSpecified. If you fill in the PhoneNumber field, but do not set PhoneNumberSpecified to true, the field will not be sent to the WCF service.</p>
<p>From my little bit of research, if that Specified field is set to false, the property will not be included in the XML document sent to the WCF service. If it is set to true, it will send it whether it&#8217;s null or not. </p>
<p>Since some of our classes have quite a few fields and we have quite a bit of code to set those fields, I did not want to go through and set every one of these stupid properties to true when I set a field. I&#8217;m actually quite surprised that we even need to do this.</p>
<p>In searching for an answer, I found the long way around of writing a program to parse your service.cs (or .vb) file and inserting this code:</p>
<pre name="code" class="C#:nogutter">
  [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
  public string PhoneNumber
  {
    get
    {
      return this.PhoneNumber;
    }
    set
    {
      this.PhoneNumber = value;
      PhoneNumberSpecified = true; // Line Added
    }
  }
</pre>
<p>So, we have to add one line to each property that has a corresponding Specified field. Now I know why people wrote a utility to do this. That file will get overwritten each time you update your service reference.</p>
<p>I wasn&#8217;t too pleased I had to do this so I tried to find a better way. I finally settled on using the PropertyChanged events and some reflection to go and fill that field in.</p>
<p>To make things simple, my Linq to SQL classes all have a base class called BaseBusiness where I do validation and hold some original values so we can use the disconnected nature of the web with Linq to SQL entities. Since I did this, I can only derive my classes on the client side from the same base class. So I created my BaseBusiness class and included my PropertyChange event in there like this:</p>
<pre name="code" class="C#:nogutter">
  public partial class BaseBusiness
  {
    public void InternalPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
      if (!e.PropertyName.Contains("Specified"))
      {
        string prop = String.Format("{0}Specified", e.PropertyName);
        PropertyInfo target = this.GetType().GetProperty(prop);
        if (target != null)
        {
          PropertyInfo src = this.GetType().GetProperty(e.PropertyName);
          bool currentValue = (bool)target.GetValue(sender, null);
          bool hasValue = (src.GetValue(sender, null) == null ? false : true);
          if (currentValue != hasValue)
            target.SetValue(sender, hasValue, null);
        }
      }
    }
  }
</pre>
<p>This is pretty straight forward so far. I check to see if the field is already set to what it should be so I don&#8217;t make any unneccesary calls. Note that I use sender as the object I am using the GetValue and SetValue on. This is because the event is in a base class and wouldn&#8217;t be the right object to use for reflection since the properties would be one level up (or down, depending of where you stand).</p>
<p>Now the only step left is to write it up in the data classes. Which is nothing more than this:</p>
<pre name="code" class="C#:nogutter">
public partial class MyDataClass : BaseBusiness
{
  public MyDataClass()
  {
    this.PropertyChanged += InternalPropertyChanged;
  }

  ~MyDataClass()
  {
    this.PropertyChanged -= InternalPropertyChanged;
  }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2009/04/27/first-usage-of-wcf-and-specified-fields/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linq to SQL in web services</title>
		<link>http://thecodemonk.com/2009/03/02/linq-to-sql-in-web-services/</link>
		<comments>http://thecodemonk.com/2009/03/02/linq-to-sql-in-web-services/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 23:26:20 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[linq]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/?p=23</guid>
		<description><![CDATA[Quite a while ago, I investigated the use of Linq to SQL in our one web service component that feeds a CMS that we package with out software. In my initial investigations, every time I would send an entity through the web service, I would get a circular reference error. This made sense since each [...]]]></description>
			<content:encoded><![CDATA[<p>Quite a while ago, I investigated the use of Linq to SQL in our one web service component that feeds a CMS that we package with out software. In my initial investigations, every time I would send an entity through the web service, I would get a circular reference error. This made sense since each relationship is bidirectional. If I have a family entity that has a relationship to a person entity, that person entity also has a reference to the family entity. This goes on infinitely. Those relationships are nice because you can grab one single person and then get data out of the family entity without having to do any joins or write a separate query. So what do you do? </p>
<p>There are a couple of options. </p>
<p>1. Make the data context serialization unidirectional. This will turn off all relationships. You will have to manually do your joins using Linq when the data reaches the other side of the transaction.</p>
<p>2. Change the parent access modifier of the relationship to Friend (VB) or Internal (C#). This leaves the child relationships intact but removes the parent relationships. There would no longer be a family relationship in the person entity. </p>
<p>I prefer option 2 simply because then I don&#8217;t have to rejoin my data every time I fetch it. I don&#8217;t need those child to parent relationships because I can build around it by making my web service functions return the family instead of just returning a person, even if I just request the person.</p>
<p>The next issue that I ran into was the updating existing records. Since adding new records takes a detached object and just inserts it as new, that isn&#8217;t an issue. The problem comes in the concurrency tracking that Linq to SQL uses. You either time stamp your record, or you allow it to check previous fields for concurrency. We don&#8217;t use the time stamp method. The way that most things work in the SQL world is that when you save, you either overwrite what is currently in the table, or you get an concurrency error that makes you input everything over again after getting a refresh from the database. This is not the way we like it. We like a merge scenario where I can make a couple changes to the record and someone else can make some other changes and we the save is made, both our changes make it to the database.</p>
<p>So, how do you fix this? It&#8217;s easy with Linq to SQL. It already has the merge saving built in, unlike ADO.Net. (The Entity Framework will do this as well if you set it up right.) Even though Linq to SQL already supports the saving, this won&#8217;t work in web services. The problem is that during serialization, the entity loses it&#8217;s data context. It&#8217;s the data context that actually tracks the changes in the record, not the entity itself. So once the data context loses it&#8217;s entity (gets detached), it has to be reattached in order to do the save. The problem with this is that the data context no longer knows what has changed in this entity, so it cannot do any concurrency validation. The key is to use the Attach method and fill in two of it&#8217;s parameters, one for current entity and one for the original entity. There are a couple ways you can do this, but I choose to add a base class where I could store the serialized entity (complete with children) and ship it back and forth.</p>
<p>No matter how you slice it, you are going to have the overhead of change tracking eating up bandwidth to and from the web service to the calling application. This can either be incredibly apparent by holding your original values in the session state and just passing it back to the web service, or you can serialize it in the entity object and just pull it out later. I use this method for simplicity. I actually just make a business class (actually, I already had one because all my validation is stored there in a generic, fun sort of way that allows it to just interact with IDataError) and in that business class, I just add a object holder and some functions to set the original value.</p>
<p>Here is a small sample of the base business class:</p>
<pre name="code" class="vb.net:nogutter">
Imports System.Xml.Serialization

Public Class BaseBusiness

  Private original As Object

  Public Sub SetOriginalValue(ByVal _OriginalValue As Object, ByVal originalType As System.Type)
    Dim sb As New StringBuilder()
    Using strw As New System.IO.StringWriter(sb)
      Dim SXO As New XmlSerializer(originalType)
      SXO.Serialize(strw, _OriginalValue)
      original = sb.ToString()
    End Using
  End Sub

  Public Function HasOriginalValue() As Boolean
    Dim bOriginal As Boolean = False
    If original IsNot Nothing Then
      bOriginal = True
    End If
    Return bOriginal
  End Function

  Public Function GetOriginalValue(ByVal originalType As System.Type) As Object
    If HasOriginalValue() Then
      Dim sXml As String = CStr(original)
      Dim fam As Object
      Using strr As New System.IO.StringReader(sXml)
        Dim SXO As New XmlSerializer(originalType)
        fam = SXO.Deserialize(strr)
        Return (fam)
      End Using
    Else
      Return (Nothing)
    End If
  End Function
End Class
</pre>
<p>Notice the use of System.Type, this allows me to pass in any data type and serialize it on the fly without having to have special code in my entity class. This makes it appropriate for any class I need to track changes in, even in the entity framework if I so desire.</p>
<p>Here is the top level entity class where I use it:</p>
<pre name="code" class="vb.net:nogutter">
Imports System.Xml.Serialization

Partial Class Family
  Inherits BaseBusiness

  Private Sub OnLoaded()
    OriginalValue = Me
  End Sub

  Public Property OriginalValue() As Family
    Get
      Return CType((Me.GetOriginalValue(GetType(Family))), Family)
    End Get
    Set(ByVal value As Family)
      Me.SetOriginalValue(value, GetType(Family))
    End Set
  End Property
End Class
</pre>
<p>That is the only code that will need to be in the entity class in order for it to work. The best part of this is when the data gets shipped back and forth, it&#8217;s always accessible as the original entity, not a serialized XML string.</p>
<p>This was just a quick test I did when investigating this stuff today. Eventually, I am going to try to minimize the code in both classes some more and see if I can even strip out the XML Serialization to string and just store it as binary data. </p>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2009/03/02/linq-to-sql-in-web-services/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wix</title>
		<link>http://thecodemonk.com/2009/01/09/wix/</link>
		<comments>http://thecodemonk.com/2009/01/09/wix/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 22:02:05 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[Windows Deployment]]></category>
		<category><![CDATA[Wix]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[setup]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/2009/01/09/wix/</guid>
		<description><![CDATA[In finally get CruiseControl.Net set up to not only automate our build process, but notify us of any breaking changes on checkin, I discovered some issues in using the standard setup and deployment projects. Not wanting to spend a lot of time on it, I decided to look into Wix and see how it could [...]]]></description>
			<content:encoded><![CDATA[<p>In finally get CruiseControl.Net set up to not only automate our build process, but notify us of any breaking changes on checkin, I discovered some issues in using the standard setup and deployment projects. Not wanting to spend a lot of time on it, I decided to look into Wix and see how it could help me streamline things.</p>
<p>It turns out Wix is a whole lot more work. Instead of a simple point and click interface, I&#8217;m presented with hand editing the XML file. Boo.</p>
<p>There are a few decent open source projects to give me a GUI interface so I can get my point and click back, but they turned out to either be for Wix 2 or they had some serious bugs in them.</p>
<p>In the end I used Dark to script my MSI file. While this worked out ok, Wix 3 wouldn&#8217;t compile the script without me making some changes. I dug through the script it created and I started to wonder how I was going to automate this. The trick is really not to automate it. The trick is to set up your script once and then leave it alone. Modifications are only made when things change in your build. That&#8217;s fine, but what about setting it up for the first time? You have to create a GUID for each component (read, every file if you want the files updateable) that gets installed. This can be time consuming if you have quite a few ancilary files that need to be shipped with the release.</p>
<p>Well, I automated that part. I created myself a small console application that will take a folder and a output file name as arguments. The program will traverse this folder and create an include script. It treats every file, directory, and directory of files as individual components. </p>
<p>In case anyone wants to do this but doesn&#8217;t want to take the time to write all the code, here it is.</p>
<pre name="code" class="csharp:nogutter">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Reflection;

namespace CreateIncludeScript
{
    class Program
    {
        static int Main(string[] args)
        {
            if (args.Length < 2 || args.Length > 2)
            {
                return (-1);
            }
            string folder = args[0];
            string outputfile = args[1];
            XmlDocument xmlDoc = new XmlDocument();
            XmlNode root = xmlDoc.AppendChild(xmlDoc.CreateElement("Include", "http://schemas.microsoft.com/wix/2006/wi"));

            XmlNode dir = root.AppendChild(xmlDoc.CreateElement("Directory", "http://schemas.microsoft.com/wix/2006/wi"));
            SetAttr(xmlDoc, dir, "Id", "TARGETDIR");
            SetAttr(xmlDoc, dir, "Name", "SourceDir");

            ProcessDirectory(xmlDoc, dir, folder);

            XmlNode feat = root.AppendChild(xmlDoc.CreateElement("Feature", "http://schemas.microsoft.com/wix/2006/wi"));
            SetAttr(xmlDoc, feat, "Id", "DefaultFeature");
            SetAttr(xmlDoc, feat, "Level", "1");
            SetAttr(xmlDoc, feat, "ConfigurableDirectory", "TARGETDIR");
            ProcessFeatures(xmlDoc, feat, dir);

            xmlDoc.Save(outputfile);
            return (0);
        }

        static void SetAttr(XmlDocument doc, XmlNode node, string name, string value)
        {
            XmlAttribute attr = node.Attributes.Append(doc.CreateAttribute(name));
            attr.Value = value;
        }

        static void ProcessDirectory(XmlDocument xmlDoc, XmlNode target, string directory)
        {
            string[] files = Directory.GetFiles(directory);
            string[] dirs = Directory.GetDirectories(directory);

            foreach (string file in files)
            {
                FileInfo finfo = new FileInfo(file);

                XmlNode comp = target.AppendChild(xmlDoc.CreateElement("Component", "http://schemas.microsoft.com/wix/2006/wi"));
                string guid = System.Guid.NewGuid().ToString().ToUpper();
                string id = "C_" + guid.Replace("-", "");
                SetAttr(xmlDoc, comp, "Id", id);
                SetAttr(xmlDoc, comp, "Guid", "{" + guid + "}");

                XmlNode fnode = comp.AppendChild(xmlDoc.CreateElement("File", "http://schemas.microsoft.com/wix/2006/wi"));
                SetAttr(xmlDoc, fnode, "Id", "F_" + guid.Replace("-",""));
                SetAttr(xmlDoc, fnode, "Name", finfo.Name);
                SetAttr(xmlDoc, fnode, "KeyPath", "yes");
                SetAttr(xmlDoc, fnode, "DiskId", "1");
                SetAttr(xmlDoc, fnode, "Source", finfo.FullName);

                if (finfo.Extension.ToLower() == ".dll" || finfo.Extension.ToLower() == ".exe")
                {
                    if (IsDotNetAssembly(finfo.FullName))
                    {
                        SetAttr(xmlDoc, fnode, "Assembly", ".net");
                        SetAttr(xmlDoc, fnode, "AssemblyManifest", "F_" + guid.Replace("-", ""));
                        SetAttr(xmlDoc, fnode, "AssemblyApplication", "F_" + guid.Replace("-", ""));
                    }
                }
            }

            foreach (string dir in dirs)
            {
                DirectoryInfo dinfo = new DirectoryInfo(dir);

                XmlNode dnode = target.AppendChild(xmlDoc.CreateElement("Directory", "http://schemas.microsoft.com/wix/2006/wi"));
                SetAttr(xmlDoc, dnode, "Id", dinfo.Name.Replace("-",""));
                SetAttr(xmlDoc, dnode, "Name", dinfo.Name);

                ProcessDirectory(xmlDoc, dnode, dinfo.FullName);
            }
        }

        static void ProcessFeatures(XmlDocument xmlDoc, XmlNode target, XmlNode root)
        {
            XmlNamespaceManager xmlmgr = new XmlNamespaceManager(xmlDoc.NameTable);
            xmlmgr.AddNamespace("wi", "http://schemas.microsoft.com/wix/2006/wi");
            XmlNodeList comps = root.SelectNodes("descendant::wi:Component", xmlmgr);

            foreach (XmlNode node in comps)
            {
                XmlNode compfeat = target.AppendChild(xmlDoc.CreateElement("ComponentRef", "http://schemas.microsoft.com/wix/2006/wi"));
                SetAttr(xmlDoc, compfeat, "Id", node.Attributes.GetNamedItem("Id").Value);
                XmlNode file = node.SelectSingleNode("wi:File", xmlmgr);
                if (file.Attributes.GetNamedItem("Assembly") != null)
                {
                    SetAttr(xmlDoc, compfeat, "Primary", "yes");
                }
            }
        }

        static bool IsDotNetAssembly(string fileName)
        {
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                try
                {
                    using (BinaryReader binReader = new BinaryReader(fs))
                    {
                        try
                        {
                            fs.Position = 0x3C; //PE Header start offset
                            uint headerOffset = binReader.ReadUInt32();
                                                         fs.Position = headerOffset + 0x18;
                            UInt16 magicNumber = binReader.ReadUInt16();
                                                         int dictionaryOffset;
                            switch (magicNumber)
                            {
                                case 0x010B: dictionaryOffset = 0x60; break;
                                case 0x020B: dictionaryOffset = 0x70; break;
                                default:
                                    throw new Exception("Invalid Image Format");
                            }

                            //position to RVA 15
                            fs.Position = headerOffset + 0x18 + dictionaryOffset + 0x70;

                            //Read the value
                            uint rva15value = binReader.ReadUInt32();
                            return (rva15value != 0);
                        }
                        finally
                        {
                            binReader.Close();
                        }
                    }
                }
                finally
                {
                    fs.Close();
                }
            }
        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2009/01/09/wix/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TableAdapter Connection Strings</title>
		<link>http://thecodemonk.com/2008/02/18/tableadapter-connection-strings/</link>
		<comments>http://thecodemonk.com/2008/02/18/tableadapter-connection-strings/#comments</comments>
		<pubDate>Mon, 18 Feb 2008 14:52:07 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[VB.Net]]></category>
		<category><![CDATA[app.config]]></category>
		<category><![CDATA[connection strings]]></category>
		<category><![CDATA[dataset]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[TableAdapter]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/2008/02/18/tableadapter-connection-strings/</guid>
		<description><![CDATA[* 7/29/2010 Update &#8211; I have uploaded a sample project here for those of you still struggling with this. It includes C# and VB.Net projects. Enjoy! I don&#8217;t know how a lot of people handle it, but one thing that always bugged me about table adapters and datasets is the way it handles it&#8217;s connection [...]]]></description>
			<content:encoded><![CDATA[<p>* 7/29/2010 Update &#8211; I have uploaded a sample project <a href="http://thecodemonk.com/2010/07/29/global-application-settings-override-now-with-examples/">here</a> for those of you still struggling with this. It includes C# and VB.Net projects. Enjoy!</p>
<p>I don&#8217;t know how a lot of people handle it, but one thing that always bugged me about table adapters and datasets is the way it handles it&#8217;s connection strings. It starts out innocent enough. A new dataset is created with it&#8217;s associated table adapter. The connection string is saved to the application settings file and that property is saved in the dataset. Running it on the development machine (or on the same network) is no big deal and just works. But what if you send that application to someone else that has their own SQL Server? </p>
<p>Did anyone at Microsoft actually use this scenario in a production environment? What were they thinking?</p>
<p>In order to run that in a production environment you have to set the connection string in the app.config file. While this may be fine for some people, what about the people like me that do not want my users to access that database? I don&#8217;t want them to have that username and password&#8230; While the chances of a normal user loading SQL Server Management Studio and logging in are slim, it&#8217;s still possible and it&#8217;s definitely possible if a user purposely wants to get out of having to do work that day.</p>
<p>What are the options? Well, one option is to use the encryption to encrypt the settings in app.config. For me, this option is not ideal. Reports of those settings getting corrupted are quite high, plus you have to deal with the loading and saving of those settings, which isn&#8217;t all that easy to do.</p>
<p>The other option is to take the route I was taking for a while&#8230; I had a function that would build me a connection string. Then I could: TableAdapter.Connection.ConnectionString = myLibrary.ConnectionStringFunction()</p>
<p>This was great, until that day came where I was in a hurry and added a few more tables to a form but forgot to set the ConnectionStrings. Whoops.</p>
<p>So I needed a solution that would stop me from having to set those ConnectionString properties, keep my connection string out of the app.config, and be easy to use (i.e. Just Works).</p>
<p>I started out by just giving all my datasets the same connection string. Then on application startup, I tried to change that one application setting. Hmm.. It seems those ConnectionString properties are set to friend and are read only.</p>
<p>Upon further investigation, it seems that there are some events that fire, such as SettingsLoaded. This event fires when the app.config is read and all the settings are loaded. When this event fires, it fires inside the MySettings class. This should allow that property to be changed.</p>
<pre name="code" class="vb.net:nogutter">
    Private Sub MySettings_SettingsLoaded(ByVal sender As Object, ByVal e As System.Configuration.SettingsLoadedEventArgs) Handles Me.SettingsLoaded
      Me.Item("MyAppConnectionString") = MyLibrary.BuildConnectionString()
    End Sub
</pre>
<p>This will set the MyAppConnectionString setting to the proper connection string. Now, all table adapters will have an up to date connection string.</p>
<p>So what happens if you want to change the connection string later while the application is still running? Well, there is no way to do that. So it&#8217;s time to come up with a way to trick it into updating that property.</p>
<p>In looking at the MySettings class, there is another event called PropertyChanged. We can use this event if we create another setting that can be updated anywhere in the application. First, we create a new string setting that has a User scope (I called mine ConnectionString). This will allow the application to update the setting at any time.</p>
<p>Next, we need to create a function that will update that property with our connection string.</p>
<pre name="code" class="vb.net:nogutter">
  Public Shared Sub ChangeConnectionString()
    My.Settings.ConnectionString = BuildConnectionString()
  End Sub
</pre>
<p>Now we can change the events in the MySettings class to look like this.</p>
<pre name="code" class="vb.net:nogutter">
    Private Sub MySettings_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles Me.PropertyChanged
      If e.PropertyName = "ConnectionString" Then
        Me.Item("MyAppConnectionString") = My.Settings.ConnectionString
      End If
    End Sub

    Private Sub MySettings_SettingsLoaded(ByVal sender As Object, ByVal e As System.Configuration.SettingsLoadedEventArgs) Handles Me.SettingsLoaded
      MyLibrary.ChangeConnectionString()
    End Sub
  End Class
</pre>
<p>Now, every time that ChangeConnectionString() is called, the MyAppConnectionString will be updated. The ChangeConnectionString procedure can be changed so that it can accept a string parameter that is the actual connection string. Then you can build a Connection String anywhere and just pass it to that procedure. </p>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2008/02/18/tableadapter-connection-strings/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Disposing of memory leaks.</title>
		<link>http://thecodemonk.com/2008/01/03/disposing-of-memory-leaks/</link>
		<comments>http://thecodemonk.com/2008/01/03/disposing-of-memory-leaks/#comments</comments>
		<pubDate>Thu, 03 Jan 2008 19:06:12 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[VB.Net]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/2008/01/03/disposing-of-memory-leaks/</guid>
		<description><![CDATA[One of the biggest causes of memory leaks that I find from time to time is from forgetting to dispose of some SQLConnection object. Even if the connection is closed, the SQLConnection object seems to stay alive forever, which keeps any form objects alive as well. This happens in VB a lot if you forget [...]]]></description>
			<content:encoded><![CDATA[<p>One of the biggest causes of memory leaks that I find from time to time is from forgetting to dispose of some SQLConnection object. Even if the connection is closed, the SQLConnection object seems to stay alive forever, which keeps any form objects alive as well.</p>
<p>This happens in VB a lot if you forget to call the Dispose method of the SQLConnection object or if you don&#8217;t use the Using keyword. While cleaning up code, the best way to get in the habit of doing it, seems to be changing everything into a Using statement so I get in the habit of using it&#8230;<br />
Instead of:</p>
<pre name="code" class="vb.net:nogutter">
    Dim myCommand As New SqlClient.SqlCommand("Select Count(*) from MyTable")
    Dim myConnection As New SqlClient.SqlConnection(ConnectionString)
    myCommand.Connection = myConnection
    myConnection.Open()
    Dim iCount As Integer = CInt(myCommand.ExecuteScalar())
    myConnection.Close()
    myConnection.Dispose()
    myCommand.Dispose()
</pre>
<p>Do this:</p>
<pre name="code" class="vb.net:nogutter">
    Using myCommand As New SqlClient.SqlCommand("Select Count(*) from MyTable")
      Using myConnection As New SqlClient.SqlConnection(ConnectionString)
        myCommand.Connection = myConnection
        myConnection.Open()
        Dim iCount As Integer = CInt(myCommand.ExecuteScalar())
      End Using
    End Using
</pre>
<p>Since the IDisposable interface on the SQLConnection object will automatically close open connections, there is no need to close it&#8230; However, if you decide to do this:</p>
<pre name="code" class="vb.net:nogutter">
    Using myCommand As New SqlClient.SqlCommand("Select Count(*) from MyTable" _
    , New SqlClient.SqlConnection(ConnectionString))
      myCommand.Connection.Open()
      Dim iCount As Integer = CInt(myCommand.ExecuteScalar())
      myCommand.Connection.Close()
    End Using
</pre>
<p>Make sure you close the connection first&#8230; Although, I don&#8217;t recommend doing it that way, because the IDisposable interface of the SQLCommand object does not call the IDisposable interface of the SqlConnection object that it holds. I&#8217;ve read that all the SqlConnection object&#8217;s IDisposable interface does is close an open connection, I wouldn&#8217;t trust that completely and dispose of it properly.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2008/01/03/disposing-of-memory-leaks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Installer &#8211; SQL Server Installation Issues and a Solution.</title>
		<link>http://thecodemonk.com/2007/10/25/windows-installer-sql-server-installation-issues-and-a-solution/</link>
		<comments>http://thecodemonk.com/2007/10/25/windows-installer-sql-server-installation-issues-and-a-solution/#comments</comments>
		<pubDate>Thu, 25 Oct 2007 22:20:23 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[VB.Net]]></category>
		<category><![CDATA[Windows Deployment]]></category>
		<category><![CDATA[Windows Development]]></category>
		<category><![CDATA[Installer Class]]></category>
		<category><![CDATA[Setup and Deployment]]></category>
		<category><![CDATA[SQL Server Express]]></category>
		<category><![CDATA[Windows Installer]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/2007/10/25/windows-installer-sql-server-installation-issues-and-a-solution/</guid>
		<description><![CDATA[Here is the problem in a nutshell: You have a custom client application that uses SQL Server 2005 Express. The server installation is a little bit to be desired. First, you have to install SQL Server Express, then you have to configure the options (unless you did command line options), then you have to execute [...]]]></description>
			<content:encoded><![CDATA[<p>Here is the problem in a nutshell: You have a custom client application that uses SQL Server 2005 Express. The server installation is a little bit to be desired. First, you have to install SQL Server Express, then you have to configure the options (unless you did command line options), then you have to execute the scripts to create your database, tables, and possibly populate it with some data. Or conversely, execute scripts or install and use the management console to attach a database. Messy, at best.</p>
<p>So what if you want to have a single installation program that will install all the prerequisites (.Net), then install SQL Server 2005 with your custom options (instance name for example), and then have it execute scripts and fill it with data? After working at it for hours, I came to the conclusion that you could be out of luck. Until I did some reconfiguring.</p>
<p>First things first, you need to get SQL Server Express to install properly. I struggled with this for a while, until I had the bright idea of using a bootstrapper&#8230; But can&#8217;t we use the one that comes with the Visual Studio Package and Deployment Wizard? Yes you can! </p>
<p>Go into your Visual Studio 8 folder and find the SDK/v2.0/Bootstrapper/Packages folder. Make a copy of the SqlExpress folder and name it something like, MyAppSqlExpress. Inside that folder, there is a product XML file. Edit that product.xml file and change the product code. Mine was Microsoft.Sql.Server.Express.1.0 and I changed it to MyAppName.Microsoft.Sql.Server.Express.1.0 … Just change the MyAppName to the app name of the product it goes with. You will also see a En folder for the English installation. The package.xml file is the one you want to edit in that folder. The first item to edit, is the arguments line. This passes arguments to the SqlExpr32.exe file (the setup for Sql Express). The arguments are the same as any other SQL Express install&#8230; So change it to be something like this:</p>
<pre name="code" class="xml:nogutter">
Arguments='-q /norebootchk /qb reboot=ReallySuppress addlocal=all
  INSTANCENAME=MyApp SECURITYMODE=SQL SAPWD=MyStrongPassword
  DISABLENETWORKPROTOCOLS=0 SQLAUTOSTART=1'
</pre>
<p>This will do a silent installation of SQL Server Express using all protocols, a custom instance name (MyApp), turn on the SQL security mode and specify a strong SA password. </p>
<p>Next, there is the strings block at the bottom. Edit the StringName &#8220;DisplayName&#8221; to look like this:</p>
<pre name="code" class="xml:nogutter">
<String Name="DisplayName">MyApp SQL Server 2005 Express Edition</String>
</pre>
<p>Save it, and go into your setup and deployment project you created, go to the project properties, then to the prerequisites, and in the list you should now see your custom install of SQL Server Express!</p>
<p>This does work, I just tested it out today.</p>
<p>So that solves problem #1. What about the problem of executing scripts? That seems to be the easy part&#8230; From my earlier <a href="http://thecodemonk.com/2007/10/23/microsoftsqlserversmo-where-have-you-been-all-my-life/">post</a> you can incorporate that code into a custom action.</p>
<p>Create a new project, and select Installer Class from the templates. This creates a new installer class for you to augment.</p>
<pre name="code" class="vb.net:nogutter">
  Private Sub ExecuteSQL(ByVal SQL As String, _
    ByVal ConnectionString As String)

    Dim srv As New Server(New ServerConnection( _
    New SqlClient.SqlConnection(ConnectionString)))

    srv.ConnectionContext.ExecuteNonQuery(SQL)
    srv.ConnectionContext.Disconnect()
  End Sub

  Private Sub BulkLoad(ByVal ConnectionString As String, _
    ByVal TableName As String)

    Dim bulk As New SqlClient.SqlBulkCopy(ConnectionString, _
    SqlClient.SqlBulkCopyOptions.KeepIdentity)

    Dim ds As New DataSet
    Dim path As String = My.Application.Info.DirectoryPath
    ds.ReadXmlSchema(path &#038; "\" &#038; TableName &#038; ".xsd")
    ds.ReadXml(path &#038; "\" &#038; TableName &#038; ".xml")
    bulk.BulkCopyTimeout = 0
    bulk.DestinationTableName = TableName
    bulk.WriteToServer(ds.Tables(TableName))
    bulk.Close()
  End Sub

  Public Overrides Sub Install(ByVal stateSaver As _
    System.Collections.IDictionary)

    MyBase.Install(stateSaver)
    Dim ConnBuilder As New SqlClient.SqlConnectionStringBuilder()
    ConnBuilder.UserID = "sa"
    ConnBuilder.Password = "MyStrongPassword"
    ConnBuilder.DataSource = "localhost\MyApp"
    ConnBuilder.InitialCatalog = "master"
    ExecuteSQL(My.Resources.CreateDatabaseSQL, _
    ConnBuilder.ConnectionString())

    ConnBuilder.InitialCatalog = "MyDatabase"
    BulkLoad(ConnBuilder.ConnectionString(), "MyTable")
  End Sub
</pre>
<p>In this example, I just stored the data files (an XML data file and an XSD schema file) in the setup project, which gets installed along with the custom installer DLL. The create database SQL stuff was all saved as a store resource in the installer class project. I did this so that some of the structure was hidden, which may or may not be an issue for others.</p>
<p>Now, add the custom action to a setup project and you are finished!</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2007/10/25/windows-installer-sql-server-installation-issues-and-a-solution/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Microsoft.SqlServer.Smo, where have you been all my life?</title>
		<link>http://thecodemonk.com/2007/10/23/microsoftsqlserversmo-where-have-you-been-all-my-life/</link>
		<comments>http://thecodemonk.com/2007/10/23/microsoftsqlserversmo-where-have-you-been-all-my-life/#comments</comments>
		<pubDate>Tue, 23 Oct 2007 21:42:44 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[VB.Net]]></category>
		<category><![CDATA[Export]]></category>
		<category><![CDATA[Import]]></category>
		<category><![CDATA[microsoft.sqlserver.smo]]></category>
		<category><![CDATA[SMO]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[SqlBulkCopy]]></category>
		<category><![CDATA[SqlClient]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/2007/10/23/microsoftsqlserversmo-where-have-you-been-all-my-life/</guid>
		<description><![CDATA[I have had a need, for quite some time, to have a comprehensive SQL Server tool where I could execute scripts, import/export tables, and generally just run a few queries. In the past, I have been using the free SQL Management Studio Express edition, which works just fine. The problem with this utility, is using [...]]]></description>
			<content:encoded><![CDATA[<p>I have had a need, for quite some time, to have a comprehensive SQL Server tool where I could execute scripts, import/export tables, and generally just run a few queries. In the past, I have been using the free SQL Management Studio Express edition, which works just fine. The problem with this utility, is using it at customer installations. The install requires administrator privileges, which work for most places, but make it impossible to install at others. So, the need to have a small utility that I can run along side my application is pretty great.</p>
<p>I started out just using the SQLClient name space. While it worked well for simple queries, trying to run a comprehensive database update script just killed it. While it would probably work, I would have to parse the script first, stripping out all the GO statements and breaking them up into separate scripts. That worked fine until I ran into the first transaction&#8230; Not good either, apparently.</p>
<p>Feeling dead in the water, I did some searching and came across a name space I had not known existed. It&#8217;s Microsoft.SqlServer.Smo. It is the replacement for Nmo and has quite a few really nice features.</p>
<p>One such feature is the ability to use .ExecuteNonQuery() without having to break apart or parse existing update scripts, including ones with built in transaction support!</p>
<p>It&#8217;s pretty simple to use and combined with the SqlClient name space, I was able to create a pretty comprehensive solution for my needs.</p>

<div class="wp_syntax"><div class="code"><pre class="vbnet" style="font-family:monospace;"><span style="color: #0600FF;">Imports</span> Microsoft.<span style="color: #0000FF;">SqlServer</span>.<span style="color: #0000FF;">Management</span>.<span style="color: #0000FF;">Smo</span>
<span style="color: #0600FF;">Imports</span> Microsoft.<span style="color: #0000FF;">SqlServer</span>.<span style="color: #0000FF;">Management</span>.<span style="color: #0000FF;">Common</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="vbnet" style="font-family:monospace;"><span style="color: #0600FF;">Dim</span> conn <span style="color: #FF8000;">As</span> <span style="color: #FF8000;">New</span> ServerConnection<span style="color: #000000;">&#40;</span>SQLAuthInfo.<span style="color: #0000FF;">GetSQLConnection</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
<span style="color: #0600FF;">Dim</span> srv <span style="color: #FF8000;">As</span> <span style="color: #FF8000;">New</span> Server<span style="color: #000000;">&#40;</span>conn<span style="color: #000000;">&#41;</span>
dropdown.<span style="color: #0000FF;">Items</span>.<span style="color: #0000FF;">Clear</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #FF8000;">For</span> i <span style="color: #FF8000;">As</span> <span style="color: #FF0000;">Integer</span> <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span> <span style="color: #FF8000;">To</span> srv.<span style="color: #0000FF;">Databases</span>.<span style="color: #0000FF;">Count</span> <span style="color: #008000;">-</span> <span style="color: #FF0000;">1</span>
  dropdown.<span style="color: #0000FF;">Items</span>.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>srv.<span style="color: #0000FF;">Databases</span>.<span style="color: #0000FF;">Item</span><span style="color: #000000;">&#40;</span>i<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Name</span><span style="color: #000000;">&#41;</span>
<span style="color: #FF8000;">Next</span>
conn.<span style="color: #0000FF;">Disconnect</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></pre></div></div>

<p>That&#8217;s as simple as it gets to iterate through all the databases on the server. The SQLAuthInfo is a class I designed that will just create a SqlConnection object based on preset values.</p>
<p>Need to execute a script? No problem&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="vbnet" style="font-family:monospace;"><span style="color: #0600FF;">Dim</span> conn <span style="color: #FF8000;">As</span> <span style="color: #FF8000;">New</span> ServerConnection<span style="color: #000000;">&#40;</span>SQLAuthInfo.<span style="color: #0000FF;">GetSQLConnection</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
<span style="color: #0600FF;">Dim</span> srv <span style="color: #FF8000;">As</span> <span style="color: #FF8000;">New</span> Server<span style="color: #000000;">&#40;</span>conn<span style="color: #000000;">&#41;</span>
<span style="color: #0600FF;">Dim</span> cmd <span style="color: #FF8000;">As</span> <span style="color: #FF8000;">String</span> <span style="color: #008000;">=</span> ScriptMemoEdit.<span style="color: #0000FF;">Text</span>
&nbsp;
srv.<span style="color: #0000FF;">ConnectionContext</span>.<span style="color: #0000FF;">ExecuteNonQuery</span><span style="color: #000000;">&#40;</span>cmd, ExecutionTypes.<span style="color: #0000FF;">ContinueOnError</span><span style="color: #000000;">&#41;</span>
&nbsp;
conn.<span style="color: #0000FF;">Disconnect</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></pre></div></div>

<p>It didn&#8217;t take me long to use many of the features&#8230; For import and export, I just used a select query to get all the data from one table and saved it into a dataset. Then I used the dataset&#8217;s WriteXML and WriteXMLSchema functions to save it to files. Then with the import function, I just read in the schema and data into a dataset and used the SqlBulkCopy object to save it to the target database table. Pretty easy stuff. This also gives me some new options for our server installation program I need to fix (i.e. create).</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2007/10/23/microsoftsqlserversmo-where-have-you-been-all-my-life/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>XML Parsing in .Net</title>
		<link>http://thecodemonk.com/2007/10/07/xml-parsing-in-net/</link>
		<comments>http://thecodemonk.com/2007/10/07/xml-parsing-in-net/#comments</comments>
		<pubDate>Sun, 07 Oct 2007 22:52:59 +0000</pubDate>
		<dc:creator>TheCodeMonk</dc:creator>
				<category><![CDATA[.Net Code]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[dotNet]]></category>
		<category><![CDATA[XmlDocument]]></category>
		<category><![CDATA[XmlNode]]></category>
		<category><![CDATA[XmlNodeList]]></category>

		<guid isPermaLink="false">http://thecodemonk.com/2007/10/07/xml-parsing-in-net/</guid>
		<description><![CDATA[While working on wxDesktop, which was my first attempt at parsing data from an XML source, I tried to find the best way to read and parse out certain data from an XML document. Before I even really got to the meat of it, I had just had it in my head that I was [...]]]></description>
			<content:encoded><![CDATA[<p>While working on <a href="http://codeplex.com/wxdesktop" title="wxDesktop" target="_blank">wxDesktop</a>, which was my first attempt at parsing data from an XML source, I tried to find the best way to read and parse out certain data from an XML document. Before I even really got to the meat of it, I had just had it in  my head that I was going to use a DataSet. Why would I do that, you ask? Well, when that&#8217;s all you know how to do, that&#8217;s usually what you go with. I have never dealt with the XML namespace, mostly because I haven&#8217;t had to. Now that I have, I know I will never use the crappy DataSet class for this ever again.</p>
<p>Take the following XML document.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;test<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;data<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Sample set name<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>4<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>6<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>20<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>54<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>10<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>19<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>17<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>15<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/data<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;otherdata<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Second Sample set name<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>10<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>12<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>14<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>4<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>6<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>8<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>16<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>18<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>20<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/otherdata<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/test<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>When you read this document in using the DataSet.ReadXML function like this:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> readXMLDataSet<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> FileName<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    DataSet ds <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> DataSet<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    ds.<span style="color: #0000FF;">ReadXml</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;test.xml&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>The DataSet will contain 3 tables. It will contain the tables called data, value, and otherdata. Not really what you would think would be in there&#8230; It sort of makes sense, except for the fact that all value columns are then lumped into one table and then linked via an ID. While this isn&#8217;t too bad, and it would probably be usable, it&#8217;s not ideal, nor fun to use.</p>
<p>Now take this piece of code:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> readXMLNodes<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> FileName<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #000000;">System.<span style="color: #0000FF;">Xml</span></span>.<span style="color: #0000FF;">XmlDocument</span> xd <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> <span style="color: #000000;">System.<span style="color: #0000FF;">Xml</span></span>.<span style="color: #0000FF;">XmlDocument</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    xd.<span style="color: #0000FF;">Load</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;test.xml&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #000000;">System.<span style="color: #0000FF;">Xml</span></span>.<span style="color: #0000FF;">XmlNode</span> node <span style="color: #008000;">=</span> xd.<span style="color: #0000FF;">SelectSingleNode</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;/test/data&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">System.<span style="color: #0000FF;">Xml</span></span>.<span style="color: #0000FF;">XmlNode</span> nameNode <span style="color: #008000;">=</span> node.<span style="color: #0000FF;">SelectSingleNode</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;name&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">System.<span style="color: #0000FF;">Xml</span></span>.<span style="color: #0000FF;">XmlNodeList</span> valueList <span style="color: #008000;">=</span> node.<span style="color: #0000FF;">SelectNodes</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;value&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>This uses the XmlDocument, XmlNode, and XmlNodeList classes and allows you to easily parse out certain parts of the XML document to find exactly what you need. nameNode.InnerText will show &#8220;Sample set name&#8221; and the valueList will contain every value in the data section. So valueList[0].InnerText will be 5.</p>
<p>Now,  you could shove this information into a correctly laid out DataSet, but why bother? Now I see the value in creating a class just to parse certain XML documents. You can set the class up so that it will match the structure as it should be logically laid out and use the class to just access the nodes as needed through functions.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodemonk.com/2007/10/07/xml-parsing-in-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
