Commits

Sky Sanders  committed 073968e

polishing form ui

  • Participants
  • Parent commits e3c3937

Comments (0)

Files changed (35)

File trunk/soddi/ClassDiagram1.cd

+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1">
+  <Class Name="Salient.StackExchange.Import.Configuration.Configuration" Collapsed="true">
+    <Position X="21.5" Y="0.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>CAAAAAgAQkIkBACGAAAAACAABAAAAEAQAAAAAABAgAA=</HashCode>
+      <FileName>Configuration\Configuration.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Configuration.DbProviderInfo" Collapsed="true">
+    <Position X="14.5" Y="1.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAABCAAAAgAAAAIAAAAAQAAAAACAAAACAAAAAAAAA=</HashCode>
+      <FileName>Configuration\DbProviderInfo.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Configuration.DbProviders" Collapsed="true">
+    <Position X="16.25" Y="1.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAEAAAAAAA=</HashCode>
+      <FileName>Configuration\DbProviders.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Gui.FrmCmdLine" Collapsed="true">
+    <Position X="19.75" Y="1.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAACAAAAAAAACAAAACAAAAAAAAEAAAAAAAAAA=</HashCode>
+      <FileName>Gui\FrmCmdLine.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Gui.FrmUI" Collapsed="true">
+    <Position X="21.5" Y="1.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AQEAgAAQISIhAAACggCCggBCAAQJFRAAAAEAAYUkIIE=</HashCode>
+      <FileName>Gui\frmUI.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Gui.ListViewStyle" Collapsed="true">
+    <Position X="18" Y="2.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>EAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+      <FileName>Gui\ListViewStyle.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.BulkCopyBase" Collapsed="true">
+    <Position X="2.75" Y="6.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AQAAAAFAAAAgEAAAAAAQAAQAAAAAAAAAEAAAAAAAAAA=</HashCode>
+      <FileName>Loaders\BulkCopyBase.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.BulkCopyEventArgs" Collapsed="true">
+    <Position X="14.5" Y="0.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAACAAAAAAAAACAAAAAAAAQAAAAAAAAAAQAAIAAAAAA=</HashCode>
+      <FileName>Loaders\BulkCopyEventArgs.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.BulkCopyTask" Collapsed="true">
+    <Position X="16.25" Y="0.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AQACACDAAAAgggICAgBAaAQEAQAAAAAABACIBAAIAAA=</HashCode>
+      <FileName>Loaders\BulkCopyTask.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.BulkLoader" Collapsed="true">
+    <Position X="2.75" Y="3.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>BQAAABBAAgAAAAAAAEBAAAAAIAAAAEgAAAAAAAAAAAA=</HashCode>
+      <FileName>Loaders\BulkLoader.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.BulkLoadJob" Collapsed="true">
+    <Position X="18" Y="0.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AQgAACBAAAAgAAIAAgAAAAAAAAAIAAAAAAAIAAAAAAA=</HashCode>
+      <FileName>Loaders\BulkLoadJob.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.ImportTarget" Collapsed="true">
+    <Position X="14.5" Y="2.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAIEAAAAAAQEAAAAAAAAAAAAAAAAAAA=</HashCode>
+      <FileName>Loaders\ImportTarget.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.LoaderAttribute" Collapsed="true">
+    <Position X="19.75" Y="2.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+      <FileName>Loaders\LoaderAttribute.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.SoBase&lt;T&gt;" Collapsed="true">
+    <Position X="6.25" Y="0.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAQAAAAgAAAAAAAAAAAAEAAAAAAAgAEAAAAAAAA=</HashCode>
+      <FileName>Loaders\SoBase.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.TaskList" Collapsed="true">
+    <Position X="18" Y="3.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AQIAACBAAAAAAAIAAAAACAAAAAAAAAAAAAAABAAAAAA=</HashCode>
+      <FileName>Loaders\TaskList.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.JobList" Collapsed="true">
+    <Position X="16.25" Y="2.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AQIAACBAAAAAAAIAAAAACAAAAAAAAAAAAAAIBAAAAAA=</HashCode>
+      <FileName>Loaders\JobList.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Program" Collapsed="true">
+    <Position X="21.5" Y="2.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAABAAAAAA=</HashCode>
+      <FileName>Program.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.MsSql.MsSqlBulkCopy" Collapsed="true">
+    <Position X="5" Y="7.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAEAAAAgEAAAAAAQgAQAAAAAAAAAEAAAAAAAAAA=</HashCode>
+      <FileName>Loaders\MsSql\MsSqlBulkInserter.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.MsSql.MSSqlInserter" Collapsed="true">
+    <Position X="5" Y="4.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAABAAAAAIAAAAAgAAAAAAAAAAAA=</HashCode>
+      <FileName>Loaders\MsSql\MSSqlInserter.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.MySql.MySqlBulkInserter" Collapsed="true">
+    <Position X="0.5" Y="7.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAFAAEAAAgAAAAAAAAAAAAAAAAAAEAAAABAAAAA=</HashCode>
+      <FileName>Loaders\MySql\MySqlBulkInserter.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.MySql.MySqlInserter" Collapsed="true">
+    <Position X="0.5" Y="4.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAABAAAAAIAAAAAgAAAAAAAAAAAA=</HashCode>
+      <FileName>Loaders\MySql\MySqlInserter.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.SQLite.SQLiteBulkInserter" Collapsed="true">
+    <Position X="2.75" Y="7.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAFAAEAAAgAAAAAAAAAAAAAAAAAAEAAAABAAAAA=</HashCode>
+      <FileName>Loaders\SQLite\SQLiteBulkInserter.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Loaders.SQLite.SQLiteInserter" Collapsed="true">
+    <Position X="2.75" Y="4.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>ABAAAACEAAAAAAAgAABAEAgABAAAAAgAAAAAAAAABCA=</HashCode>
+      <FileName>Loaders\SQLite\SQLiteInserter.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Properties.Resources" Collapsed="true">
+    <Position X="14.5" Y="3.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAAABEAAAAQAABAQAAAAAAAAAAIA=</HashCode>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Properties.Settings" Collapsed="true">
+    <Position X="16.25" Y="3.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAgAAMAAAAAABAAAAAAEEAAAQQAA=</HashCode>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.Data.EnumerableDataReader" Collapsed="true">
+    <Position X="8.25" Y="4.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAIAAAAAQAAAAAAAAgAAAAAAAAAAAABQBAAAA=</HashCode>
+      <FileName>Salient.Data\EnumerableDataReader.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.Data.ObjectDataReader" Collapsed="true">
+    <Position X="8.25" Y="3.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>BACQAAggMCgAAAgBAAAABCYgAAJEAEQwIBQAAACApEA=</HashCode>
+      <FileName>Salient.Data\ObjectDataReader.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="Salient.Reflection.DynamicProperties" Collapsed="true">
+    <Position X="18" Y="1.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AiBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+      <FileName>Salient.Reflection\DynamicProperties.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.TableTypes.Badges" Collapsed="true">
+    <Position X="3" Y="1.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAACAAAAAAAAAAAAAAAAAAwAQAAAAAABAAAAAAAAAAA=</HashCode>
+      <FileName>TableTypes\Badges.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="Salient.StackExchange.Import.TableTypes.Comments" Collapsed="true">
+    <Position X="5.25" Y="1.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>QAACAAAAAAAAAAkAAAAAAAgAQAAAAAAAAAAACAAAAAA=</HashCode>
+      <FileName>TableTypes\Comments.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="Salient.StackExchange.Import.TableTypes.Posts" Collapsed="true">
+    <Position X="7.5" Y="1.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>QABCAAAAIIAABEgAAAABBBAQQAAEAEAEAgAAAAAAAAo=</HashCode>
+      <FileName>TableTypes\Posts.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="Salient.StackExchange.Import.TableTypes.PostTags" Collapsed="true">
+    <Position X="9.75" Y="1.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAgAAEAAAAAAAAAQAAAAAAAAAAAAAAAAAA=</HashCode>
+      <FileName>TableTypes\PostTags.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="Salient.StackExchange.Import.TableTypes.Users" Collapsed="true">
+    <Position X="12" Y="1.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>QgCCEAQAAAEAAAAAAEIAAACQSAAAAAAAAAAAACAAAAA=</HashCode>
+      <FileName>TableTypes\Users.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="Salient.StackExchange.Import.TableTypes.Votes" Collapsed="true">
+    <Position X="0.75" Y="1.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>QAACAAAAAAAAAIEAAAAAAAgAQAAAAAAAAAAEAAAAAAA=</HashCode>
+      <FileName>TableTypes\Votes.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Tools.Common" Collapsed="true">
+    <Position X="19.75" Y="0.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAIAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAA=</HashCode>
+      <FileName>Tools\Common.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="Salient.StackExchange.Import.Tools.TypeConverter" Collapsed="true">
+    <Position X="19.75" Y="3.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAEAAAAAAgAAAAAAAAAAAAIBAAAAAAAAAAAAAg=</HashCode>
+      <FileName>Tools\Common.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Interface Name="Salient.StackExchange.Import.Loaders.ISoBase" Collapsed="true">
+    <Position X="14.5" Y="4.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+      <FileName>Loaders\ISoBase.cs</FileName>
+    </TypeIdentifier>
+  </Interface>
+  <Enum Name="Salient.StackExchange.Import.Loaders.CopyEventType" Collapsed="true">
+    <Position X="14.5" Y="5.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAQIAAAAAAAACAAAAEAAgAAAAIAEAAAA=</HashCode>
+      <FileName>Loaders\CopyEventType.cs</FileName>
+    </TypeIdentifier>
+  </Enum>
+  <Font Name="Tahoma" Size="8.25" />
+</ClassDiagram>

