Subsonic, part deux


I have now finished my database schema, so I played with setting up my data access using SubSonic. Thus far, I am pretty impressed.
 
First, if you need a repository, you can do something like this:

provider = new SqlDataProvider();
provider.DefaultConnectionString =
"{connectionstring here}";
ISubSonicRepository
repository = new SubSonicRepository(provider);

What this gives you is the ability to set up a mock, by deriving from ISubSonicRepository. I like this and will use it rather extensively in my test code. Thus far, I have written most of my tests against the respository. Yeah, I know this is not necessary, but it is one of the best ways to learn how to use it.
 
Here is the code to get a Backend with the id of 1:

Backend

backend = repository.Get<Backend>(1);

And, to add a new one, I simply create and save:

Backend backend = new Backend();
backend.BackendName =
"My Backend";
ISubSonicRepository repository = new SubSonicRepository(provider);
repository.Save(backend);

You gotta love generics. The one thing I am not sure I like is the way collections are implemented, as I will have to mock up each collection for my code instead of the Repository. Here is a load everything for the backend collection (to load a dropdownlist, for example):

BackendCollection coll = new BackendCollection();
coll.Load();

To me, that breaks the entire idea of having a Repository. I will have to think it through before making a firm decision, however. Perhaps this is something left over from the Active Record implementation?
 
Here are a few tests. Realize that these were to learn SubSonic and break many rules for tests I would write for my own stuff. ALso realize these are more Integration tests than Unit tests, as they actually manipulate real data. They are a good start for understanding how the repository works and will help in future posts when I am mocking the Repository. If you are a purist, please cut me some slack until I show some real tests. Then you can skewer me all you want.
 
namespace Microtrak.MultiProgrammer.Data.Tests.VisualStudio
{
 
/// <summary>
  /// Summary description for RepositoryTests
  /// </summary>
  [TestClass]
 
public class RepositoryTests
  {
   
private static SqlDataProvider provider;

    public RepositoryTests()
    {
     
//
      // TODO: Add constructor logic here
      //
    }

    private TestContext testContextInstance;

    /// <summary>
    ///Gets or sets the test context which provides
    ///information about and functionality for the current test run.
    ///</summary>
    public TestContext TestContext
    {
     
get
      {
       
return testContextInstance;
      }
     
set
      {
        testContextInstance =
value;
      }
    }

    #region Additional test attributes
   
//
    // You can use the following additional attributes as you write your tests:
    //
    // Use ClassInitialize to run code before running the first test in the class
    [ClassInitialize()]
   
public static void MyClassInitialize(TestContext testContext)
    {
      provider =
new SqlDataProvider();
      provider.DefaultConnectionString =
"server=(local);database=UnitWarehouse;UIS=sa;PWD=pass@word1;";
    }
    

    #endregion

    [TestMethod]
   
public void GetBackendForDallasColo()
    {
     
//expected
      int backendId = 1;
     
string backendName = "Dallas Colo";

      ISubSonicRepository repository = new SubSonicRepository(provider);

      Backend backend = repository.Get<Backend>(1);

      Assert.AreEqual(backendId, backend.BackendId, "Backend Id is different");
     
Assert.AreEqual(backendName, backend.BackendName, "Backend name is different");

    }

    [TestMethod]
   
public void GetAllBackends()
    {
     
BackendCollection coll = new BackendCollection();
      coll.Load();

      Assert.IsTrue(coll.Count == 4, "There are not four items in the collection");
    }

    [TestMethod]
   
public void AddtoCollection()
    {
     
Backend backend = new Backend();
      backend.BackendName =
"My Backend";
     
ISubSonicRepository repository = new SubSonicRepository(provider);
      repository.Save(backend);
    }

  }
}

 
 
Well, that is it for now. I will shared more as I get into my own tests.
 
Advertisements

Update on Miranda


Some things in life just suck. Does not matter how you slice a sh*t sandwich, it is still sh*t. Other things don’t suck as much. We have a situation that sucks, but I am not sure if it really sucks or just sort of sucks. And doctors wonder why so many parents go to complementary or alternative medicine.
 
