Archive

Monthly Archives: February 2009

Part 1, Part 2.

Now it is time finally for the random name generation.  I’ve gotten everything into place, so it’s just a matter of grabbing the names and randomizing among them.  Just as a check, after Part 2 was finished I had a total of 98,572 rows of data, or simply 98,572 names.

Many times I would not write actual unit tests against the database as it breaks isolation.  This time though, I’m making an exception.  First I added a reference to Generator.Core, System.Data, and System.Data.Entity.  I then created a new unit test class called DatabaseTests and added the following test to get things rolling.  Keep in mind, since these tests break isolation, I don’t write them in the red light green light idea of TDD.  My assumption is that they only prove the database is setup, running, the connection string is correct, and other minor configuration based and server based components.  In addition, yes, these are somewhat silly tests, such as the RetrieveFirstName() test has a bit of redundancy to it, but the point is to have an automated test to assure that the data has been moved into the database and is returning appropriately.

 1: [TestClass]
 2: public class DatabaseTests
 3: {
 4:     [TestMethod]
 5:     public void RetrieveFirstFemaleName()
 6:     {
 7:         var entities = new GeneratorEntities();
 8:         var returnName = (from name in entities.Names
 9:                           where name.Type == "Female First Names"
 10:                           select name).FirstOrDefault();
 11:         Assert.IsNotNull(returnName);
 12:         Assert.IsTrue(returnName.Name != string.Empty);
 13:     }
 14: 
 15:     [TestMethod]
 16:     public void RetrieveLastName()
 17:     {
 18:         var entities = new GeneratorEntities();
 19:         var returnName = (from name in entities.Names
 20:                           where name.Type == "Last Names"
 21:                           select name).FirstOrDefault();
 22:         Assert.IsNotNull(returnName);
 23:         Assert.IsTrue(returnName.Name != string.Empty);
 24:     }
 25:  
 26:     [TestMethod]
 27:     public void RetrieveFirstMaleName()
 28:     {
 29:         var entities = new GeneratorEntities();
 30:         var returnName = (from name in entities.Names
 31:                           where name.Type == "Male First Names"
 32:                           select name).FirstOrDefault();
 33:         Assert.IsNotNull(returnName);
 34:         Assert.IsTrue(returnName.Name != string.Empty);
 35:     }
 36: 
 37:     [TestMethod]
 38:     public void RetrieveFirstName()
 39:     {
 40:         var entities = new GeneratorEntities();
 41:         var returnName = (from name in entities.Names
 42:                           where name.Type == "Female First Names" || name.Type == "Male First Names"
 43:                           select name).FirstOrDefault();
 44:         Assert.IsNotNull(returnName);
 45:         Assert.IsTrue(returnName.Name != string.Empty && returnName.Type == "Female First Names" ||
 46:                       returnName.Type == "Male First Names");
 47:     }
 48: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The next step now was to refactor the existing tests to prove the assembly of the name data transfer objects that would hold the first name and last name derived from the returned entity objects.

The first thing I did was break out the actual name objects into their respective files.  I did this using ReSharper, because it’s super insanely simple with ReSharper.  After that I put the class files in the project that has the model.  Next I fixed the namespaces to Generator.Core.Model.  The class files after these changes looked like the code below.

IFullName.cs

 1: namespace Generator.Core.Model
 2: {
 3:     public interface IFullName
 4:     {
 5:         string FirstName { get; set; }
 6:         string LastName { get; set; }
 7:     }
 8: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

FullName.cs

 1: namespace Generator.Core.Model
 2: {
 3:     public class FullName : IFullName
 4:     {
 5:         public FullName()
 6:         {
 7:             FirstName = string.Empty;
 8:             LastName = string.Empty;
 9:         }
 10: 
 11:         #region IFullName Members
 12: 
 13:         public string FirstName { get; set; }
 14:         public string LastName { get; set; }
 15:  
 16:         #endregion
 17:     }
 18: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

NameFactory.cs

 1: namespace Generator.Core.Model
 2: {
 3:     public class NameFactory
 4:     {
 5:         public static IFullName Build()
 6:         {
 7:             return new FullName {FirstName = "TestFirst", LastName = "TestLast"};
 8:         }
 9:     }
 10: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Now that we have these files moved out to the project where all the munging will happen, I’m going to start the actual refactor of the tests.  What I’ve come up with for the test refactor is as follows.

 1: using Generator.Core.Model;
 2: using Microsoft.VisualStudio.TestTools.UnitTesting;
 3:  
 4: namespace Factory.Tests
 5: {
 6:     [TestClass]
 7:     public class FactoryNameBuilder
 8:     {
 9:         [TestMethod]
 10:         public void VerifyFullNameObjectInstantiatesWithNames()
 11:         {
 12:             var name = new FullName();
 13:             Assert.IsTrue(name.FirstName.Length == 0);
 14:             Assert.IsTrue(name.LastName.Length == 0);
 15:         }
 16: 
 17:         [TestMethod]
 18:         public void VerifyFullNameObjectReturnsFromFactory()
 19:         {
 20:             var factory = new NameFactory();
 21:             IFullName name = factory.Build();
 22:             Assert.IsTrue(name.FirstName.Length > 0);
 23:             Assert.IsTrue(name.LastName.Length > 0);
 24:         }
 25:  
 26:         [TestMethod]
 27:         public void VerifyFullNameIsRandom()
 28:         {
 29:             var factory = new NameFactory();
 30:             IFullName nameOne = factory.Build();
 31:             IFullName nameTwo = factory.Build();
 32: 
 33:             Assert.AreNotEqual(nameOne.FirstName, nameTwo.FirstName);
 34:             Assert.AreNotEqual(nameOne.LastName, nameTwo.LastName);
 35:         }
 36:     }
 37: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

In the factory I removed the fake return and fleshed out the appropriate build method.

 1: using System;
 2: using System.Collections.Generic;
 3: using System.Linq;
 4: 
 5: namespace Generator.Core.Model
 6: {
 7:     public class NameFactory
 8:     {
 9:         public IFullName Build()
 10:         {
 11:             Random rand = new Random(DateTime.Now.Millisecond);
 12: 
 13:             GeneratorEntities entities = new GeneratorEntities();
 14: 
 15:             List<Names> FirstNames = (from name in entities.Names
 16:                                       where name.Type == "Female First Names" || name.Type == "Male First Names"
 17:                                       select name).ToList();
 18:             List<Names> LastNames = (from name in entities.Names
 19:                                      where name.Type == "Last Names"
 20:                                      select name).ToList();
 21: 
 22:             FullName fullName = new FullName();
 23:             fullName.FirstName = FirstNames[rand.Next(0, FirstNames.Count)].Name;
 24:             fullName.LastName = LastNames[rand.Next(0, LastNames.Count)].Name;
 25: 
 26:             return fullName;
 27:         }
 28:     }
 29: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Run the tests now and you have a random name gold mine.  However, I wanted a bit more than that.  With another test added…

 1: [TestMethod]
 2: public void VerifyMultipleNameReturn()
 3: {
 4:     var factory = new NameFactory();
 5:     List<IFullName> list = factory.Build(1000);
 6: 
 7:     for (int i = 0; i < list.Count; i++)
 8:     {
 9:         int compareUp = i + 1;
 10:         if (compareUp == list.Count)
 11:         {
 12:             compareUp = 0;
 13:         }
 14:         Assert.AreNotEqual(list[compareUp].FirstName + list[compareUp].LastName, list[i].FirstName + list[i].LastName);
 15:     }
 16: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

…then the extra Build method.

 1: public List<IFullName> Build(int numberOfNames)
 2: {
 3:     var rand = new Random(DateTime.Now.Millisecond);
 4:     var entities = new GeneratorEntities();
 5:  
 6:     List<Names> FirstNames = (from name in entities.Names
 7:                               where name.Type == "Female First Names" || name.Type == "Male First Names"
 8:                               select name).ToList();
 9:     List<Names> LastNames = (from name in entities.Names
 10:                              where name.Type == "Last Names"
 11:                              select name).ToList();
 12: 
 13:     var names = new List<IFullName>();
 14: 
 15:     for (int i = 0; i < numberOfNames; i++)
 16:     {
 17:         var fullName = new FullName();
 18:         fullName.FirstName = FirstNames[rand.Next(0, FirstNames.Count)].Name;
 19:         fullName.LastName = LastNames[rand.Next(0, LastNames.Count)].Name;
 20:         names.Add(fullName);
 21:     }
 22: 
 23:     return names;
 24: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

and now I have a strong verification that I get solid randoms for 1000 name pairs.  I bumped it up to 2000 too just for fun, and didn’t hit duplicates until I put it up to 200,000.

REST Services are intended to have clean URIs.  So when Microsoft started pushing their REST over WCF Services I thought, “SWEET”, lemme get some of that.  While working with these services though a problem arose, “http://www.soemthing.com/someservice.svc” is NOT a very clean REST URI.  I just don’t dig nonsense like this so I went digging about for a fix.

Sure one can go into the whole process of doing some URI rewriting, but I wanted something fast, simple, and deployed in about 10-15 minutes.  HTTP Modules to the rescue!

First I created a regular class project and created a class file called RestUriCleanup.cs.  I then added the following code into the class file.

   1:  using System.Web; 
   2:   
   3:  namespace StandardServicesApplication
   4:  {
   5:      public class RestUriCleanup : IHttpModule
   6:      {
   7:          #region IHttpModule Members 
   8:   
   9:          public void Init(HttpApplication context)
  10:          {
  11:              context.BeginRequest +=
  12:                  delegate
  13:                      {
  14:                          var ctx = HttpContext.Current;
  15:                          string path = ctx.Request.AppRelativeCurrentExecutionFilePath; 
  16:   
  17:                          int i = path.IndexOf('/', 2);
  18:                          if (i > 0)
  19:                          {
  20:                              string svc = path.Substring(0, i) + ".svc";
  21:                              string rest = path.Substring(i, path.Length - i);
  22:                              string qs = ctx.Request.QueryString.ToString();
  23:                              ctx.RewritePath(svc, rest, qs, false);
  24:                          }
  25:                      };
  26:          } 
  27:   
  28:          public void Dispose()
  29:          {
  30:          } 
  31:   
  32:          #endregion
  33:      }
  34:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

In the web.config file I added the following configuration settings in the httpModules Section.  Notice that the ScriptModule is already included as a handler as of .NET 3.5.

   1:      <httpModules>
   2:        <add name="RestUriCleanup" type="StandardServicesApplication.RestUriCleanup, StandardServicesApplication" />
   3:        <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
   4:      </httpModules>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Now at this point things can get tricky.  Depending on the version of IIS you’ll possibly need to make some changes at this point.  IIS 6.0 is setup as follows.  Open up the management console and right click the app or virtual directory and click on properties.  Click on the Home Directory tab and click on the Configuration button.

Once you have that dialog open then Insert a new wildcard application map.  Find and select the aspnet_isapi.dll file.  It should be located here:  “C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll

Make SURE when you are adding the file, do NOT leave or check the Verify that file exists box.  I repeat, do NOT check it.

That’s it.  You now have your *.svc extension removed from your services file and should have nice clean REST based URIs.  This process is slightly different on IIS 7 w/ Vista or Windows Server 2008.  First off you do NOT need to create a wildcard on IIS 7 but you will need to go in and create a setting in IIS for the HTTP Module.  If interested let me know and I’ll add another blog entry for that, but for now…  this is how one gets rid of the *.svc extension.

Ugh.  I was interrupted after a solid 30+ minutes of concentration while working through a recursion problem.  It all screeched to a stop.  I lost track of what was going on.  Everything I had been concentrating on was immediately dumped as a request for my attention came to assist in doing something else, something completely unrelated.  That 30 minutes of work was completely erased, only the skeletal remains left in actual code, that at least built, but was not working appropriately.  Everything I held in memory, the multiple memories I was using in my gray matter, each was catastrophically purged.

I then completed this alternate, non-related development task.  It was fun, I enjoyed it.

Now knew I?d have to step back into that 30 minutes of memory, and spend another 10 minutes just to get back to the point where I could continue with what I was working on.  I now faced the challenge of putting all of those multiple memories back into place, of remembering each and every piece of data that I held in my mind, and assure that each connection was once again related appropriately in my gray matter.

What was originally about 20-30 more minutes of work before the interruption, now grew into the 20-30 minutes plus the 10 or so minutes taken to reacquire the appropriate working state.  This happens to every developer, sometimes we can maintain our state, but mostly we?re completely ruined and must start by rebuilding our working state.

How many project managers, significant others, and generally the planet just disregards this fact?  Maybe people just don?t understand, even though it is inherent to the human process of thought.  Simply, anything requiring attention and thought cannot be interrupted without devastating consequences to the intended end result.

I’m not sure what the name should be, not sure how or where to go about this yet, but would love to hold some lunch time sessions and put some code together.  The idea I have revolves around small team meet ups during lunch for about 30-45 minutes.  A lead will be chosen to cover a topic and some functional code will be put together per that leads direction.

Of course this would mean whoever would come would need a laptop or other device of sorts to do development on.  They would also need appropriate tools.  If we?re working with C# something like VS.NET, if we?re working with Java then Eclipse, or with Erlang we?d need your favorite text editor.  Technically, I guess any of these could be built in a text editor, and the point isn?t what it is built in but to cover the language or specific skill topic.

Anyone else have any ideas?  I?ll be looking and talking to establishments around town that could or would host something like this.  Next I?ll just need to figure out who and what topics, which anyone could chime in on.

Part 1Part 3.

Alright, time to tear into getting that name data imported into the database.  To review the previous entry check out part 1.

Next I set the Windows App Project I added in part 1 to be the startup project.  After that I created a screen that looks like the image below (click to see larger image).

Also add an open file dialog control.  Next double click on the Process button and add the following code.  Make sure not to miss the instantiation of the names list property in the initialization.

 1: using System;
 2: using System.Collections.Generic;
 3: using System.IO;
 4: using System.Text.RegularExpressions;
 5: using System.Windows.Forms;
 6: 
 7: namespace TextFileImporter
 8: {
 9:     public partial class Form1 : Form
 10:     {
 11:         public Form1()
 12:         {
 13:             InitializeComponent();
 14:             Names = new List<string>();
 15:         }
 16: 
 17:         private List<string> Names { get; set; }
 18: 
 19:         private void buttonProcessFile_Click(object sender, EventArgs e)
 20:         {
 21:             if (openFile.ShowDialog() == DialogResult.OK)
 22:             {
 23:                 if (File.Exists(openFile.FileName))
 24:                 {
 25:                     TextReader tr = new StreamReader(openFile.FileName);
 26:                     textProcessedFile.Text = tr.ReadToEnd();
 27:                     tr.Close();
 28:                     // Cleanup text.
 29:                     textProcessedFile.Text = ProcessName(textProcessedFile.Text);
 30:                 }
 31:                 else
 32:                 {
 33:                     MessageBox.Show("Select a file that exists.", "File doesn't exist.", MessageBoxButtons.OK,
 34:                                     MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
 35:                 }
 36:             }
 37:         }
 38: 
 39:         private string ProcessName(string textBody)
 40:         {
 41:             var regex = new Regex("[^A-Z']+");
 42:             textBody = regex.Replace(textBody, " ");
 43:  
 44:             foreach (var s in textBody.Split(Convert.ToChar(" ")))
 45:             {
 46:                 Names.Add(s);
 47:             }
 48: 
 49:             return textBody;
 50:         }
 51:     }
 52: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

With the beauty of those regular expressions the files will parse appropriately in about 1-5 seconds.  Next we need a way to write this data into the database.  I did this by adding a Class Project named Generator.Core and added a folder called Model.

In the Model Directory I added a new ADO.NET Entity Framework Model.  The images below show my steps through the wizard.

  • Wizard # 1 - Adding Data Model.Wizard # 1 – Adding Data Model.
  • Wizard # 2 - Adding Data Model.Wizard # 2 – Adding Data Model.
  • Wizard # 3 - Adding Data Model.Wizard # 3 – Adding Data Model.
  • Wizard # 4 - Adding Data Model.Wizard # 4 – Adding Data Model.
  • Wizard # 5 - Adding Data Model.Wizard # 5 – Adding Data Model.

.smugcontainer div {overflow: hidden;line-height: 1.1;margin-top: 10px;font-family: verdana, arial, lucida, sans-serif;font-size: 85%;background-color1: rgb(20, 20, 20);}
.smugimg li {float: left;display: block;width: 160px;height: 200px;background-position: 50% 50%;margin-right: 10px;margin-bottom: 10px;}
.smugimg li img {width: auto; height: auto; border: solid 1px #aaa; background: #555; padding: 2px; vertical-align: middle;}
.smugimg a {display: block;text-align: center;text-decoration: none; color1: rgb(240,240,240);}
.smugimg a:hover img {border: 3px solid #6da6d1; padding: 0px;}

.smugcontainer div {overflow: hidden;line-height: 1.1;margin-top: 10px;font-family: verdana, arial, lucida, sans-serif;font-size: 85%;background-color1: rgb(20, 20, 20);}
.smugimg li {float: left;display: block;width: 160px;height: 200px;background-position: 50% 50%;margin-right: 10px;margin-bottom: 10px;}
.smugimg li img {width: auto; height: auto; border: solid 1px #aaa; background: #555; padding: 2px; vertical-align: middle;}
.smugimg a {display: block;text-align: center;text-decoration: none; color1: rgb(240,240,240);}
.smugimg a:hover img {border: 3px solid #6da6d1; padding: 0px;}

At the end I also deleted the Class1.cs file from the project.

I then added a reference to the Generator.Core Project in the TextFileImporter Application Project.  Next add an application configuration file to the TextFileImporter Project with the following configuration section.

 1: <?xml version="1.0" encoding="utf-8"?>
 2: <configuration>
 3:   <connectionStrings>
 4:     <add name="GeneratorEntities" connectionString="metadata=res://*/Model.Data.csdl|res://*/Model.Data.ssdl|res://*/Model.Data.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\carriage;Initial Catalog=Generator;Integrated Security=True;Pooling=False;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
 5:   </connectionStrings>
 6: </configuration>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

At the last minute, and to make sure anyone following along with these instructions is really paying attention, I made a minor change to the database table.  I changed the column Type to a data type of nvarchar(50).  I then updated the Data.edmx file in the Generator.Core Project.  To do this open up the file and right click anywhere in the white space around the model.  Then click on Update Model from Database….  Now, as things go, the stupid model didn’t update for me.  This is something that seems to occur very frequetly with the ADO.NET Entity Framework Model Files.  Since it didn’t update I had to manually right click on the Type Property and then set the Type of the Type (yes I know, redundant naming) to String.

So if anyone from Microsoft is reading this, the entity model files are STILL broken for some reason.  It’s been about 6 months since the entity framework and such where in beta and they still behave in many ways like they’re in beta, please fix this.  k thx bye.

Next I double clicked the Save (buttonSaveToDb) button and entered the following code to write the file data into the database.

 1: private void buttonSaveToDb_Click(object sender, EventArgs e)
 2: {
 3:     if (comboNameType.Text == string.Empty)
 4:     {
 5:         MessageBox.Show("Select a type of name.", "Select Name", MessageBoxButtons.OK,
 6:                         MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
 7:     }
 8:     else
 9:     {
 10:         // TODO Write to DB.
 11:         var generatorEntities = new GeneratorEntities();
 12:         foreach (var name in Names)
 13:         {
 14:             var newName =
 15:                 new Names
 16:                     {
 17:                         NameId = Guid.NewGuid(),
 18:                         Name = name,
 19:                         Type = comboNameType.Text
 20:                     };
 21:             generatorEntities.AddToNames(newName);
 22:         }
 23:         generatorEntities.SaveChanges(true);
 24:     }
 25: }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Then a quick reference and that finishes up the TextFileImporter Project.

 1: using Generator.Core.Model;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Now mind you, I broke TDD principles because this app was merely a utility, would be used a few times, and above all breaks isolation and crosses boundaries.  A good rule is to not write tests for a project like this.  Unless you feel it absolutely necessary then I wouldn’t even think of it.

Now run the application and open and import each of the three files into the database.  This will give us the data we need for the next step of our random name generator.

Follow

Get every new post delivered to your Inbox.

Join 3,712 other followers