File trunk/soddi/Configuration/Configuration.cs

 using System.Data.Common;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using System.Text.RegularExpressions;
 using Salient.StackExchange.Import.Loaders;
 using Salient.StackExchange.Import.TableTypes;
 {
     public class Configuration
     {
-        private const int DefaultBatchSize = 25000;
+        private const int DefaultBatchSize = 5000;
 
-        #region Enums
 
         [Flags]
         public enum ImportOptions
             FieldCount = 16
         }
 
-        #endregion
 
-        #region Fields
 
-        #endregion
 
-        #region Constructors
 
         public Configuration()
         {
             ParseArguments(args);
         }
 
-        #endregion
 
-        #region Properties
 
         public int BatchSize { get; set; }
 
 
         public List<ImportTarget> Targets { get; set; }
 
-        #endregion
 
-        #region Public Methods
 
         public Type[] GetAllTableTypes()
         {
 
 
                 string batch = BatchSize != DefaultBatchSize ? " batch:" + BatchSize : "";
-                string cmdLine = string.Format("source:\"{0}\" target:\"{1}\"{2}{3}{4}{5} {6}", Source,
+                string cmdLine = string.Format("{7} source:\"{0}\" target:\"{1}\"{2}{3}{4}{5} {6}", Source,
                                                csb.ConnectionString, batch, Indices ? " indices" : "",
-                                               FullText ? " fulltext" : "", Split ? " split" : "", targets);
+                                               FullText ? " fulltext" : "", Split ? " split" : "", targets, Path.GetFileName(Assembly.GetExecutingAssembly().Location));
                 return cmdLine;
             }
             else
             {
                 return
-                    string.Format("Provider: {0}\r\nSource  : {1}\r\nTarget  : {2}\r\nOptions : {3}", Provider, Source,
-                                  Target, Options);
+                    string.Format("Source  : {0}\r\nTarget  : {1}\r\nOptions : {2}", Source, Target, Options);
             }
         }
 
-        #endregion
 
-        #region Private Methods
 
         public static List<string> GetAllSites(string source)
         {
                 Match match = dirRx.Match(Path.GetFileName(dir));
                 if (match.Success)
                 {
-                    sites.Add(match.Groups[2].Value.ToLowerInvariant());
+                    sites.Add(match.Groups[2].Value);
                 }
             }
             return sites;
 
             string siteId = segments[0];
 
-            string siteSchema = segments.Length > 1 ? segments[1].ToLowerInvariant() : siteId.ToLowerInvariant();
+            string siteSchema = segments.Length > 1 ? segments[1] : siteId;
 
             string[] dirs = Directory.GetDirectories(source, "* " + siteId);
 
             for (int i = 0; i < args.Length; i++)
             {
                 string value = null;
-                string arg = args[i].Trim(); //.ToLowerInvariant();
+                string arg = args[i].Trim(); 
                 if (arg.IndexOf(":") > -1)
                 {
                     value = arg.Substring(arg.IndexOf(":") + 1).Trim('"', '\'');
                         Options = Options | ImportOptions.GUI;
                         break;
                     default:
-                        unparsed.Add(args[i].Trim().ToLowerInvariant());
+                        unparsed.Add(args[i].Trim());
                         break;
                 }
             }
             BatchSize = DefaultBatchSize;
         }
 
-        #endregion
     }
 }

File trunk/soddi/GPL.TXT

+        GNU GENERAL PUBLIC LICENSE
+           Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+          Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+        GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+          NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.

File trunk/soddi/Gui/FrmAbout.Designer.cs

+namespace Salient.StackExchange.Import.Gui
+{
+    partial class FrmAbout
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.richTextBox1 = new System.Windows.Forms.RichTextBox();
+            this.SuspendLayout();
+            // 
+            // richTextBox1
+            // 
+            this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.richTextBox1.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.richTextBox1.Location = new System.Drawing.Point(0, 0);
+            this.richTextBox1.Name = "richTextBox1";
+            this.richTextBox1.ReadOnly = true;
+            this.richTextBox1.Size = new System.Drawing.Size(792, 573);
+            this.richTextBox1.TabIndex = 0;
+            this.richTextBox1.Text = "";
+            this.richTextBox1.WordWrap = false;
+            // 
+            // FrmAbout
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(792, 573);
+            this.Controls.Add(this.richTextBox1);
+            this.Name = "FrmAbout";
+            this.Text = "About SODDI";
+            this.Load += new System.EventHandler(this.FrmAbout_Load);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.RichTextBox richTextBox1;
+    }
+}

File trunk/soddi/Gui/FrmAbout.cs