As many of you know, my daughter Miranda has been fighting cancer since some time last year (diagnosed with Ewing’s Sarcoma on September 1, 2007). In early September, they removed some nodules from her lungs (or at least we thought they removed all of them). Apparently, they did not remove one of them. During the treatment, it did not shrink, which led them to believe that the nodule was not tumorous, as the main tumor reacted fine. On her CT scan yesterday (my birthday), the nodule has grown from 2mm to 4mm. Her oncologist did not call until late, as he and the radiologist pulled out all of the film and examined the history of CT scans she has had. That is how they noticed that the spot had not grown or shrunk over the entire time of treatment.
 
Dr. Ho, her oncologist, has told me it is not a major cause of concern, but all of the things I read suggest it is more likely bad news than good. I am, once again, learning more about cancer than I ever intended. The questions to ask are:
  1. Is the nodule calcified. Not a firm indicate it is benign, but a good sign
  2. Is the nodule smooth edged or not? Smooth is generally better.
  3. If it was your daughter, would you wait a month to find out if it grew?

We are now in the position of decided whether to operate or wait until the next scan. The fact the other nodule was not cancerous is good news. The fact this one is growing is not. If it is benign, you don’t want to make your daughter go through an operation. If it is not, you want to know as quickly as possible, to avoid further metastasis. At 4mm, it is very small (a bee bee, if you will), so it is not that dangerous, but cancer is a tricky fellow and we really know so little about it.

Doctors generally give you odds, when they are being honest. They know that x out of 100 patients make it five years without incident. But, for each child it is not a percentage. It is either 0% (the child dies) or 100% (the child lives). The question I have to ask is whether the odds are better with surgery (some risk) or with waiting (some risk).

It is my sincere hope we are just a bit too paranoid and everything is going according to schedule.

BTW, there is some hope on the horizon. President Bush signed the Conquer Childhood Cancer Act, which pumps $150 million into childhood cancer research. And, there is a targeted drug for Ewings … unfortunately, it will not be used in humans for years to come.

Peace and Grace,
Greg

Code Generating the Repository Pattern with Substage (Subsonic 2.1)


First, I was wrong in my last post and want to correct my statement (will correct in the post soon). You do not have to specify a web root to generate with SubStage. The tool is just not as well documented as I had hoped at first blush. Considering it is an open source project and still in development, that is not a big deal. When you play with projects as they are being developed, you have a few times where you get a bit burned. Wink
 
Now to the fun. In order to generate Repository code, here are the instructions.
 

Add a New Project

Click on the box with the plus in the upper left hand cornder (just below the menu):

Substage - create new project

The only property you have to change here is the name, which I set to UnitWarehouse. Other potential properties to hit are:

TemplateDirectory – if you have your own custom SubSonic templates
EnableTrace – for projects you wish to trace

Add a Connection String

Right click on the connection string node and choose Add Connection String

Substage - Add connection string 1

Now alter the properties to fit your database and name it something other than New Connection String. For mine, I am working with a work project called UnitWarehouse, so my properties are as follows:

ConnectionString: Data Source=(local); Database=UnitWarehouse; Integrated Security=true;
Name: UnitWarehouse

The name is important for a future step.

Add a Provider

Right click on the project and choose Add Provider.

Subsonic - Add new provider

There are tons of properties here, but there are only two that are mandtory for my first pass:
 
Name: UnitWarehouse
TableBaseClass: RepositoryRecord (default is ActiveRecord)
 

Invoke Providers

The next step is to query the provider(s) and find out what they contain. Click on the Invoke Providers button at the upper left (below the menu).

Subsonic - Invoke Providers

This will take a few seconds, but you end up being able to expand the UnitWarehouse provider now, yielding the following:

Subsonic - After Invoke

Generate Code

Before doing this, I would click on the SubStage configuration and place your code where you want. This is done by changing the CodeGenerationPath property. You can go witht he default, which is under the Program Files where Subsonic is installed. I am not fond of this location, however.

