WELCOME

This blog is where I post about my consulting work with Microsoft Technologies, and other random tidbits that don't fit in my Photo Blog or my Iraq Blog.

Monday, December 8, 2008

Configuing VS2008 (or VS2010) and TFS to use Beyond Compare

I've been really enjoying using Visual Studio 2008 and TFS for production development for the first time, but I hate the default file compare tool.

Here is a great blog post with simple instructions on how to configure VS2008 to use Beyond Compare (the best windows file comparison tool):

http://ronaldwidha.net/askbobo/articles/the-best-comparison-tool-and-vs2008-integration/

Friday, November 21, 2008

Geek notes: Windows on Amazon EC2 and Terminal Server (RDP) Client for iPhone

I've been playing with the new Windows Servers in Amazon EC2. Hosted Windows 2003 Servers for $0.125 per hour... fire one up in a couple minutes and terminal server into it for a couple hours, and turn it off until you need it again... very cool!

http://aws.amazon.com/windows/

I've been thinking about setting up a virtual developer workstation this way, as well as development/test servers.

On a somewhat related note: terminal server (RDP) client for iPhone!

http://www.dabcc.com/article.aspx?id=8387

Thursday, November 13, 2008

VS2008 question: How do you make a unit test ONLY run as part of an Ordered Test?

The title of this post pretty much says it all. Visual Studio 2008 supports "Ordered Tests", which are a pretty slick way to run a set of Unit Tests in a set sequence.

Back in the day we had to create one unit test that called the other tests in order to achieve this.

So the new "Ordered Test" is cool except for one problem that I haven't been able to figure out: How do I make a unit test ONLY run as part of an Ordered Test?

The whole point of using the Ordered Test in my case is that I have a bunch of methods with data dependencies that can ONLY be run in a specific order. But I can't figure out how to disable them from running individually... grrr!

I'm sure there is a way to do this, but I haven't been able to figure it out. Your help greatly appreciated!

Friday, August 8, 2008

A little more about me

I had to come up with a bio for an upcoming speaking engagement, and I decided I should have a little more fun with it than the dry weak bit of fluff that I've used in the past... Here it is:

Eric Bowen is a former Microsoft Architect Evangelist and currently a Principal Consultant at ILM Professional Services specializing in enterprise architecture and technical project leadership of complex projects using Microsoft technologies. Eric has been programming for 28 years since he taught himself Z80 assembly language on his family's TRS-80 Model I Level II. And he has still never worn the t-shirt that Bill Gates signed when he won the programming contest at the Microsoft PDC in 2001.

In his spare time Eric works as a photojournalist providing independent coverage of the Minnesota National Guard and the war in Iraq. Eric has made multiple trips to Iraq, and his work has appeared locally on Channel 5 Eyewitness News and MinnPost.Com, as well as nationally on the CBS Evening News and in Parade Magazine. Eric is also a former US Army Paratrooper, and former member of the US National Biathlon Team.

Thursday, July 24, 2008

Implementing a simple HelloWorld service in WCF using Interfaces and generic proxies

I needed a complete end to end demonstration of a .NET service implemented in WCF and taking advantage of Interface based contracts and generic proxies. I found lots of bits and pieces on the web, but I thought I would post my complete demo here in case somebody else finds value in it...

First the interface that defines our service contract:


using System;

using System.Collections.Generic;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

namespace SandBox.SharedClassLibrary

{

[ServiceContract]

public interface IHelloWorld

{

[OperationContract]

string GetHelloWorld(string Request);

}

}



The service itself (note in this case we are hosting the service in a ASP.NET project on IIS 7.0):


using System;

using System.Collections.Generic;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

using SandBox.SharedClassLibrary;

namespace SandBoxWeb

{

public class HelloWorldService : IHelloWorld

{

public string GetHelloWorld(string Request)

{

return Request + DateTime.Now.ToShortTimeString();

}

}

}



The web.config for the service:


<system.serviceModel>

<behaviors>

<serviceBehaviors>

<behavior name="SandBoxWeb.Service1Behavior">

<serviceMetadata httpGetEnabled="true"/>

<serviceDebug includeExceptionDetailInFaults="false"/>

</behavior>

</serviceBehaviors>

</behaviors>

<services>

<service behaviorConfiguration="SandBoxWeb.Service1Behavior" name="SandBoxWeb.HelloWorldService">

<endpoint address="" binding="wsHttpBinding" contract="SandBox.SharedClassLibrary.IHelloWorld">

<identity>

<dns value="localhost"/>

</identity>

</endpoint>

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

</service>

</services>

</system.serviceModel>



The client application which is a console application:

using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;

using System.ServiceModel;

namespace SandboxConsole