+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using Salient.StackExchange.Import.Tools;
+
+namespace Salient.StackExchange.Import.Gui
+{
+    public partial class FrmAbout : Form
+    {
+        public FrmAbout()
+        {
+            InitializeComponent();
+        }
+
+        private void FrmAbout_Load(object sender, EventArgs e)
+        {
+            richTextBox1.Text = Common.GetTextResource(@"README.txt", Assembly.GetExecutingAssembly());
+            
+        }
+    }
+}

File trunk/soddi/Gui/FrmAbout.resx

+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

File trunk/soddi/Gui/FrmCmdLine.cs

 
 #region
 
+using System.IO;
+using System.Reflection;
 using System.Windows.Forms;
 
 #endregion

File trunk/soddi/Gui/frmUI.Designer.cs

             System.Windows.Forms.Label targetLabel;
             System.Windows.Forms.Label label1;
             System.Windows.Forms.Label label2;
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmUI));
             this.BatchSizeNumericUpDown = new System.Windows.Forms.NumericUpDown();
             this.fullTextCheckBox = new System.Windows.Forms.CheckBox();
             this.indicesCheckBox = new System.Windows.Forms.CheckBox();
             this.splitCheckBox = new System.Windows.Forms.CheckBox();
             this.targetTextBox = new System.Windows.Forms.TextBox();
             this.ImportButton = new System.Windows.Forms.Button();
-            this.TargetListBox = new System.Windows.Forms.CheckedListBox();
+            this.dbProvidersComboBox = new System.Windows.Forms.ComboBox();
             this.dbProvidersBindingSource = new System.Windows.Forms.BindingSource(this.components);
-            this.dbProvidersComboBox = new System.Windows.Forms.ComboBox();
             this.TasksListView = new System.Windows.Forms.ListView();
             this.SiteColumnHeader = new System.Windows.Forms.ColumnHeader();
             this.TableColumnHeader = new System.Windows.Forms.ColumnHeader();
             this.menuStrip1 = new System.Windows.Forms.MenuStrip();
             this.buildCommandLineToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
-            this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.listView1 = new System.Windows.Forms.ListView();
+            this.SchemaColumnHeader = new System.Windows.Forms.ColumnHeader();
+            this.SiteNameColumnHeader = new System.Windows.Forms.ColumnHeader();
+            this.errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
+            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.BrowseSourceButton = new System.Windows.Forms.Button();
             bulkInsertBatchSizeLabel = new System.Windows.Forms.Label();
             sourceLabel = new System.Windows.Forms.Label();
             targetLabel = new System.Windows.Forms.Label();
             ((System.ComponentModel.ISupportInitialize)(this.dbProvidersBindingSource)).BeginInit();
             this.statusStrip1.SuspendLayout();
             this.menuStrip1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).BeginInit();
+            this.panel1.SuspendLayout();
             this.SuspendLayout();
             // 
             // bulkInsertBatchSizeLabel
             // 
             bulkInsertBatchSizeLabel.AutoSize = true;
-            bulkInsertBatchSizeLabel.Location = new System.Drawing.Point(212, 146);
+            bulkInsertBatchSizeLabel.Location = new System.Drawing.Point(294, 75);
             bulkInsertBatchSizeLabel.Name = "bulkInsertBatchSizeLabel";
             bulkInsertBatchSizeLabel.Size = new System.Drawing.Size(61, 13);
             bulkInsertBatchSizeLabel.TabIndex = 1;
             // sourceLabel
             // 
             sourceLabel.AutoSize = true;
-            sourceLabel.Location = new System.Drawing.Point(9, 24);
+            sourceLabel.Location = new System.Drawing.Point(3, 0);
             sourceLabel.Name = "sourceLabel";
             sourceLabel.Size = new System.Drawing.Size(44, 13);
             sourceLabel.TabIndex = 9;
             // targetLabel
             // 
             targetLabel.AutoSize = true;
-            targetLabel.Location = new System.Drawing.Point(9, 57);
+            targetLabel.Location = new System.Drawing.Point(3, 36);
             targetLabel.Name = "targetLabel";
             targetLabel.Size = new System.Drawing.Size(41, 13);
             targetLabel.TabIndex = 13;
             // label1
             // 
             label1.AutoSize = true;
-            label1.Location = new System.Drawing.Point(9, 90);
+            label1.Location = new System.Drawing.Point(0, 75);
             label1.Name = "label1";
             label1.Size = new System.Drawing.Size(49, 13);
             label1.TabIndex = 20;
             // label2
             // 
             label2.AutoSize = true;
-            label2.Location = new System.Drawing.Point(385, 31);
+            label2.Location = new System.Drawing.Point(397, 0);
             label2.Name = "label2";
             label2.Size = new System.Drawing.Size(33, 13);
             label2.TabIndex = 22;
             label2.Text = "Sites:";
+            this.toolTip1.SetToolTip(label2, "Checked sites will be imported.\r\nEdit Schema label to change target.\r\n");
             // 
             // BatchSizeNumericUpDown
             // 
-            this.BatchSizeNumericUpDown.Location = new System.Drawing.Point(273, 142);
+            this.BatchSizeNumericUpDown.Location = new System.Drawing.Point(297, 92);
             this.BatchSizeNumericUpDown.Maximum = new decimal(new int[] {
-                                                                            2000000000,
-                                                                            0,
-                                                                            0,
-                                                                            0});
+            2000000000,
+            0,
+            0,
+            0});
             this.BatchSizeNumericUpDown.Minimum = new decimal(new int[] {
-                                                                            1,
-                                                                            0,
-                                                                            0,
-                                                                            0});
+            1,
+            0,
+            0,
+            0});
             this.BatchSizeNumericUpDown.Name = "BatchSizeNumericUpDown";
             this.BatchSizeNumericUpDown.Size = new System.Drawing.Size(86, 20);
-            this.BatchSizeNumericUpDown.TabIndex = 2;
+            this.BatchSizeNumericUpDown.TabIndex = 5;
+            this.toolTip1.SetToolTip(this.BatchSizeNumericUpDown, "Number of rows per transaction.");
             this.BatchSizeNumericUpDown.Value = new decimal(new int[] {
-                                                                          1,
-                                                                          0,
-                                                                          0,
-                                                                          0});
+            1,
+            0,
+            0,
+            0});
             // 
             // fullTextCheckBox
             // 
             this.fullTextCheckBox.Checked = global::Salient.StackExchange.Import.Properties.Settings.Default.FullTextChecked;
             this.fullTextCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Salient.StackExchange.Import.Properties.Settings.Default, "FullTextChecked", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
-            this.fullTextCheckBox.Location = new System.Drawing.Point(140, 140);
+            this.fullTextCheckBox.Location = new System.Drawing.Point(129, 120);
             this.fullTextCheckBox.Name = "fullTextCheckBox";
             this.fullTextCheckBox.Size = new System.Drawing.Size(72, 24);
-            this.fullTextCheckBox.TabIndex = 4;
+            this.fullTextCheckBox.TabIndex = 8;
             this.fullTextCheckBox.Text = "Full Text";
             this.fullTextCheckBox.UseVisualStyleBackColor = true;
             // 
             // 
             this.indicesCheckBox.Checked = global::Salient.StackExchange.Import.Properties.Settings.Default.IndicesChecked;
             this.indicesCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Salient.StackExchange.Import.Properties.Settings.Default, "IndicesChecked", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