Click on the Provider again and then click the Generate Code button. It is the middle above the left pane.

SubSonic - Generate code

This happens fairly quickly.

First Blush

It looks like this will save me some time. I am not seeing the actual repositories created here, but that is not a huge deal, as I can code this out. I also notice there is a stub for foreign keys (and it recognizes them), but it is not there. I will have to look at the roadmap. Overall, however, I am interested in learning more, so I think I may have found a solution. I do not want to return to .NET tiers, as it painted us into a box last time. It may have improved now, but it is Active Record, not repository, so I don’t want to go there.

Before settling in, I will take a look at CodeSmith, just to be sure there are not any good Repository templates. But, thus far, I am willing to continue to implement SubSonic and see where it leads me.

Peace and Grace,
Greg

Is Cuil really cool?


I was reading a few sites today and found that Anna Patterson, former Google employee (architect?) and her husband Tom Costello are launching a search engine called Cuil (pronounced "cool"). My first impression is not that I am not that impressed.
 

Relevance

 
I ran a few searches on Cuil and Google. The Cuil search consistently got more pages, when it did not give me a "search produced no results" page. On the other side, many of the top results were pure SPAM. Here is an example. Run McDonalds Disney in both engines. In Google. the top link is "McDonalds Dumps Disney".
 
google.
 
In fact, ther results are as follows (all relevant):
 
  • 6 on Disney dumping McDonalds
  • 2 on Disney, McDonalds and China (labor issues)
  • 1 on Disney and McDonalds, pre split
  • 1 on the Downtown Disney McDonalds

ALL 10 relevant to my search.

The same thing in Cuil results in the following:

cuil