{

class Program

{

static void Main(string[] args)

{

Console.WriteLine(SandBox.SharedClassLibrary.ServiceClient.CallServiceByName("WSHttpBinding_HelloWorldService"));

Console.WriteLine(SandBox.SharedClassLibrary.ServiceClient.CallServiceByAddress("http://localhost:3456/HelloWorldService.svc"));

Console.ReadLine();

}

}

}




public class ServiceClient

{

public static string CallServiceByName(string EndPointName)

{

using (GenericProxy<IHelloWorld> service = new GenericProxy<IHelloWorld>(EndPointName))

{

return service.Channel.GetHelloWorld("Test by Name");

}

}

public static string CallServiceByAddress(string EndPointAddress)

{

Binding _binding = new WSHttpBinding();

EndpointAddress _endpointAddress = new EndpointAddress(EndPointAddress);

using (GenericProxy<IHelloWorld> service = new GenericProxy<IHelloWorld>(_binding, _endpointAddress))

{

return service.Channel.GetHelloWorld("Test by Address");

}

}

}



The (optional) app.config for the console application. This very verbose version was created for demonstration purposes using the "Create Service Reference" command.

Note: The second version of our call doesn't use the app.config at all.


<system.serviceModel>

<bindings>

<wsHttpBinding>

<binding name="WSHttpBinding_HelloWorldService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">

<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>

<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>

<security mode="Message">

<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>

<message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true"/>

</security>

</binding>

</wsHttpBinding>

</bindings>

<client>

<endpoint address="http://localhost:3456/HelloWorldService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_HelloWorldService" contract="SandBox.SharedClassLibrary.IHelloWorld" name="WSHttpBinding_HelloWorldService">

<identity>

<dns value="localhost"/>

</identity>

</endpoint>

</client>

</system.serviceModel>



Finally our GenericProxy class that creates the Channel that we use to call the service:


public class GenericProxy<T> : System.ServiceModel.ClientBase<T> where T : class

{

T _serviceInstance;

public GenericProxy(string endpointName)

: base(endpointName)

{

}

public GenericProxy(Binding ServiceBinding, EndpointAddress ServiceEndpointAddress)

: base(ServiceBinding, ServiceEndpointAddress)

{

}

public new T Channel

{

get

{

if (_serviceInstance == null)

{

//this.ChannelFactory.Credentials.UserName.UserName = "user";

//this.ChannelFactory.Credentials.UserName.Password = "123456";

_serviceInstance = this.ChannelFactory.CreateChannel();

}

return _serviceInstance;

}

}

}

Tuesday, July 15, 2008

My client doesn't allow the use of Foreign Key Constraints in SQL Server

I'm working on a project at a Fortune 500 Microsoft customer and ran across something interesting: They DO NOT allow foreign key constraints in production SQL Server databases. The theory being that they have negative performance impact, and that developers can check for related data as needed in stored procedure code.

This is new to me, but I wanted to double check with some SQL Gurus before I call their baby ugly... :-)

Here is a great response from my friend Brian:

"Their baby is UGLY! But you really can't tell a parent that!

They are correct, you do take a noticeable hit ( seen up to 5% on heavily updated DB's)
In particular you can see a lot locking and deadlocks.

However I've yet to see development staff that consistently check the data or deal properly with errors and/or partial rollbacks! I'll put money on the fact they have corrupt data!

I like FK's because they 'document' the DB and I use them to automate data archiving.

That said, I am in the process of converting my current app to ignore FK relationships.
(We do 24,000,000 + insert/update/deletes daily so performance is an issue)

I define relationships in the DB.
Enable then in Dev and Test to facilitate testing.
Disable them in perf and prod for performance

Once a day/week check the FK's. Not much more expensive than DBCC CheckDB
IF we find corrupt data, we enable the FK so we throw errors to facilitate route cause analysis.
Note this happens regularly after a code release ;) A little less often when new customer/data patterns hit the DB.

While this is not a 'Best Practice' it is a better than what they are doing today. "


Example code:

-- Create the tables and populate with valid data
use tempdb
go

if object_id('child') is not null drop table child
if object_id('parent') is not null drop table parent
go

create table parent (id int primary key)
create table child (id int primary key, pid int)
alter table child with nocheck add constraint FK_child_parent foreign key ( pid) references parent(id) -- Use 'with nocheck' so FK can be added even if existing data is corrupt
go

insert into parent values (1)
insert into parent values (3)
insert into child values (1, 1)
insert into child values (3, 3)
go

-- Try adding invalid data
insert into child values (2, 2)
go

-- Disable FK and try again
alter table child nocheck constraint FK_child_parent
insert into child values (2, 2)

-- Check the table
DBCC checkconstraints (FK_child_parent)

-- Enable the FK so code now throws errors
alter table child with nocheck check constraint FK_child_parent -- Use 'with nocheck' so existing corrupt data is ignored, but new data will error
insert into child values (2, 2)