-            this.indicesCheckBox.Location = new System.Drawing.Point(72, 140);
+            this.indicesCheckBox.Location = new System.Drawing.Point(61, 120);
             this.indicesCheckBox.Name = "indicesCheckBox";
             this.indicesCheckBox.Size = new System.Drawing.Size(68, 24);
-            this.indicesCheckBox.TabIndex = 6;
+            this.indicesCheckBox.TabIndex = 7;
             this.indicesCheckBox.Text = "Indices";
             this.indicesCheckBox.UseVisualStyleBackColor = true;
             // 
             // sourceTextBox
             // 
             this.sourceTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::Salient.StackExchange.Import.Properties.Settings.Default, "SourceValue", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
-            this.sourceTextBox.Location = new System.Drawing.Point(9, 37);
+            this.sourceTextBox.Location = new System.Drawing.Point(3, 13);
             this.sourceTextBox.Name = "sourceTextBox";
-            this.sourceTextBox.Size = new System.Drawing.Size(370, 20);
-            this.sourceTextBox.TabIndex = 10;
+            this.sourceTextBox.Size = new System.Drawing.Size(352, 20);
+            this.sourceTextBox.TabIndex = 1;
             this.sourceTextBox.Text = global::Salient.StackExchange.Import.Properties.Settings.Default.SourceValue;
+            this.toolTip1.SetToolTip(this.sourceTextBox, "The path of the decompressed data dump.");
             this.sourceTextBox.TextChanged += new System.EventHandler(this.SourceTextChanged);
             // 
             // splitCheckBox
             // 
             this.splitCheckBox.Checked = global::Salient.StackExchange.Import.Properties.Settings.Default.SplitChecked;
             this.splitCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Salient.StackExchange.Import.Properties.Settings.Default, "SplitChecked", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
-            this.splitCheckBox.Location = new System.Drawing.Point(14, 140);
+            this.splitCheckBox.Location = new System.Drawing.Point(3, 120);
             this.splitCheckBox.Name = "splitCheckBox";
             this.splitCheckBox.Size = new System.Drawing.Size(58, 24);
-            this.splitCheckBox.TabIndex = 12;
+            this.splitCheckBox.TabIndex = 6;
             this.splitCheckBox.Text = "Split";
             this.splitCheckBox.UseVisualStyleBackColor = true;
             // 
             // targetTextBox
             // 
             this.targetTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::Salient.StackExchange.Import.Properties.Settings.Default, "TargetText", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
-            this.targetTextBox.Location = new System.Drawing.Point(9, 70);
+            this.targetTextBox.Location = new System.Drawing.Point(3, 52);
             this.targetTextBox.Name = "targetTextBox";
-            this.targetTextBox.Size = new System.Drawing.Size(370, 20);
-            this.targetTextBox.TabIndex = 14;
+            this.targetTextBox.Size = new System.Drawing.Size(383, 20);
+            this.targetTextBox.TabIndex = 3;
             this.targetTextBox.Text = global::Salient.StackExchange.Import.Properties.Settings.Default.TargetText;
+            this.toolTip1.SetToolTip(this.targetTextBox, resources.GetString("targetTextBox.ToolTip"));
             // 
             // ImportButton
             // 
-            this.ImportButton.Location = new System.Drawing.Point(9, 179);
+            this.ImportButton.Location = new System.Drawing.Point(9, 178);
             this.ImportButton.Name = "ImportButton";
-            this.ImportButton.Size = new System.Drawing.Size(499, 36);
-            this.ImportButton.TabIndex = 17;
+            this.ImportButton.Size = new System.Drawing.Size(383, 36);
+            this.ImportButton.TabIndex = 10;
             this.ImportButton.Text = "Import";
             this.ImportButton.UseVisualStyleBackColor = true;
             this.ImportButton.Click += new System.EventHandler(this.ImportClick);
             // 
-            // TargetListBox
+            // dbProvidersComboBox
             // 
-            this.TargetListBox.FormattingEnabled = true;
-            this.TargetListBox.Location = new System.Drawing.Point(388, 46);
-            this.TargetListBox.Name = "TargetListBox";
-            this.TargetListBox.Size = new System.Drawing.Size(120, 94);
-            this.TargetListBox.TabIndex = 18;
+            this.dbProvidersComboBox.DataSource = this.dbProvidersBindingSource;
+            this.dbProvidersComboBox.DisplayMember = "Name";
+            this.dbProvidersComboBox.FormattingEnabled = true;
+            this.dbProvidersComboBox.Location = new System.Drawing.Point(0, 91);
+            this.dbProvidersComboBox.Name = "dbProvidersComboBox";
+            this.dbProvidersComboBox.Size = new System.Drawing.Size(273, 21);
+            this.dbProvidersComboBox.TabIndex = 4;
+            this.dbProvidersComboBox.ValueMember = "Name";
+            this.dbProvidersComboBox.SelectedIndexChanged += new System.EventHandler(this.ProvidersSelectedIndexChanged);
             // 
             // dbProvidersBindingSource
             // 
-            this.dbProvidersBindingSource.DataSource = typeof(DbProviderInfo);
-            // 
-            // dbProvidersComboBox
-            // 
-            this.dbProvidersComboBox.DataSource = this.dbProvidersBindingSource;
-            this.dbProvidersComboBox.DisplayMember = "InvariantName";
-            this.dbProvidersComboBox.FormattingEnabled = true;
-            this.dbProvidersComboBox.Location = new System.Drawing.Point(9, 103);
-            this.dbProvidersComboBox.Name = "dbProvidersComboBox";
-            this.dbProvidersComboBox.Size = new System.Drawing.Size(370, 21);
-            this.dbProvidersComboBox.TabIndex = 20;
-            this.dbProvidersComboBox.ValueMember = "Name";
-            this.dbProvidersComboBox.SelectedIndexChanged += new System.EventHandler(this.ProvidersSelectedIndexChanged);
+            this.dbProvidersBindingSource.DataSource = typeof(Salient.StackExchange.Import.Configuration.DbProviderInfo);
             // 
             // TasksListView
             // 
             this.TasksListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-                                                                               | System.Windows.Forms.AnchorStyles.Left)
-                                                                              | System.Windows.Forms.AnchorStyles.Right)));
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.TasksListView.CausesValidation = false;
             this.TasksListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
-                                                                                            this.SiteColumnHeader,
-                                                                                            this.TableColumnHeader,
-                                                                                            this.CountColumnHeader,
-                                                                                            this.StateColumnHeader,
-                                                                                            this.MessageColumnHeader});
-            this.TasksListView.Location = new System.Drawing.Point(9, 221);
+            this.SiteColumnHeader,
+            this.TableColumnHeader,
+            this.CountColumnHeader,
+            this.StateColumnHeader,
+            this.MessageColumnHeader});
+            this.TasksListView.Location = new System.Drawing.Point(9, 220);
             this.TasksListView.Name = "TasksListView";