Some impressions here. Wow, that looks great. I like the additional features. If I were an eye candy man, I would be sold. But, I spend too much time preaching proper functionality to let a bit of eye candy steer me. Here are the results

  1. Redirects to http://www.adxtn.com/, a "search" page.
  2. Redirects redirects to http://www.adxtn.com/, a "search" page.
  3. Redirects redirects to http://www.walmart.com/rollbacks?dest=120807&sourceid=03237428460627726046 – an affiliate redirect
  4. Site selling disney toys
  5. Redirects to http://www.adxtn.com/, a "search" page.
  6. Same sales site as #4
  7. Same sales site as #4
  8. Same sales site as #4
  9. directs to http://www.adxtn.com/, a "search" page.
  10. Same sales site as #4
  11. Site selling trains (http://kit.pchot1079.com/anniversary.html)

At least 5 of the links do go to something Disney (no McDonalds), but all are on the same site. Seems like it would be easy to figure out how to fake things to be the top site on this search engine.

Thus far nothing useful to me. So, let’s refine our search and type in Disney Dumps McDonalds, the story I am looking for. Result:

We didn’t find any results for “Disney Dumps McDonalds”
 
As you add words, Cuil begins to find less and less, primary not relevant, so it looks worse. I tried a few searches I know return results and was pleased by most of what Google returned.
 
Result: Google wins hands down.

Kid Friendly?

Ouch! How about we try something a bit more risky and type in "redhead". Google seach finds "red hair" (wikipedia), "redhead", a you tube video, redhead brass, realm of redheads, flickr: "redhead", redhead blog and blonde redhead. Of these, all are probably safe to visit for children. Cuil returns 3 sites on Blonde Redhead, 2 redhead blogs, the redhead public school a redhead lovers site and 5 porn sites. Okay, so Cuil is far less kid friendly than Google.

What about Blonde Redhead (a group)? All links on both google and cuil are relevant.

Lesson learned: Teach kids to search properly.

To be fair, I hit on words like plump and foot, as both are innocent words that can be fetishy, and google faired worse on plump, so there is no 100% kid friendly search amongst the "big boys".

Result: Tie, although on hair color, Cuil serves up far more … (pun intended) 

Speed

Google returns results in a fraction of a second no matter what I am seeking. Cuil can be nearly immediate to agonizingly slow. Perhaps once the slashdotters are finished on it, it will return more quickly?

Result: Google wins hands down

Other

I did some Undernet type of searches and nearly the entire front page goes to sites trying to install software on my computer. The same searches on Google yield safer sites, although many are still garbage. When I say Undernet , I am talking about security searches when you are looking for hacks. I am sure searches for warez and other illegal activities would reveal the same type of pop ups and redirects. Google fared far better in these types of searches, as the first page in Cuil was generally a lot of pages trying to install something on my computer.

Summary

The site is impressive looking. I like the layout of the searches. Finding a relevant search is nearly impossible from my tests. Yours might return something better and perhaps this will improve in the future. Currently I see no reason to use Cuil, unless you want your search results to be a bit prettier than Google. Considering SPAM is very often the first page of links, I would find it exasperating to find a good hit. I will not switch.

There is also the bug of not getting results one minute and tons of results the next. I think this might be related to traffic and I really hope they are getting slammed, as if this is a light day, the scalability sucks.

My suggestions for Cuil (if they care)

  • Focus less on hype (we catalog more pages than Google) and more on quality searches
  • Determine why the engine fails on searches that later work
  • Cull out the SPAM (any search phrase with is before it is probably SPAM hsdfas is Disney McDonalds seems to always lead to garbage)
  • Find out why the search engine falters for a long time

I would also recommend not press releasing the world until you get slammed up against the wall a few times by us geeks. We will probably give you a second chance. The world probably won’t.

Peace and Grace,
Greg

Going Subsonic


I am in the midst of retooling one of our tools at work and I need to clean up the data access (done with .NET tiers). As I was working on how to work out thedata access, I thought about Rob Conery’s MVP ECommerce series. In this project, Rob uses the Repository pattern for data access, so let’s talk about that for a second.
 

Repository Pattern

The norm you see in many ASP.NET applications, or even Windows applications for that matter, is a straight-forward progression from UI to database. It looks something like this:

Typical Flow

The problem with this model is it is hard to test your code without actually performing data access. Now, you probably know I am not against testing your data access with a unit test framework, as long as you realize these are integration tests and not unit tests. I also advocate keeping these in different classes and ultimately different assemblies, as they serve very different purposes.

The repository pattern turns this method on its ear a bit, as you feed the Repository to your code rather than have your code call the Repository. By flipping, you can easily create a mock repository, either by creating one in your test assembly (as Rob has done in his project) or by using a Mock framework (I am currently fond of Rhino Mocks, but this could just be my flavor of the month, as I am still trying to determine what exactly I really want in a mock framework). Off the tangent about mocks, the pattern looks more like this:

Repository Flow

Now, this is actually a pretty poor diagram, as you are not necessarily feeding the Repository at the business level, but you can see a bit of the inversion from "normal" flow. This is testable as you can code more like so (from Rob Conery’s ECommerce source). Note that this is only a small portion of the test repository and test code.

 

namespace Commerce.MVC.Data {

    public class TestCatalogRepository : ICatalogRepository {

 

        public IQueryable<ProductReview> GetReviews() {

            List<ProductReview> result = new List<ProductReview>();

            for (int i = 1; i <= 30; i++) {

 

                ProductReview review = new ProductReview();

                review.Author = "TestAuthor";

                review.Body = "lorem ipsum";

                review.Email = "email@nowhere.com";

                review.ProductID = i;

                review.ID = i;

                result.Add(review);

            }

            return result.AsQueryable();

        }

 

    }

}

namespace Commerce.MVC.Tests {

        [TestMethod]

        public void Review_Repository_Can_Return_Reviews() {

 

            ICatalogRepository rep=new TestCatalogRepository();

            Assert.IsNotNull(rep.GetReviews());

 

        }

    }

}

If you need a bit deeper of a look, here is the class diagram of the pattern:

Repository UML

What this tells us is we can have some generic functions in our base class and specific functions in our derived classes, so SpecificRepository is the class we are actually running (with whatever the Repository is called).