-            this.TasksListView.Size = new System.Drawing.Size(499, 189);
+            this.TasksListView.Size = new System.Drawing.Size(574, 148);
             this.TasksListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
             this.TasksListView.TabIndex = 21;
+            this.TasksListView.TabStop = false;
             this.TasksListView.UseCompatibleStateImageBehavior = false;
             this.TasksListView.View = System.Windows.Forms.View.Details;
             // 
             // statusStrip1
             // 
             this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-                                                                                          this.StatusLabel});
-            this.statusStrip1.Location = new System.Drawing.Point(0, 419);
+            this.StatusLabel});
+            this.statusStrip1.Location = new System.Drawing.Point(0, 377);
             this.statusStrip1.Name = "statusStrip1";
-            this.statusStrip1.Size = new System.Drawing.Size(517, 22);
+            this.statusStrip1.Size = new System.Drawing.Size(592, 22);
             this.statusStrip1.TabIndex = 23;
             this.statusStrip1.Text = "statusStrip1";
             // 
             // menuStrip1
             // 
             this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-                                                                                        this.buildCommandLineToolStripMenuItem,
-                                                                                        this.toolStripMenuItem1,
-                                                                                        this.aboutToolStripMenuItem});
+            this.buildCommandLineToolStripMenuItem,
+            this.toolStripMenuItem1});
             this.menuStrip1.Location = new System.Drawing.Point(0, 0);
             this.menuStrip1.Name = "menuStrip1";
-            this.menuStrip1.Size = new System.Drawing.Size(517, 24);
+            this.menuStrip1.Size = new System.Drawing.Size(592, 24);
             this.menuStrip1.TabIndex = 24;
             this.menuStrip1.Text = "menuStrip1";
             // 
             // toolStripMenuItem1
             // 
             this.toolStripMenuItem1.Name = "toolStripMenuItem1";
-            this.toolStripMenuItem1.Size = new System.Drawing.Size(40, 20);
-            this.toolStripMenuItem1.Text = "Help";
+            this.toolStripMenuItem1.Size = new System.Drawing.Size(73, 20);
+            this.toolStripMenuItem1.Text = "Help/About";
+            this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click);
             // 
-            // aboutToolStripMenuItem
+            // listView1
             // 
-            this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
-            this.aboutToolStripMenuItem.Size = new System.Drawing.Size(48, 20);
-            this.aboutToolStripMenuItem.Text = "About";
+            this.listView1.CheckBoxes = true;
+            this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this.SchemaColumnHeader,
+            this.SiteNameColumnHeader});
+            this.listView1.LabelEdit = true;
+            this.listView1.Location = new System.Drawing.Point(400, 13);
+            this.listView1.Name = "listView1";
+            this.listView1.Size = new System.Drawing.Size(163, 117);
+            this.listView1.TabIndex = 9;
+            this.toolTip1.SetToolTip(this.listView1, "Checked sites will be imported.\r\nEdit Schema label to change target.\r\n");
+            this.listView1.UseCompatibleStateImageBehavior = false;
+            this.listView1.View = System.Windows.Forms.View.Details;
+            this.listView1.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.listView1_AfterLabelEdit);
+            // 
+            // SchemaColumnHeader
+            // 
+            this.SchemaColumnHeader.Text = "Schema";
+            this.SchemaColumnHeader.Width = 70;
+            // 
+            // SiteNameColumnHeader
+            // 
+            this.SiteNameColumnHeader.Text = "Site";
+            this.SiteNameColumnHeader.Width = 50;
+            // 
+            // errorProvider1
+            // 
+            this.errorProvider1.ContainerControl = this;
+            // 
+            // panel1
+            // 
+            this.panel1.Controls.Add(this.listView1);
+            this.panel1.Controls.Add(this.BrowseSourceButton);
+            this.panel1.Controls.Add(this.dbProvidersComboBox);
+            this.panel1.Controls.Add(this.BatchSizeNumericUpDown);
+            this.panel1.Controls.Add(this.sourceTextBox);
+            this.panel1.Controls.Add(this.targetTextBox);
+            this.panel1.Controls.Add(sourceLabel);
+            this.panel1.Controls.Add(targetLabel);
+            this.panel1.Controls.Add(this.splitCheckBox);
+            this.panel1.Controls.Add(this.indicesCheckBox);
+            this.panel1.Controls.Add(this.fullTextCheckBox);
+            this.panel1.Controls.Add(bulkInsertBatchSizeLabel);
+            this.panel1.Controls.Add(label1);
+            this.panel1.Controls.Add(label2);
+            this.panel1.Location = new System.Drawing.Point(9, 27);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(580, 145);
+            this.panel1.TabIndex = 26;
+            // 
+            // BrowseSourceButton
+            // 
+            this.BrowseSourceButton.Location = new System.Drawing.Point(361, 12);
+            this.BrowseSourceButton.Name = "BrowseSourceButton";
+            this.BrowseSourceButton.Size = new System.Drawing.Size(25, 23);
+            this.BrowseSourceButton.TabIndex = 2;
+            this.BrowseSourceButton.Text = "...";
+            this.BrowseSourceButton.UseVisualStyleBackColor = true;
             // 
             // FrmUI
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.AutoScroll = true;
-            this.ClientSize = new System.Drawing.Size(517, 441);
-            this.Controls.Add(this.TargetListBox);
-            this.Controls.Add(this.dbProvidersComboBox);
-            this.Controls.Add(this.sourceTextBox);
-            this.Controls.Add(this.targetTextBox);
+            this.ClientSize = new System.Drawing.Size(592, 399);
+            this.Controls.Add(this.menuStrip1);
+            this.Controls.Add(this.panel1);
             this.Controls.Add(this.statusStrip1);
-            this.Controls.Add(this.menuStrip1);
-            this.Controls.Add(label2);
+            this.Controls.Add(this.ImportButton);
             this.Controls.Add(this.TasksListView);
-            this.Controls.Add(label1);
-            this.Controls.Add(this.ImportButton);
-            this.Controls.Add(bulkInsertBatchSizeLabel);
-            this.Controls.Add(this.BatchSizeNumericUpDown);
-            this.Controls.Add(this.fullTextCheckBox);
-            this.Controls.Add(this.indicesCheckBox);
-            this.Controls.Add(sourceLabel);
-            this.Controls.Add(this.splitCheckBox);
-            this.Controls.Add(targetLabel);
             this.MaximizeBox = false;
-            this.MaximumSize = new System.Drawing.Size(525, 1024);
-            this.MinimumSize = new System.Drawing.Size(525, 468);
+            this.MaximumSize = new System.Drawing.Size(600, 1024);
+            this.MinimumSize = new System.Drawing.Size(600, 400);
             this.Name = "FrmUI";
             this.Text = "SODDI v.10 SO Fast  ;-)";
             this.Load += new System.EventHandler(this.FormLoad);
             this.statusStrip1.PerformLayout();
             this.menuStrip1.ResumeLayout(false);
             this.menuStrip1.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).EndInit();
+            this.panel1.ResumeLayout(false);
+            this.panel1.PerformLayout();
             this.ResumeLayout(false);
             this.PerformLayout();
 
         private System.Windows.Forms.CheckBox splitCheckBox;
         private System.Windows.Forms.TextBox targetTextBox;
         private System.Windows.Forms.Button ImportButton;