Subsonic

One thing always leads to another and I found Rob’s other project: Subsonic. Subsonic is a code free ORM, or at least that is the main vision. There is also a tool called Substage that can generate the classes for you so you can incorporate them in your own project, as Subsonic requires full trust (something you WILL NOT get with many ISPs).

I have not gotten deep enough into Subsonic to state it is definitely my ORM on this project, but I like what I see thus far. My only issue is I am not writing a web application. This leads me to two ways to create my classes:

  1. Create the project as a web project and "steal" the generated assemblies
  2. Use Substage

The later is my choice. The problem is you have to point it to a web application anyway. Thus, I am offering the suggestion that you should be able to use any valid application configuration to feed Substage to fire off the Subsonic engine to create your classes. As it stands right now, you point to the web directory and it reads web.config, so I am kludging this a bit to make it work, but I believe it would be better if you could point at a config rather than a folder.

Update: I was wrong. While the tool is focused on web output, you do not have to kludge it at all. In fact, you need not specify the web application in the configuration to get it working. I will accept my beating now. Open-mouthed

As with MVC Membership, I will eventually look at the Source code and figure out how to make this ORM easily accessible from all types of projects, without kludging. This is not a criticism of the work Rob and others have done thus far. I am not one to shoot a gift horse. I just see a bigger box than the one originally drawn and I want to see it filled.

I will blog about the kludge at some point and detail my journey through this project if I decide this is the ORM for me. My primary focus is testability and the Subsonic project utilizes the Repository pattern, so it already has one major thing in its favor. More forthcoming.

Peace and Grace,
Greg

Boycotting McDonalds


The American Family Association has decided to boycott McDonalds over their joining the National Gay and Lesbian Chamber of Commerce and a $20,000 donation to the organization. It is there position that McDonalds is promoting the gay and lesbian agenda and trying to undermine traditional marriage. What has particularly gotten their rancor is a comment by Bill Whitman, McDonald’s spokesman, who stated “Hatred has no place in our culture. That includes McDonald’s, and we stand by and support our people to live and work in a society free of discrimination and harassment.”
 
Boycotting McDonalds? Now that is something I can get behind. Nah, it’s not because of the gay and lesbian thing. I could really care less. Of course, I support the AFA’s right to protest, but I believe there are far too many more important things to focus on. I also support McDonalds right to support whom they desire. It is all part of the American way.
 
I see McDonalds as a company that can make up its mind what groups to join. And, if they feel this can increase their profits, good for them. If they are doing this for ideological reasons, more power. And what about that $20,000? $20,000 from a multi-billion dollar company is chump change and nothing to get overly excited about.
 
My reason for boycotting McDonalds would be the garbage they sell. But, then I am also up for boycotting the fast food industry completely. Think about it, here is an industry that sells food that often has more than 50% of its calories from fat. In one meal you can get 2.3rds of the daily recommended fat intake for the day (that is max fat intake, by the way). And much of the fat is saturated. Kiss those arteries goodbye.
 
I have been in a mostly informal boycott of fast food for quite some time. There are a few occasions where I have broken down and ordered fast food and I am finding I really do not like it any more. Once you wean yourself away from fast food, you find that it is not really as tasty as you previously thought it was. And, if it really not that tasty, why destroy your body on it?
 
There is one thing I do agree with the AFA on. Disagreeing with others is not the same as hatred. It is commonly regarded as such in this society, where our "news" shows are more about different talking idiots screaming at their guests. And, it is common on the Internet, where logical fallacy has been elevated to an artform. But, it should not enter into our news media, who is supposed to be reporting the news, not forcing us into adopting a certain viewpoint.
 
The UPI went so far as to headline their article "Anti-gay group to boycott McDonalds". I find this to be irresponsible for a news organization, as they are supposed to report the news, not present commentary disguised as a news article. I am not sure I can name  group whose primary charter is anti-anything. There are many times when groups get more bang for the buck out of negatives, of course, but it is hard, if not impossible, to sustain indefinitely. And, if that is your major focus, you either have to morph or die.
 