-        private System.Windows.Forms.CheckedListBox TargetListBox;
-        private System.Windows.Forms.BindingSource dbProvidersBindingSource;
         private System.Windows.Forms.ComboBox dbProvidersComboBox;
         private System.Windows.Forms.ListView TasksListView;
         private System.Windows.Forms.ColumnHeader SiteColumnHeader;
         private System.Windows.Forms.StatusStrip statusStrip1;
         private System.Windows.Forms.MenuStrip menuStrip1;
         private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
-        private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
         private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
         private System.Windows.Forms.ToolStripMenuItem buildCommandLineToolStripMenuItem;
+        private System.Windows.Forms.BindingSource dbProvidersBindingSource;
+        private System.Windows.Forms.ListView listView1;
+        private System.Windows.Forms.ColumnHeader SiteNameColumnHeader;
+        private System.Windows.Forms.ColumnHeader SchemaColumnHeader;
+        private System.Windows.Forms.ErrorProvider errorProvider1;
+        private System.Windows.Forms.ToolTip toolTip1;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Button BrowseSourceButton;
     }
 }

File trunk/soddi/Gui/frmUI.cs

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Data.Common;
 using System.Diagnostics;
 using System.Drawing;
 using System.IO;
         {
             TasksListView.SetExStyles();
             SourceTextChanged(null, EventArgs.Empty);
+            sourceTextBox.Focus();
         }
 
         private void ImportClick(object sender, EventArgs e)
             }
             else
             {
+                if (!ValidateForm())
+                {
+                    return;
+                }
+
+                //_importTargets
+                panel1.Enabled = false;
                 _abort = false;
                 StatusLabel.Text = "Importing...";
                 Configuration.Configuration config = BuildConfigurationFromUi();
 
         private Configuration.Configuration BuildConfigurationFromUi()
         {
+            _importTargets =
+                listView1.CheckedItems.Cast<ListViewItem>().Select(i => i.Tag).Cast<ImportTarget>().ToList();
             Configuration.Configuration tconfig = new Configuration.Configuration
                 {
                     Provider = (DbProviderInfo) dbProvidersComboBox.SelectedItem,
                     Source = sourceTextBox.Text,
-                    Targets = TargetListBox.CheckedItems.Cast<ImportTarget>().ToList(),
+                    Targets = _importTargets,
+                    //Targets =  TargetListBox.CheckedItems.Cast<ImportTarget>().ToList(),
                     BatchSize = (int) BatchSizeNumericUpDown.Value,
                     Split = splitCheckBox.Checked,
                     Indices = indicesCheckBox.Checked,
                 {
                     ImportButton.Text = "Import";
                     ImportButton.Enabled = true;
-
+                    panel1.Enabled = true;
                     _timer.Stop();
                     long count = loader.Jobs.Select(j => j.Tasks.Sum(t => t.Count)).Sum();
 
             }
         }
 
-        #region Misc Handlers
 
         private void ProvidersSelectedIndexChanged(object sender, EventArgs e)
         {
 
         private void UpdateSites(string source, List<ImportTarget> selected)
         {
-            TargetListBox.Items.Clear();
+            listView1.Items.Clear();
+
             List<ImportTarget> targets = null;
             if (Directory.Exists(source))
             {
             {
                 foreach (ImportTarget target in targets)
                 {
-                    ImportTarget importTarget = target;
-                    bool chked = selected.Find(t => string.Compare(t.Path, importTarget.Path, true) == 0) != null;
-                    TargetListBox.Items.Add(target, chked);
+                    listView1.Items.Add(new ListViewItem(new[] {target.Name, target.Schema})
+                        {
+                            Tag = target,
+                            Checked = selected.Find(t => string.Compare(t.Path, target.Path, true) == 0) != null
+                        });
                 }
             }
         }
             frm.ShowDialog();
         }
 
-        #endregion
+
+        private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
+        {
+            ImportTarget target = (ImportTarget) listView1.Items[e.Item].Tag;
+            target.Schema = e.Label;
+        }
+
+        private bool ValidateForm()
+        {
+            bool valid = true;
+            errorProvider1.Clear();
+            if (listView1.Items.Count == 0)
+            {
+                valid = false;
+                errorProvider1.SetError(sourceTextBox, "Invalid source path.");
+            }
+            if (listView1.CheckedItems.Count == 0)
+            {
+                valid = false;
+                errorProvider1.SetError(listView1, "No sites selected.");
+            }
+
+            try
+            {
+                DbProviderInfo info = (DbProviderInfo) dbProvidersComboBox.SelectedItem;
+                DbConnectionStringBuilder csb = info.Factory.CreateConnectionStringBuilder();
+                csb.ConnectionString = targetTextBox.Text;
+                targetTextBox.Text = csb.ConnectionString;
+            }
+            catch (Exception ex)
+            {
+                valid = false;
+                errorProvider1.SetError(targetTextBox, ex.Message);
+            }
+
+            return valid;
+        }
+
+        private void toolStripMenuItem1_Click(object sender, EventArgs e)
+        {
+            FrmAbout frm = new FrmAbout();
+            frm.Show();
+        }
     }
 }

File trunk/soddi/Gui/frmUI.resx

   <metadata name="label2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>False</value>
   </metadata>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>716, 17</value>
+  </metadata>
+  <data name="targetTextBox.ToolTip" xml:space="preserve">
+    <value>A valid connection string.
+MS Sql: Database must exist.
+MySql: Omit Database, database(s) will be created for each site.
+SQLite: Data Source should be the target directory. Data files will be created for each site.</value>
+  </data>
   <metadata name="dbProvidersBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>193, 17</value>
   </metadata>
   <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>484, 17</value>
   </metadata>
+  <metadata name="errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>593, 17</value>
+  </metadata>
 </root>

File trunk/soddi/LICENSE.TXT

+You may use this code under the terms of either the MIT License or 
+the GNU General Public License (GPL) Version 2.
+
+The MIT License is recommended for most projects. It is simple and 
+easy to understand and it places almost no restrictions on what you 
+can do with this code.
+
+If the GPL suits your project better you are also free to use this 
+code project under that license.
+
+You don’t have to do anything special to choose one license or the 
+other and you don’t have to notify anyone which license you are using. 
+
+You are free to use this code in commercial projects as long as the 
+copyright header is left intact.

File trunk/soddi/Loaders/BulkCopyBase.cs

 {
     public abstract class BulkCopyBase
     {
-        #region Fields
-
-        #endregion
 
         public event EventHandler<BulkCopyEventArgs> RowsInserted;
 
-        public abstract void AddColumnMappings(string source, string target, DbType type);
-
-
         protected virtual void OnRowsInserted(BulkCopyEventArgs ea)
         {
             if (RowsInserted != null)
                 RowsInserted(this, ea);
         }
 
-        #region Properties
-
         public virtual int BatchSize { get; set; }
-
         public virtual int BulkCopyTimeout { get; set; }
-
-
         public virtual string DestinationTableName { get; set; }
-
         public virtual int NotifyAfter { get; set; }
 
-        #endregion
-
-        #region Public Methods
+        public abstract void AddColumnMappings(string source, string target, DbType type);
 
         public virtual void WriteToServer(IDataReader reader)
         {
         }
 
-        #endregion
     }
 }

File trunk/soddi/Loaders/BulkCopyTask.cs

     /// </summary>
     public class BulkCopyTask
     {
-        private const int NotifyCount = 2500;
+        private const int NotifyCount = 5000;
         public event EventHandler Complete;
         public event EventHandler PostProcess;
 

File trunk/soddi/Loaders/MsSql/MSSqlInserter.cs

 
 using System;
 using System.Data.SqlClient;
+using System.Reflection;
 using Salient.Data;
 using Salient.StackExchange.Import.Tools;
 
     [Loader("System.Data.SqlClient")]
     public class MSSqlInserter : BulkLoader
     {
-        public MSSqlInserter(Configuration.Configuration config) : base(config)
+        public MSSqlInserter(Configuration.Configuration config)
+            : base(config)
         {
         }
 
             Type[] allTableTypes = Config.GetAllTableTypes();
             foreach (Type item in allTableTypes)
             {
-                Jobs.Add(new BulkLoadJob {Tag = item.Name});
+                Jobs.Add(new BulkLoadJob { Tag = item.Name });
             }
 
             base.Configure();
 
         public override void PrepareDatabase(string schema)
         {
+
             using (SqlConnection conn = new SqlConnection(Config.Provider.ConnectionString))
             {
                 conn.Open();
 
+
                 using (SqlCommand cmd = conn.CreateCommand())
                 {
+
                     cmd.CommandTimeout = 300;
                     cmd.CommandText = string.Format("CREATE SCHEMA {0} AUTHORIZATION [dbo]", schema);
 
                     }
 
 
-                    string script = Common.GetTextResource("Scripts\\mssql.sql", GetType().Assembly);
+                    string script = Common.GetTextResource("Loaders\\Scripts\\mssql.sql", Assembly.GetExecutingAssembly());
                     script = script.Replace("PostFullText",
                                             string.Format("{0}PostFullText", schema.Replace(" ", "").Trim('[', ']')));
-                    script = script.Replace("[dbo]", schema);
+                    script = script.Replace("DUMMY", schema);
 
 
                     if ((Config.Options & Configuration.Configuration.ImportOptions.Split) ==

File trunk/soddi/Loaders/MySql/MySqlBulkInserter.cs

                             }
                             catch (Exception ex)
                             {
-                                //TODO: get a logger going
                                 Trace.WriteLine(ex.Message);
+                                throw;
                             }
                             reportCounter++;
                             totalRecords++;

File trunk/soddi/Loaders/MySql/MySqlInserter.cs

 #region
 
 using System;
+using System.Reflection;
 using MySql.Data.MySqlClient;
 using Salient.Data;
 using Salient.StackExchange.Import.Tools;
                 {
                     cmd.CommandTimeout = 300;
 
-                    string script = Common.GetTextResource("Scripts\\mysql.sql", GetType().Assembly);
+                    string script = Common.GetTextResource("Loaders\\Scripts\\mysql.sql", Assembly.GetExecutingAssembly());
 
-                    script = script.Replace("`dbo`", "`" + schema + "`");
+                    script = script.Replace("DUMMY", "`" + schema + "`");
 
                     if ((Config.Options & Configuration.Configuration.ImportOptions.Split) ==
                         Configuration.Configuration.ImportOptions.Split)

File trunk/soddi/Loaders/SQLite/SQLiteBulkInserter.cs

 using System.Diagnostics;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using Salient.StackExchange.Import.Tools;
 
 #endregion
                 _command.CommandText = "pragma journal_mode = off;pragma foreign_keys=off;";
                 _command.ExecuteNonQuery();
                 _command.CommandText =
-                    Common.GetTextResource("Scripts\\sqlite-tmp.sql", GetType().Assembly);
+                    Common.GetTextResource("Loaders\\Scripts\\sqlite-tmp.sql", Assembly.GetExecutingAssembly());
                 _command.ExecuteNonQuery();
 
                 string names = string.Join(",",
                             catch (Exception ex)
                             {
                                 Trace.WriteLine(ex.Message);
+                                throw;
                             }
                             reportCounter++;
                             totalRecords++;

File trunk/soddi/Loaders/SQLite/SQLiteInserter.cs

 using System.Data.SQLite;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using System.Threading;
 using Salient.Data;
 using Salient.StackExchange.Import.Tools;
 
             foreach (ImportTarget target in Config.Targets)
             {
-                PrepareOutputDataFile(_targetPath, target.Name);
+                PrepareOutputDataFile(_targetPath, target.Schema);
                 _locks[target.Name] = new object();
-                Jobs.Add(new BulkLoadJob {Tag = target.Name});
+                Jobs.Add(new BulkLoadJob { Tag = target.Schema });
             }
 
             base.Configure();
             BulkCopyTask task = new BulkCopyTask(new SQLiteBulkInserter(_targetPath, target.Schema, table), table,
                                                  reader, target.Name, Config.BatchSize, target.Schema);
             task.PostProcess += PostProcess; // when the task is complete, merge into main file
-            _locks[task.Site] = new object();
-            Jobs.Find(j => j.Tag == target.Name).Tasks.Add(task);
+            _locks[task.Schema] = new object();
+            Jobs.Find(j => j.Tag == target.Schema).Tasks.Add(task);
         }
 
 
                     cmd.CommandText = Pragma;
                     cmd.ExecuteNonQuery();
 
-                    string script = Common.GetTextResource("Scripts\\sqlite-main.sql", GetType().Assembly);
+                    string script = Common.GetTextResource("Loaders\\Scripts\\sqlite-main.sql", Assembly.GetExecutingAssembly());
                     if (Config.Indices)
                     {
                         script = script.Replace("-- INDICES", "");
             }
         }
 
-        private static string GetConnectionString(string targetPath, string site)
+        private static string GetConnectionString(string targetPath, string schema)
         {
-            return string.Format(@"Data Source={0};Version=3;New=True;", GetOutputPath(targetPath, site));
+            return string.Format(@"Data Source={0};Version=3;New=True;", GetOutputPath(targetPath, schema));
         }
 
-        private static string GetOutputPath(string targetPath, string site)
+        private static string GetOutputPath(string targetPath, string schema)
         {
-            return Path.Combine(targetPath, string.Format("{0}.db3", site));
+            return Path.Combine(targetPath, string.Format("{0}.db3", schema));
         }
 
-        private static void PrepareOutputDatabaseFile(string targetPath, string site)
+        private static void PrepareOutputDatabaseFile(string targetPath, string schema)
         {
-            string path = GetOutputPath(targetPath, site);
+            string path = GetOutputPath(targetPath, schema);
             if (File.Exists(path))
             {
                 File.Delete(path);
             }
         }
 
-        private void PrepareOutputDataFile(string targetPath, string site)
+        private void PrepareOutputDataFile(string targetPath, string schema)
         {
-            PrepareOutputDatabaseFile(targetPath, site);
-            CreateMainDbFile(GetConnectionString(targetPath, site));
+            PrepareOutputDatabaseFile(targetPath, schema);
+            CreateMainDbFile(GetConnectionString(targetPath, schema));
         }
 
         private void PostProcess(object sender, EventArgs e)
 
             string table = task.Table;
 
-            string sourcePath = Path.Combine(_targetPath, string.Format("{0}.{1}.db3", task.Site, table));
-            lock (_locks[task.Site])
+            string sourcePath = Path.Combine(_targetPath, string.Format("{0}.{1}.db3", task.Schema, table));
+            lock (_locks[task.Schema])
             {
                 task.OnRowsInserted(CopyEventType.Processing, "Merging...");
 
-                using (SQLiteConnection conn = new SQLiteConnection(GetConnectionString(_targetPath, task.Site)))
+                using (SQLiteConnection conn = new SQLiteConnection(GetConnectionString(_targetPath, task.Schema)))
                 {
                     conn.Open();
                     SQLiteCommand cmd = conn.CreateCommand();

File trunk/soddi/Loaders/Scripts/mssql.sql

-IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Badges]') AND type in (N'U'))
-DROP TABLE [dbo].[Badges]
-IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Comments]') AND type in (N'U'))
-DROP TABLE [dbo].[Comments]
-IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Posts]') AND type in (N'U'))
-DROP TABLE [dbo].[Posts]
-IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[PostTags]') AND type in (N'U'))
-DROP TABLE [dbo].[PostTags]
-IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[PostTypes]') AND type in (N'U'))
-DROP TABLE [dbo].[PostTypes]
-IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Users]') AND type in (N'U'))
-DROP TABLE [dbo].[Users]
-IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Votes]') AND type in (N'U'))
-DROP TABLE [dbo].[Votes]
-IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[VoteTypes]') AND type in (N'U'))
-DROP TABLE [dbo].[VoteTypes]
+-- NOTE: DUMMY is replaced by the name of the site
+
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'DUMMY.[Badges]') AND type in (N'U'))
+DROP TABLE DUMMY.[Badges]
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'DUMMY.[Comments]') AND type in (N'U'))
+DROP TABLE DUMMY.[Comments]
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'DUMMY.[Posts]') AND type in (N'U'))
+DROP TABLE DUMMY.[Posts]
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'DUMMY.[PostTags]') AND type in (N'U'))
+DROP TABLE DUMMY.[PostTags]
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'DUMMY.[PostTypes]') AND type in (N'U'))
+DROP TABLE DUMMY.[PostTypes]
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'DUMMY.[Users]') AND type in (N'U'))
+DROP TABLE DUMMY.[Users]
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'DUMMY.[Votes]') AND type in (N'U'))
+DROP TABLE DUMMY.[Votes]
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'DUMMY.[VoteTypes]') AND type in (N'U'))
+DROP TABLE DUMMY.[VoteTypes]
 
 SET ansi_nulls  ON
 SET quoted_identifier  ON
 SET ansi_padding  ON
 