Peace and Grace,
Greg

Editing Visual Studio Templates


I have seen a couple of posts lately with people asking how to customize what VS spits out when you create a new item in a project, so I decided to post. This post applies to Visual Studio 2008 only. For 2005 and earlier, the templates are still in roughly the same place, but they are not zipped up (actually making it easier to customize them?).

Editing the files

First, we need to find the templates. There are a variety of templates, and it depends on what you want to edit. The general location is:

C:Program FilesMicrosoft Visual Studio 9.0Common7IDE

Or for 64 bit

C:Program Files (x86)Microsoft Visual Studio 9.0Common7IDE

There are numerous directories under this folder, but we are only interested in two for most of our work: ItemTemplates and ProjectTemplates. These folders contain (big surprise coming ;->) item templates and project templates.

Folder

Let’s look at a web project template first. The zip file is located at:

C:Program FilesMicrosoft Visual Studio 9.0Common7IDEProjectTemplates{language}Web1033

We will open up the WebApplicationProject.zip file. Inside we find the following (pictured below):

WebProject

Opening the default.cs file yields the following:

using System;

using System.Collections;

using System.Configuration;

using System.Data;

$if$ ($targetframeworkversion$ == 3.5)using System.Linq;

$endif$using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

$if$ ($targetframeworkversion$ == 3.5)using System.Xml.Linq;

$endif$

namespace $safeprojectname$

{

      public partial class _Default : System.Web.UI.Page

      {

            protected void Page_Load(object sender, EventArgs e) 

            {

 

            }

      }

}

Now lets move up to a new class template for a web project. You find this at:

C:Program FilesMicrosoft Visual Studio 9.0Common7IDEItemTemplatesWebCSharp1033

The file is webform.zip and we will want to edit codebeside.cs. The only real difference here is highlighted below:

public partial class $codebesideclassname$ : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

 

    }

}

Tags available

Here are a list of some of the tags you might want to use to customize your templates.

·         $clrversion$ – current version of the CLR

·         $guid#$ (where # is a number between 1 and 10) – GUID that replaces the GUID in the project file

·         $itemname$ – Name provided by user (note that the web team has stepped out of the box here

·         $machinename$ – machine created on

·         $projectname$ – Name given in the new project dialog

·         $registeredorganization$ – Registry key value for HKLMSoftwareMicrosoftWindows NTCurrentVersionRegisteredOrganization

·         $safeitemname$ – Name provided by user with all unsafe characters replaced

·         $safeprojectname$ – ditto, but for a project

·         $time$ – Current date time in the format DD/MM/YYYY HH:MM:SS

·         $userdomain$ – Current user domain

·         $username$ – Current user name

·         $year$ –Current year in the format YYYY

Please note that the $time$ variable is in the format DD/MM/YYYY HH:MM:SS and is not localized for culture. This is probably not a big deal, but it should be noted. Here are a few “undocumented” tokens:

·         $fileinputname$ – unsafe file name, sans extensions

·         $fileinputextension$ – extension of above

·         $runsilent$ – In template, no clue what this does (Boolean value)

·         $itemname$ – unsafe item name

·         $itemrootname$ – Seems to be the same as above?

·         $rootname$ – ditto

·         $safeitemrootname$ – Safe file name without extension

·         $rootnamespace$ – Namespace at level you are creating your class.

Some people have stated that $rootnamespace$ is the namespace for the root of the project, indicating there is a different tag when you are going deeper. I have not found this to be true, which indicates this is the namespace at the root of the folder you are creating in. Not as big a deal for web projects, but it does have implications for windows programs, where you can add a folder and have the folder name automagically appended to your namespace.

Note that you can also create your own custom templates and pass custom parameters to them:

http://msdn.microsoft.com/en-us/library/ms247063(VS.80).aspx

The launch page for templates is here:

http://msdn.microsoft.com/en-us/library/6db0hwky(VS.80).aspx

Hope this helps!

Peace and Grace,
Greg