-CREATE TABLE [dbo].[VoteTypes] (
+CREATE TABLE DUMMY.[VoteTypes] (
   [Id]   [INT]    NOT NULL,
   [Name] [VARCHAR](40)    NOT NULL
   , CONSTRAINT [PK__VoteType__3214EC073864608B] PRIMARY KEY CLUSTERED ( [Id] ASC ) ON [PRIMARY]
 SET ansi_nulls  ON
 SET quoted_identifier  ON
 
-CREATE TABLE [dbo].[PostTypes] (
+CREATE TABLE DUMMY.[PostTypes] (
   [Id]   [INT]    NOT NULL,
   [Type] [NVARCHAR](10)    NOT NULL
   , CONSTRAINT [PK_PostTypes] PRIMARY KEY CLUSTERED ( [Id] ASC ) ON [PRIMARY]
 	SET ansi_nulls  ON
 	SET quoted_identifier  ON
 
-	CREATE TABLE [dbo].[PostTags] (
+	CREATE TABLE DUMMY.[PostTags] (
 	  [PostId] [INT]    NOT NULL,
 	  [Tag]    [NVARCHAR](50)    NOT NULL
 	  , CONSTRAINT [PK_PostTags_1] PRIMARY KEY CLUSTERED ( [PostId] ASC,[Tag] ASC ) ON [PRIMARY]
 	  ) ON [PRIMARY]
   
   END
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(1, N'AcceptedByOriginator')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(2, N'UpMod')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(3, N'DownMod')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(4, N'Offensive')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(5, N'Favorite')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(6, N'Close')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(7, N'Reopen')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(8, N'BountyStart')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(9, N'BountyClose')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(10,N'Deletion')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(11,N'Undeletion')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(12,N'Spam')
-INSERT [dbo].[VoteTypes] ([Id], [Name]) VALUES(13,N'InformModerator')
-INSERT [dbo].[PostTypes] ([Id], [Type]) VALUES(1, N'Question') 
-INSERT [dbo].[PostTypes] ([Id], [Type]) VALUES(2, N'Answer') 
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(1, N'AcceptedByOriginator')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(2, N'UpMod')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(3, N'DownMod')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(4, N'Offensive')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(5, N'Favorite')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(6, N'Close')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(7, N'Reopen')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(8, N'BountyStart')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(9, N'BountyClose')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(10,N'Deletion')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(11,N'Undeletion')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(12,N'Spam')
+INSERT DUMMY.[VoteTypes] ([Id], [Name]) VALUES(13,N'InformModerator')
+INSERT DUMMY.[PostTypes] ([Id], [Type]) VALUES(1, N'Question') 
+INSERT DUMMY.[PostTypes] ([Id], [Type]) VALUES(2, N'Answer') 
 
 IF 0 = 1--FULLTEXT
   BEGIN
-	IF  EXISTS (SELECT * FROM sys.fulltext_indexes fti WHERE fti.object_id = OBJECT_ID(N'[dbo].[Posts]'))
-	ALTER FULLTEXT INDEX ON [dbo].[Posts] DISABLE
-	IF  EXISTS (SELECT * FROM sys.fulltext_indexes fti WHERE fti.object_id = OBJECT_ID(N'[dbo].[Posts]'))
-	DROP FULLTEXT INDEX ON [dbo].[Posts]
+	IF  EXISTS (SELECT * FROM sys.fulltext_indexes fti WHERE fti.object_id = OBJECT_ID(N'DUMMY.[Posts]'))
+	ALTER FULLTEXT INDEX ON DUMMY.[Posts] DISABLE
+	IF  EXISTS (SELECT * FROM sys.fulltext_indexes fti WHERE fti.object_id = OBJECT_ID(N'DUMMY.[Posts]'))
+	DROP FULLTEXT INDEX ON DUMMY.[Posts]
 	IF  EXISTS (SELECT * FROM sysfulltextcatalogs ftc WHERE ftc.name = N'PostFullText')
 	DROP FULLTEXT CATALOG [PostFullText]
 	CREATE FULLTEXT CATALOG [PostFullText]WITH ACCENT_SENSITIVITY = ON
 SET ansi_nulls  ON
 SET quoted_identifier  ON
 
-CREATE TABLE [dbo].[Votes] (
+CREATE TABLE DUMMY.[Votes] (
   [Id]           [INT]    NOT NULL,