tag:blogger.com,1999:blog-62523845448644187082024-03-12T21:20:19.795-07:00Adventures in .NET, SQL, and other software developmentThis blog is for me to discussion issues I've had with software development as well as solutions to some difficult problems I have found.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.comBlogger19125tag:blogger.com,1999:blog-6252384544864418708.post-66975595188573434472014-09-21T19:17:00.001-07:002014-09-21T19:28:54.021-07:00Constructor ParametersIt's funny, in all my years of writing software I have never given much thought to when I should use parameters in a constructor verses setter properties (or getXXX / setXXX methods for you Java people). I always just picked it based upon what I saw as convenience. Usually convenience to me meant less lines of code. For example:<br />
<br />
MyClass myClass = new MyClass("hello world");<br />
<br />
Is shorter than saying:<br />
<br />
MyClass myClass = new MyClass();<br />
myClass.Text = "hello world";<br />
<br />
But the other day I was once again overriding the GetHashCode method for a .NET class because I had overridden the Equals method and you should override both at the same time. Usually I just don't care much about this method and write some probably incredible poor hashing method (aka, GetHashCode of some properties)<br />
<br />
Well, I decided to do a bit of a Google for a proper hash method. I actually found some <a href="http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode" target="_blank">very interesting proposals </a>and looked to implement some of them. All of the methods of overriding GetHashCode look at using the fields in the class to develop a unique hash.<br />
<br />
Now, the important thing about the GetHashCode method is that the result from it <i><b>must be </b></i>immutable for the class. Since we are basing our hash off of some class fields, those fields must now also be immutable. <br />
<br />
Let's say you have a class called Person. It would seem reasonable that the hash code be based upon the person's name. Every class with a name of John Doe should generate the same hash code.<br />
<br />
But here in comes the problem, what if the name changes? We want the GetHashCode to always return the same thing for the class and we need the name to be immutable now. This is especially important if that class is added to a list or becomes a key to a dictionary. <br />
<br />
And so here I was lead to my "AH HA!" moment. Parameters passed in with the constructor should be considered immutable and define the class for its life time. <b><i> Any constructor parameter should not be allowed to be changed after the instantiation of the class</i></b>. This way the GetHashCode always returns the same value regardless. So, my person class gets a constructor of Person(string firstName, string lastName). Now forever going forward those two properties are fixed to the class and the GetHashCode always works.<br />
<br />
Class fields that are accessed via set properties (or setXXX methods) are mutable and therefore cannot be used for hashing. So, for my Person I may have mutable properties, but the name is now considered fixed.
<br />
<br />
Person myPerson = new Person("Jane", "Doe");<br />
myPerson.Slogan = "Hello World!!!";<br />
<br />
In this case, the name is immutable, whereas the slogan is not. The slogan cannot participate in hashing. <br />
<h2>
<b>In Conclusion</b> </h2>
I am proposing that class constructor parameters be immutable and used to define the class when implementing of the Equals and GetHashCode methods. Alternatively, getter/setter properties or methods for immutable properties should throw an exception if a calling method attempts to change the value.<br />
<h2>
A word of caution</h2>
All constructor parameters that participate in the hash code themselves must also be immutable. Following this principle though out your classes will ensure that, but if parameter's object can change its hash code, then your classes hash code is no longer fixed.<br />
<h2>
</h2>
<br />
Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-89949138734459005462014-05-14T17:44:00.001-07:002014-05-14T17:44:03.012-07:00Simplied reading of codeSo I recently was working on refactoring a piece of code I found online. It was this:
<pre class="csharpcode"><span class="kwrd">if</span> (<span class="kwrd">this</span>.itemUnderDragCursor == newItem)
<span class="kwrd">return</span>;
<span class="rem">// The first pass handles the previous item under the cursor.</span>
<span class="rem">// The second pass handles the new one.</span>
<span class="kwrd">for</span>( <span class="kwrd">int</span> i = 0; i < 2; ++i )
{
<span class="kwrd">if</span>( i == 1 )
<span class="kwrd">this</span>.itemUnderDragCursor = newItem;
<span class="kwrd">if</span>( <span class="kwrd">this</span>.itemUnderDragCursor != <span class="kwrd">null</span> )
{
UIElement item = <span class="kwrd">this</span>.GetSelectorItem(<span class="kwrd">this</span>.itemUnderDragCursor);
<span class="kwrd">if</span>( item != <span class="kwrd">null</span> )
SelectorItemDragState.SetIsUnderDragCursor( item, i == 1 );
}
}</pre>
Now looking at this code, it's tough to tell what exactly it does. Refactoring it, same functionality, but much easier to read:
<!-- code formatted by http://manoli.net/csharpformat/ -->
<pre class="csharpcode">
<span class="kwrd">void</span> UpdateItemUnderDragCursor(<span class="kwrd">object</span> newItem)
{
<span class="kwrd">if</span> (<span class="kwrd">this</span>.itemUnderDragCursor != newItem)
{
SetItemSelectedState(itemUnderDragCursor, <span class="kwrd">false</span>);
itemUnderDragCursor = newItem;
SetItemSelectedState(itemUnderDragCursor, <span class="kwrd">true</span>);
}
}
<span class="kwrd">private</span> <span class="kwrd">void</span> SetItemSelectedState(<span class="kwrd">object</span> itemToSetState, <span class="kwrd">bool</span> state)
{
<span class="kwrd">if</span> (itemToSetState != <span class="kwrd">null</span>)
{
UIElement item = <span class="kwrd">this</span>.GetSelectorItem(itemToSetState);
<span class="kwrd">if</span> (item != <span class="kwrd">null</span>)
SelectorItemDragState.SetIsUnderDragCursor(item, state);
}
}
</pre>
Lesson here is that code can be made complex to read and maintain or can be made easy.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-14106141084191655222012-04-03T14:47:00.002-07:002012-04-03T14:55:07.321-07:00Favoring InheritanceI started refactoring a core library used in software we've been developing for the past few years. One of the common tasks in the library is converting an object to a database primary key value, which is always an int.<br />
<br />
The code was littered with the following checks at the top of every method. Of course it changes based upon the type, but the logic was the same. And worse, since I wrote the same check over and over again, I inconsistently implemented my logic checks. The general idea is to check that object is a provided type, check that the provider is a specific instance type, then get the ID:<pre class="csharpcode"><span class="kwrd">if</span> (patient <span class="kwrd">is</span> PathProvidedPatient == <span class="kwrd">false</span>)
<span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="str">"Patient argument must be of type PathProvidedPatient"</span>);
<span class="kwrd">if</span> (((PathProvidedPatient)patient).IPatientProvider <span class="kwrd">is</span> WCF_PatientProvider == <span class="kwrd">false</span>)
<span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="str">"Patient argument property IPatientProvider must be a WCF_PatientProvider class."</span>);
WCF_PatientProvider patientProvider = ((PathProvidedPatient)patient).IPatientProvider <span class="kwrd">as</span> WCF_PatientProvider;
int PatientID = patientProvider.GetPermanentObjectKey(patientProvider.GetObjectKey((PathProvidedPatient)patient));
</pre>My first step at refactoring this code was to pull this repeated code out into methods:<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">int</span> GetPatientId(PathPatient patient)
<span class="kwrd">public</span> <span class="kwrd">int</span> GetCaseId(PathCase Case)
<span class="kwrd">public</span> <span class="kwrd">int</span> GetSampleId(PathSample Sample)</pre>Etc...<br />
<br />
This cleaned up the code quite a bit! But suddenly I was hit with another problem. While these individual functions knew the type, I had refactored earlier and created some generic functions to take a IPathWithObjectID, from which all the "provided" versions of the objects derive. Now I was in trouble!<br />
<br />
A little background. Using a classic <a href=http://en.wikipedia.org/wiki/Bridge_pattern">Bridge Pattern</a>, a provided implementation stores a reference to an ObjectID and a provider class. When a request comes into the provided object, it turns it around and calls the provider class with the objectID to fulfill the request.<br />
<br />
And now back to the story at hand... my first go around looked something like this:<pre class="csharpcode"><span class="kwrd">if</span> (myObject <span class="kwrd">is</span> PathSample)
<span class="kwrd">return</span> GetSampleId((PathSample)myObject);
<span class="kwrd">if</span> (myObject <span class="kwrd">is</span> PathPatient)
<span class="kwrd">return</span> GetPatientId((PathPatient)myObject);
<span class="kwrd">if</span> (myObject <span class="kwrd">is</span> PathCase)
<span class="kwrd">return</span> GetCaseId((PathCase)myObject);
</pre>Uh oh! This isn't looking very good. Multiple if statements or a switch statement usually is a sign of a poor design. <br />
<br />
What is needed here is abstraction. What really should happen is the provider should know how to get the database ID value. But how do we get the provider? <br />
<br />
The first thing I looked at was provider hierarchy.<br />
<br />
All WCF_XXXProvider classes implement their corresponding IXXXProvider interface that implements a common interface IPathProvider.<br />
<br />
So far so good, every provider is deriving from a common type of IPathProvider.<br />
<br />
I next looked at the Provided Objects inheritance hierarchy.<br />
<br />
PathProvidedXXX classes all implement the IPathProvidedObject interface that implements the IPathWithObjectID interface.<br />
<br />
Again, looks good!<br />
<br />
I decided to add a property to the IPathProvidedObject interface:<pre class="csharpcode">IPathProvider Provider { <span class="kwrd">get</span>; }</pre>Now, I had to go implement that property in each of the derived classes. A pain, but no challenges because every provided class already has a property that is deriving from IPathProvider.<br />
<br />
OK, so now regardless of the provided object, I can retrieve the provider via my new property and the ObjectID (via a property required by the IPathWithObjectID interface). So far, so good.<br />
<br />
Next I turned to looking at my specific provider implementations. All of my providers implement the WCF_IProvider interface as well as the IXXXProvider interface. This is good as well. <br />
<br />
I added another method to the WCF_IProvider:<pre class="csharpcode"><span class="kwrd">int</span> GetObjectPermanentIdentifier(IPathProvidedObject <span class="kwrd">obj</span>);</pre>And then implemented this method in each of the classes that implement the WCF_IProvider.<br />
<br />
So my large if statement mess cleans up nicely into a very simple method:<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">int</span> GetPermanentObjectKey(IPathProvidedObject obj)
{
<span class="kwrd">if</span> (obj.Provider <span class="kwrd">is</span> WCF_IProvider)
{
<span class="kwrd">return</span> ((WCF_IProvider)obj.Provider).GetObjectPermanentIdentifier(obj);
}
<span class="kwrd">return</span> 0;
}</pre>So, what is the advantage?? <br />
<br />
First off, the code is simple. It is easy to read and understand. <br />
Second, it is extendable. When I add a new class (which I am sure I will), I will not forget to update some massive if statement. In fact the compiler will force me to implement the correct functionality by requiring me to implement the members of the interface.<br />
<br />
Learning to program is not the same thing as learning to be a software engineer. It takes finesse and there is an art to making good code. But once you learn it, your code will be flexible, maintainable, and easy to test.<br />
<br />
And having a good suite of unit tests enables you to refactor and validate your changes.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-3326764882297660982012-03-22T15:58:00.001-07:002012-03-22T15:58:56.635-07:00Abstraction by methods..I recently wanted to refactor a database connectivity framework to support another type of key in the system.<br />
<br />
At first glance, this seemed easy. Every object implements an interface called IPathWithObjectID, that specifies the object must have a property:<br />
object ObjectID { get; }<br />
<br />
Since ObjectID can be any object, it should be trivial to switch things to a string or something else.<br />
<br />
The problem, however, lies in the details.<br />
<br />
Most methods did this:<br />
<br />
int ID = (int) MyObject.ObjectID;<br />
<br />
At the time it seemed simple enough, but in hindsight, this is very limited.<br />
<br />
A better approach would be to encapsulate the type cast into a method, which is what I refactored the code to do:<br />
<!-- code formatted by http://manoli.net/csharpformat/ --><br />
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">int</span> GetObjectKeyAsInt(IComparable ObjectKey)
{
<span class="kwrd">if</span> (ObjectKey != <span class="kwrd">null</span>)
{
<span class="kwrd">if</span> (ObjectKey <span class="kwrd">is</span> <span class="kwrd">int</span>)
<span class="kwrd">return</span> (<span class="kwrd">int</span>)ObjectKey;
<span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="str">"The ObjectKey property is expected to be of type 'int'."</span>);
}
<span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="str">"The ObjectKey is null!"</span>);
}</pre><br />
Now, in reality all this method does is do a type cast, with some checks. But the power in it is later on I can refactor what is stored in the ObjectID.<br />
<br />
So, my code goes from:<br />
<br />
int ID = (int) MyObject.ObjectID;<br />
<br />
To<br />
<br />
int ID = GetObjectKeyAsInt(MyObject.ObjectID);<br />
<br />
Maybe I want an ObjectID to be a new class called MyDataKey. Rather than changing hundreds of different places across the code base, I just change one. The GetObjectKeyAsInt method.<br />
<br />
Methods provide a powerful mechanism of abstraction. Use them as often as possible, even if the action seems as trivial as a typecast.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-66507600055833095242011-02-21T22:04:00.000-08:002011-02-21T22:04:38.224-08:00My take on MVVM, I like to add a "C" so we get MVVMCThere is a lot on the web about the Model-View-ViewModel (MVVM) pattern. To me, overall, it seems like a great way to go for developing testable, extensible user interfaces. However, I have run across a few areas where I'm not in total agreement, and other areas where I just think MVVM blogs just gloss over details of things that I think are really important. In my next few blog posts, I hope to outline how I see MVVM and how I have chosen to implement it. I may not be correct in everything, but I hope to present a direction to go for development.<br />
<br />
My ultimate goals are to develop code that is consistent, easy to read and follow, and hopefully automatically testable via unit testing or other automation. <br />
<br />
The first thing I propose doing is removing control logic from the ViewModel. In most MVVM implementations, you see the VM containing the control logic, for example, if a "Save" button is clicked, we see the VM responding to the command and writing the data to the database. I don't like this. It's not that having it in the VM is a bad thing, it is encapsulated and away from the view. But to me the VM should be light weight, responsible only for transforming model data into a data format easily digestible by the view and for gathering user input back from the view.<br />
<br />
By moving control logic, validation, etc. into a controller class, this allows the view model to focus on it's job, makes it easier to read, and I think makes it easier to test the controller.<br />
<br />
Here is a diagram of my structure. Unlike most MVVM models, I take into account using MVVM on custom controls as well as Main UI windows. Designing a custom control (that derives from User Control) and using the MVVM pattern requires departure from the traditional MVVM pattern.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-5VlQS5jATyc/TWIcRRDtb3I/AAAAAAAADG8/hgRQ1UNirGA/s1600/MVVMC+-+Object+Interactions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="299" src="http://4.bp.blogspot.com/-5VlQS5jATyc/TWIcRRDtb3I/AAAAAAAADG8/hgRQ1UNirGA/s400/MVVMC+-+Object+Interactions.png" width="400" /></a></div><br />
In looking at the model, we see a departure from the classic MVVM model where the view only accesses only the ViewModel. If the setup is for a top-level window, and not a control, then things become just like the classic MVVM model.<br />
<br />
But when making a user control, their are things that belong to the view in the WPF world and we really need them to notify the controller. Dependency properties are a prime example of this. They are attached to the code-behind of an XAML file, which really belongs to the view. In this case, the view needs to inform the controller module that a dependency property has been updated and let the controller respond appropriately. And the controller needs to inform the view when a dependency properties value should change. If we are not working on a user control, then everything goes back to normal MVVM where the view has no knowledge of the controller or view model.<br />
<br />
However, if we look at a dependency diagram, I think the view have knowledge of the controller is OK. After all, dependencies still only go one way and this is fine. It still allows us to replace the view with a unit test and not have anything break.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-B-GEVmh1aNA/TWIcRdSkU7I/AAAAAAAADG4/dcXgsivjecg/s1600/MVVMC+-+Dependency+flow.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="277" src="http://1.bp.blogspot.com/-B-GEVmh1aNA/TWIcRdSkU7I/AAAAAAAADG4/dcXgsivjecg/s400/MVVMC+-+Dependency+flow.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br />
</td><td class="tr-caption" style="text-align: center;"><br />
</td><td class="tr-caption" style="text-align: center;"><br />
</td></tr>
</tbody></table>It is this important that dependencies flow one way. This is critical for being able to test and for a clean architecture. The View has knowledge of the ViewModel and possible the Controller. The Controller and possible the ViewModel has knowledge of the Model. In this model, the View can be replaced without the knowledge of any of the underlying layers. <br />
<br />
Messaging up the chain takes place via events. If the ViewModel needs to notify the View of changes, this is accomplished by raising an event and allowing the View to listen for it. The WPF way of doing this is to use the INotifyPropertyChanged interface. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-ns6DarBZtDk/TWNOPEiRbPI/AAAAAAAADHQ/zSHhaIT9_g4/s1600/Events+in+MVVM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-ns6DarBZtDk/TWNOPEiRbPI/AAAAAAAADHQ/zSHhaIT9_g4/s1600/Events+in+MVVM.png" /></a></div><br />
It is critical to use interfaces whenever possible. An interface allows us to swap out components with testable components. An interface between the ViewModel / Controller and Model allows us to unit test the ViewModel / Controller by creating a mock model. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-M9AEeRDu1Cc/TWIcRo_ubRI/AAAAAAAADHA/ZNMM2e1OF_k/s1600/MVVMC+-+unit+testing.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="311" src="http://4.bp.blogspot.com/-M9AEeRDu1Cc/TWIcRo_ubRI/AAAAAAAADHA/ZNMM2e1OF_k/s400/MVVMC+-+unit+testing.png" width="400" /></a></div><br />
In developing the ViewModel and Controller, it is critical that these classes be separated from any UI components, including opening new windows. Every action within the view model and the controller should be completely contained. Opening a new window would be instantiating another view, which violates the requirement that the ViewModel and Controller have no knowledge of the View. Additionally moving things on and off the UI thread is something that belongs in the domain of the View. However, often it is the Controller that makes this move. <br />
<br />
In order to accomplish application tasks, such as opening new windows and putting things onto the UI thread, interfaces should be created to concrete classes responsible for operating in the View space. This configuration allows these objects to be mocked out during unit testing. This will be the subject of a future blog post.<br />
<br />
I hope to put some example code up soon as well. Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com1tag:blogger.com,1999:blog-6252384544864418708.post-20930344257801120052011-01-03T18:01:00.000-08:002011-01-03T18:02:58.445-08:00Using Nested classes to encapsulate View Models in User ControlsI have been working on developing some more complex user controls that will serve as the base of a lot of applications we develop. These controls will exist in a separate library of common controls. Although I am not using <a href="http://compositewpf.codeplex.com/">Prism</a>, this is following in line with the composite concept the present, having an application being composed of many different reusable user controls.<br />
<br />
I like the MVVM pattern and have made extensive use of View Models within the control. However, I do not want to really show all those "internal" view models to the users of the control. Unfortunately, traditional hiding techniques, such as internal classes are not allowed by WPF. To solve this problem, I employed a few tricks.<br />
<br />
1. Declare the constructor as internal on the public class. This prevents the applications from initializing their own instances of View Model and protects against others using your classes. This means you can more freely upgrade and modify your class as the internal needs of your control change without worrying about breaking someone else's code.<br />
<br />
2. "Hide", or at least partially hide all the "guts" of the control by putting them inside the user control class as embedded classes. When doing this, I like to have each View Model in its own file. I learned long ago that one class per file is a good rule to follow. To do this, I use the handy partial class feature.<br />
<br />
Now, these two methods don't always work. If you directly reference the View Model from the XAML, you have to make the class public. You can see the requirements for classes used within <a href="http://msdn.microsoft.com/en-us/library/ms753379.aspx#Requirements_for_a_Custom_Class_as_a_XAML_Element">XAML here</a>. However, in my case many of my view models are only instantiated in code and returned via properties (like lists of items, etc). In fact, only one of my View Models needed to be made public.<br />
<br />
Here is an example of a control's View Model. It can't be instantiated outside the control's assembly (aka, the app using it) and the class is at least somewhat hidden from view. For example, Intellisense won't show all the class names unless someone actually types out "MyUserControl.". <br />
<br />
<!-- code formatted by http://manoli.net/csharpformat/ --><br />
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> MyUserControl
{
<span class="kwrd">public</span> <span class="kwrd">class</span> MyViewModel
{
<span class="kwrd">internal</span> MyViewModel() { }
}
}
</pre>Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-43972963144006174092010-12-10T17:12:00.000-08:002010-12-10T17:12:33.807-08:00WPF Tips and Tricks - DockPanel Doesn't Behave RightConsider the following:<br />
<!--- BEGIN CODE --><br />
<div class="xml" style="font-family:monospace;color: #006; border: 1px solid #d0d0d0; background-color: #f0f0f0;"><ol><li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><DockPanel<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><ListBox</span> <span style="color: #000066;">Width</span>=<span style="color: #ff0000;">"2000"</span><span style="color: #000000; font-weight: bold;">></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #808080; font-style: italic;"><!-- Lots of items --></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></ListBox<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: bold; vertical-align:top;font-weight: bold; color: #006060;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><StackPanel</span> <span style="color: #000066;">DockPanel.Dock</span>=<span style="color: #ff0000;">"Bottom"</span> <span style="color: #000066;">Height</span>=<span style="color: #ff0000;">"35"</span> <span style="color: #000066;">Orientation</span>=<span style="color: #ff0000;">"Horizontal"</span> <span style="color: #000066;">VerticalAlignment</span>=<span style="color: #ff0000;">"Bottom"</span> <span style="color: #000066;">HorizontalAlignment</span>=<span style="color: #ff0000;">"Right"</span><span style="color: #000000; font-weight: bold;">></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><Button</span> <span style="color: #000066;">VerticalAlignment</span>=<span style="color: #ff0000;">"Center"</span> <span style="color: #000066;">HorizontalAlignment</span>=<span style="color: #ff0000;">"Right"</span><span style="color: #000000; font-weight: bold;">></span></span>OK<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></Button<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><Button</span> <span style="color: #000066;">VerticalAlignment</span>=<span style="color: #ff0000;">"Center"</span> <span style="color: #000066;">HorizontalAlignment</span>=<span style="color: #ff0000;">"Right"</span><span style="color: #000000; font-weight: bold;">></span></span>Cancel<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></Button<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></StackPanel<span style="color: #000000; font-weight: bold;">></span></span></span> </div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></DockPanel<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
</ol></div><!-- END CODE --><br />
You would think that the buttons at the bottom will always be there. But if that ListBox gets too many items, the DockPanel will happily cover up the StackPanel. That doesn't seem right since the StackPanel has an explicit height and it is explicitly docked to the bottom. The reason for this is the DockPanel renders items in the order they are entered. In this case, the ListBox gets rendered first and fills the space. The fix is simple, although does not reflect the real layout of the page. That is to flip the StackPanel and ListBox.<br />
<!--- BEGIN CODE --><br />
<div class="xml" style="font-family:monospace;color: #006; border: 1px solid #d0d0d0; background-color: #f0f0f0;"><ol><li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><DockPanel<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><StackPanel</span> <span style="color: #000066;">DockPanel.Dock</span>=<span style="color: #ff0000;">"Bottom"</span> <span style="color: #000066;">Height</span>=<span style="color: #ff0000;">"35"</span> <span style="color: #000066;">Orientation</span>=<span style="color: #ff0000;">"Horizontal"</span> <span style="color: #000066;">VerticalAlignment</span>=<span style="color: #ff0000;">"Bottom"</span> <span style="color: #000066;">HorizontalAlignment</span>=<span style="color: #ff0000;">"Right"</span><span style="color: #000000; font-weight: bold;">></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><Button</span> <span style="color: #000066;">VerticalAlignment</span>=<span style="color: #ff0000;">"Center"</span> <span style="color: #000066;">HorizontalAlignment</span>=<span style="color: #ff0000;">"Right"</span><span style="color: #000000; font-weight: bold;">></span></span>OK<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></Button<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><Button</span> <span style="color: #000066;">VerticalAlignment</span>=<span style="color: #ff0000;">"Center"</span> <span style="color: #000066;">HorizontalAlignment</span>=<span style="color: #ff0000;">"Right"</span><span style="color: #000000; font-weight: bold;">></span></span>Cancel<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></Button<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: bold; vertical-align:top;font-weight: bold; color: #006060;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></StackPanel<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"><ListBox</span> <span style="color: #000066;">Width</span>=<span style="color: #ff0000;">"2000"</span><span style="color: #000000; font-weight: bold;">></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #808080; font-style: italic;"><!-- Lots of items --></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></ListBox<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
<li style="font-weight: normal; vertical-align:top;font: normal normal 130% 'Courier New', Courier, monospace; color: #003030;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;color: #000020;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></DockPanel<span style="color: #000000; font-weight: bold;">></span></span></span></div></li>
</ol></div><!-- END CODE -->Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-65682026539815536442010-09-02T13:48:00.000-07:002010-09-02T13:49:29.853-07:00Making Test SQL DataToday I had the need to make a lot of dummy rows to test performance of a system. Often the case is when you design a query it performs great with a few thousand rows, but over the years as your data grows, things slow down. So, today I wanted to test my schema with a larger dataset. The first question was how to do that. SQL performs much better with sets, not iterations. The thought of running an INSERT statement millions of times did not appeal to me. Here's some tricks to make a lot of data "relatively" fast. I say relatively because this will still take many minutes, but not many hours. Remember, SQL is SET based! Use sets whenever possible!<br />
<br />
<div style="background-color: white; border: solid 1px black"><span style="font-family: Courier New; font-size: x-small;"><br />
<span style="color: green;"><i>-- Don't want 25M "1 Row inserted" messages!</i></span><br />
<span style="color: blue;">SET</span> <span style="color: maroon;">nocount</span> <span style="color: blue;">ON</span><br />
<br />
<span style="color: green;"><i>-- Some timing stuff, see how fast it is.</i></span><br />
<span style="color: blue;">DECLARE</span> <span style="color: #8000ff;">@a</span> <span style="color: black;"><i>DATETIME</i></span><span style="color: silver;">,</span><br />
<span style="color: #8000ff;">@b</span> <span style="color: black;"><i>DATETIME</i></span><br />
<br />
<span style="color: blue;">SET</span> <span style="color: #8000ff;">@a</span> <span style="color: silver;">=</span> <span style="color: maroon;">current_timestamp</span><br />
<br />
<span style="color: green;"><i>-- Create a temporary table to create a multiplier factor.</i></span><br />
<span style="color: blue;">DECLARE</span> <span style="color: #8000ff;">@myTable</span> <span style="color: blue;">TABLE</span> <span style="color: maroon;">(</span><span style="color: maroon;">id</span> <span style="color: black;"><i>INT</i></span><span style="color: maroon;">)</span><br />
<br />
<span style="color: green;"><i>-- Add 5000 rows to our dummy table.</i></span><br />
<span style="color: blue;">DECLARE</span> <span style="color: #8000ff;">@counter</span> <span style="color: black;"><i>INT</i></span><br />
<br />
<span style="color: blue;">SET</span> <span style="color: #8000ff;">@counter</span> <span style="color: silver;">=</span> <span style="color: black;">0</span><br />
<span style="color: blue;">WHILE</span> <span style="color: #8000ff;">@counter</span> <span style="color: silver;"><</span> <span style="color: black;">5000</span><br />
<span style="color: blue;">BEGIN</span><br />
<span style="color: blue;">SET</span> <span style="color: #8000ff;">@counter</span> <span style="color: silver;">=</span> <span style="color: #8000ff;">@counter</span> <span style="color: silver;">+</span> <span style="color: black;">1</span><br />
<span style="color: blue;">INSERT</span> <span style="color: blue;">INTO</span> <span style="color: #8000ff;">@myTable</span> <span style="color: blue;">VALUES</span> (<span style="color: #8000ff;">@counter</span><span style="color: maroon;">)</span><br />
<span style="color: blue;">END</span><br />
<br />
<span style="color: green;"><i>-- This is the big multiplier.. a cartesian product is 5000*5000=25M rows! We </i></span><br />
<span style="color: green;"><i>-- don't even need to select from the tables, but if we want we could use the</i></span><br />
<span style="color: green;"><i>-- numbers for something..</i></span><br />
<span style="color: blue;">INSERT</span> <span style="color: blue;">INTO</span> <span style="color: maroon;">uw_containers</span> <span style="color: maroon;">(</span><span style="color: maroon;">type_id</span><span style="color: maroon;">)</span><br />
<span style="color: blue;">SELECT</span> <span style="color: black;">1</span><span style="color: blue;"><span style="color: black;"> </span>FROM</span> <span style="color: #8000ff;">@myTable</span> <span style="color: maroon;">a</span><span style="color: silver;">,</span> <span style="color: #8000ff;">@myTable</span> <span style="color: maroon;">b</span><br />
<br />
<span style="color: green;"><i>-- Now create a history event for each of the new containers.</i></span><br />
<span style="color: blue;">INSERT</span> <span style="color: blue;">INTO</span> <span style="color: maroon;">uw_container_history</span><br />
<span style="color: maroon;">(</span><span style="color: maroon;">containerid</span><span style="color: silver;">,</span><span style="color: maroon;">label</span><span style="color: silver;">,</span><span style="color: maroon;">effectivestart</span><span style="color: silver;">,</span><span style="color: maroon;">effectiveend</span><span style="color: silver;">,</span><span style="color: maroon;">eventstartid</span><span style="color: maroon;">)</span><br />
<span style="color: blue;">SELECT</span> <span style="color: maroon;"> </span></span><br />
<span style="font-family: Courier New; font-size: x-small;"><span style="color: maroon;"> id</span><span style="color: silver;">,</span><span style="color: red;">'C'</span> <span style="color: silver;">+</span> CAST(<span style="color: maroon;">id AS varchar(50))</span><span style="color: silver;">,</span><span style="color: magenta;"><i>Getdate</i></span><span style="color: maroon;">(</span><span style="color: maroon;">)</span><span style="color: silver;">,</span><span style="color: red;">'12/31/9999'</span><span style="color: silver;">,</span><span style="color: black;">139059</span><br />
<span style="color: blue;">FROM</span> </span><br />
<span style="font-family: Courier New; font-size: x-small;"><span style="color: maroon;"> uw_containers</span><br />
<span style="color: blue;"></span><br />
<br />
<span style="color: blue;">SET</span> <span style="color: #8000ff;">@b</span> <span style="color: silver;">=</span> <span style="color: maroon;">current_timestamp</span><br />
<span style="color: blue;">SELECT</span> <span style="color: magenta;"><i>Datediff</i></span><span style="color: maroon;">(</span><span style="color: maroon;">ms</span><span style="color: silver;">,</span> <span style="color: #8000ff;">@a</span><span style="color: silver;">,</span> <span style="color: #8000ff;">@b</span><span style="color: maroon;">)</span><br />
</span><br />
</div>Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-54924459141198393182010-08-19T15:04:00.000-07:002010-08-19T15:04:58.056-07:00Known Values and NULL - Communication channels and when to cache"There are known knowns. These are things we know that we know. There are known unknowns. That is to say, there are things that we now know we don’t know. But there are also unknown unknowns. These are things we do not know we don’t know." - <cite style="font-style: normal;">United States Secretary of Defense <a href="http://en.wikipedia.org/wiki/Donald_Rumsfeld" title="Donald Rumsfeld">Donald Rumsfeld</a></cite><br />
<br />
<cite style="font-style: normal;">Rumsfeld really summed up the problem with his statement. One of the most commonly used constructs in programming in the concept of NULL, to indicate an unknown or unset value. This is all fine, until you start to design a communication channel and start caching information on the client. </cite><br />
<cite style="font-style: normal;"><br />
</cite><br />
<cite style="font-style: normal;">The problem really comes down to half filled data structures being returned to the client or sent to the server. This occurs usually because of a trade off between completeness of data and performance or queries. Now, we can argue whether or not this is the best approach, but for now let's just assume this is the case. A more valid place for this is an "Update" message to the server, where we want to use a common UpdateRequest structure, but only want to update some portions of the data.</cite><br />
<cite style="font-style: normal;"><br />
</cite><br />
<cite style="font-style: normal;">The problem is, when the client sees a NULL in a field, does it mean the value was actually NULL in the database, and therefor a "known unknown" or does it mean the value was never set and therefore the client should request that value from the server if needed? The same problem can go for updating data:</cite><br />
<br />
<cite style="font-style: normal;">Say we have the simple UpdateRequest as:</cite><br />
<cite style="font-style: normal;">int id;</cite><br />
<cite style="font-style: normal;">string name;</cite><br />
<cite style="font-style: normal;">string description;</cite><br />
<cite style="font-style: normal;"><br />
</cite><br />
<cite style="font-style: normal;">If we send an update request with {id=1, name="Kevin", Description=null}, does that mean that the description is unknown, and should be written as such to the database, or does it mean we don't want to update the description and keep whatever the previous description was?</cite><br />
<cite style="font-style: normal;"><br />
</cite><br />
<cite style="font-style: normal;">In order to solve this problem, I introduced a simple wrapper class called KnownValue:</cite><br />
<br />
<!-- code formatted by http://manoli.net/csharpformat/ --><br />
<pre class="csharpcode"> [DebuggerDisplay(<span class="str">"Known: {Value}"</span>)]
<span class="kwrd">public</span> <span class="kwrd">class</span> KnownValue <T>
{
<span class="rem">/// <summary></span>
<span class="rem">/// Initializes a new instance of the <see cref="KnownValue&lt;T&gt;"/> class.</span>
<span class="rem">/// </summary></span>
<span class="rem">/// <param name="value">The value.</param></span>
<span class="kwrd">public</span> KnownValue(T <span class="kwrd">value</span>)
{
Value = <span class="kwrd">value</span>;
}
<span class="rem">/// <summary></span>
<span class="rem">/// Gets or sets the value.</span>
<span class="rem">/// </summary></span>
<span class="rem">/// <value>The value.</value></span>
[DataMember(IsRequired=<span class="kwrd">true</span>)]
<span class="kwrd">public</span> T Value
{
get; set;
}
}</pre><br />
The beauty of this simple class is we can now introduce three-state logic:<br />
<br />
<span class="csharpcode" style="padding-bottom: 0px">Description = <span class="kwrd">null</span></span>: The value is unknown, so don't change it on the server or if the user requests it, we don't have it cached so go get it.<br />
<span class="csharpcode" style="padding-bottom: 0px">Description = KnownValue<<span class="kwrd">string</span>>(<span class="kwrd">null</span>)</span>: The value is known, and should be set to NULL. If the user requests the value, don't go to the server since we already know it is NULL.<br />
<span class="csharpcode" style="padding-bottom: 0px">Description = KnownValue<<span class="kwrd">string</span>>(<span class="str">"My Description"</span>)</span>: The value is known, and should be set to "My Description".Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-30980141885073193762010-07-02T13:17:00.000-07:002010-07-02T13:26:41.388-07:00What's at a location at a given time?Today I was challenged with a problem that seemed deceptively simple and the answer is. But coming up with it took a while. The question was for a location log, what were all the objects at a given location at a given time?<br /><br />The table is simple:<br />LocationID int<br />ObjectID int<br />Date datetime<br /><br />So, {1,1,6/30/10 10am} would indicate that object 1 was at location 1 at 10am on 6/30/10.<br /><br />Given a set of log entries:<br /><br />{1,1,6/30/10 10am}<br />{2,1,6/30/10 12pm}<br />{4,1,6/30/10 6pm}<br />{2,1,6/30/10 8pm}<br />{1,2,6/30/10 11am}<br />{3,2,6/30/10 1pm}<br />{4,2,6/30/10 5pm}<br /><br />We can see from this list that at 11am for location 1, both object 1 & 2 are there. But at 12:01pm, only object 2 is left. So, how do we get this list for any given time?<br /><br />Here you go..<br /><br />declare @myDate datetime<br />set @myDate='2010-06-30 11:00'<br />declare @MyLocation int<br />set @MyLocation =2<br /><br />select * from<br />LocationLog t1<br /> left join LocationLog t2 on t1.ObjectID=t2.ObjectID and t2.Date > t1.Date and t2.Date <= @myDate<br /> WHERE<br /> t1.Date<=@MyDate<br /> and t1.LocationID=@MyLocation<br /> and t2.ObjectID is nullKevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-22184386425360357012009-10-28T15:22:00.001-07:002009-10-28T15:38:29.486-07:00MySQL vs MS SQL ServerI know MySQL's query engine isn't as powerful as MSSQL, but there are things in the MySQL syntax that just run circles around MSSQL. For example, MySQL has a great option to the INSERT command called IGNORE. <br /><br />It is very common to construct a many to many table using just two columns for the relationship and making those two columns the primary key. This implies each row is unique. A common problem is how to update this relationship. <br /><br />Say you have a web site where a user can choose from a list of options. When the user wants to update their settings, they check or uncheck some new settings. On the backend, we need to update the relationship.<br /><br />A common approach is to delete all the old relationships, then reinsert them. This to me is an expensive and brute force approach. A less "heavy handed" approach would be to select all the current mappings, then figure out what is new and what should be removed. However, we've now made a rather complex difference engine on the client and it's not concurrent, unless we lock the database while doing the work on the client.<br /><br />So, welcome MySQL's INSERT IGNORE command.<br /><br />Here's how it works: <br /><br />INSERT IGNORE INTO table (field1,field2) VALUES (val1, val2)<br /><br />Simple, if the row already exists (a unique constraint is violated), MySQL simply skips the insert.<br /><br /><br />However, what if we want to do the same thing in MS SQL? Not nearly as easy, and a lot more resource intensive..<br /><br /><span style="font-weight:bold;">T-SQL:</span><br />insert into table (field1,field2) <br /> select val1, val2 <br /> where <br /> not exists(select 1 from table where field1=val1 and field2=val2)<br /><br />Another command I love in MySQL, but absent from MSSQL is the INSERT .. ON DUPLICATE syntax.. It solves a common problem, do you need to add a new record or update an existing one.<br /><br />Most people have some code that looks like this:<br /><br />SELECT COUNT(*) FROM table WHERE id=val1<br /><br />IF COUNT(*) = 0 THEN<br /> INSERT ....<br />ELSE<br /> UPDATE ....<br /><br />Straight from the MySQL manual:<br /><br />INSERT INTO table (a,b,c) VALUES (1,2,3)<br /> ON DUPLICATE KEY UPDATE c=c+1;<br /><br />is equivalent to<br /><br />UPDATE table SET c=c+1 WHERE a=1;<br /><br />but if no value exists for a=1, then<br /><br />INSERT table (a,b,c) VALUES (1,2,3)<br /><br />Sometimes, it's those little extra I just love.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-48443308050623877012009-06-24T11:23:00.000-07:002009-06-24T11:59:55.734-07:00Service principal name when using WCF, net.tcp binding, and a domain service accountService Principal Names (SPN) allow you to assign a name to a service and it will be used as a simple authentication mechanism. Basically, when the client connects to the service, the service sends the client it's SPN. The client also knows what SPN it expects. If they match, things are good.<br /><br />In order to use the WCF NetTcpBinding with a Windows Service, it is necessary to create a SPN.<br /><br />Here's the scenario:<br /><br />We have a Windows Service that exposes a WCF NetTcpBinding service. The Windows service runs as a domain user account instead of LOCAL SYSTEM, NETWORK SERVICE, etc. Let's say the service is running under the account MyDomain\MyServiceAccount.<br /><br />We have a client on the domain that will access the WCF service.<br /><br />The problem arises when the client tries to talk to the server. Without an SPN, there is no way for the client to verify it has reached the appropriate service.<br /><br />So, how do you use an SPN...<br /><br /><ol><li>We need to create an SPN and associate it with the service account. This is done using a utility called setspn.exe that is located in the <a href="http://go.microsoft.com/fwlink/?LinkId=100114">Windows 2003 Support Tools</a>.</li><li>We need to create the SPN. An SPN consists of two parts, service and host. The format is <serviceclass>\<host>. In our case, the host really doesn't matter because we will attach the SPN to a username, not a computer. Here's the command:<br /><span style="font-weight: bold;font-family:courier new;" >setspn -A MyServiceClass\MyHostName MyDomain\MyServiceAccount</span></host></serviceclass></li><li>Next, on the client, we need to specify the SPN when we create an endpoint mapping. This can be done using the app.config file or programmatically. In the app.config file, in the <endpoint> section, add<br /><span style="font-family:courier new;" ><br /><identity><br />  <serviceprincipalname value="MyServiceClass\MyHostName"/><br /></identity><br /></span><br />Or we create the endpoint with the SPN..<br /><span style="font-family:courier new;" ><br />EndpointIdentity id = EndpointIdentity.CreateSpnIdentity("MyServiceClass\MyHostName");<br />EndpointAddress addr = new EndpointAddress(new Uri(URI), id);<br /></span><br /></li><br /></ol><br /><br />That's it. Now your client will be able to verify the service it is connecting to.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com9tag:blogger.com,1999:blog-6252384544864418708.post-90461432278450988402008-11-19T11:49:00.000-08:002008-11-19T12:01:39.556-08:00Visual Studio 2008's bug in it's XAML editor bugged me all morningAll I got to say is "AAAAHHH!"...<br /><br />I spent the morning trying to figure out why Intellisense fails to work in my XAML files. Life was great, then one day it stopped working. I couldn't figure out why. Googling for solutions came up with nothing.<br /><br />So, I decided to create a blank XAML file in my project. Guess what? Intellisense worked there. So, I went through starting to recreate my "bad" XAML file. As soon as I added a namespace reference to my own assembly, it broke. In the code snippet below, you'll see the offending line. It's the xmlns:local. Remove that line, Intellisense works, add it and Intellisense breaks. Great!<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd"><</span><span class="html">Window</span> <span class="attr">x:Class</span><span class="kwrd">="MyProject.Window1"</span><br /> <span class="attr">xmlns</span><span class="kwrd">="http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span><br /> <span class="attr">xmlns:x</span><span class="kwrd">="http://schemas.microsoft.com/winfx/2006/xaml"</span><br /> <span class="attr">xmlns:local</span><span class="kwrd">="clr-namespace:MyProject"</span><span class="kwrd">></span><br /></pre><br /><br /><br />Now that I knew it was related to that line, a much more targeted google brought up this one <a href="http://social.microsoft.com/Forums/en-US/vswpfdesigner/thread/3a2c156a-195d-4069-9164-0253cfa7b0e3">Microsoft forum</a> where the issue was discussed, recognized as a bug by MS, and supposed will be fixed in the next Service Pack. Problem was, at the time of writing, the next SP was to be SP1. I've got SP1, but the bug still persists.<br /><br />So, in light of the stupid bug, this is the workaround I'm using. It's not perfect, but if you use a reference to your local assembly only for a model-view, you can push your model-view off into a resource file then link via a shared dictionary to your actual UI.<br /><br /><span style="font-weight:bold;">SharedResources.xaml:<br /></span><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd"><</span><span class="html">ResourceDictionary</span> <span class="attr">xmlns</span><span class="kwrd">="http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span><br /> <span class="attr">xmlns:x</span><span class="kwrd">="http://schemas.microsoft.com/winfx/2006/xaml"</span><br /> <span class="attr">xmlns:sys</span><span class="kwrd">="clr-namespace:System;assembly=mscorlib"</span><br /> <span class="attr">xmlns:local</span><span class="kwrd">="clr-namespace:MyProject"</span><br /> <span class="kwrd">></span><br /> <span class="rem"><!-- Your local resources go here.. oh, and Intellisense is broken when editing this file --></span><br /><span class="kwrd"></</span><span class="html">ResourceDictionary</span><span class="kwrd">></span></pre><br /><br />And now the actual window...<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd"><</span><span class="html">Window</span> <span class="attr">x:Class</span><span class="kwrd">="MyProjects.Window1"</span><br /> <span class="attr">xmlns</span><span class="kwrd">="http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span><br /> <span class="attr">xmlns:x</span><span class="kwrd">="http://schemas.microsoft.com/winfx/2006/xaml"</span><span class="kwrd">></span><br /> <br /> <span class="kwrd"><</span><span class="html">Window.Resources</span><span class="kwrd">></span> <br /> <span class="kwrd"><</span><span class="html">ResourceDictionary</span><span class="kwrd">></span> <br /> <span class="kwrd"><</span><span class="html">ResourceDictionary.MergedDictionaries</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">ResourceDictionary</span> <span class="attr">Source</span><span class="kwrd">="SharedResources.xaml"</span><span class="kwrd">/></span><br /> <span class="kwrd"><</span><span class="html">ResourceDictionary</span><span class="kwrd">></span><br /> <span class="rem"><!-- Any local resources --></span><br /> <span class="kwrd"></</span><span class="html">ResourceDictionary</span><span class="kwrd">></span><br /> <span class="kwrd"></</span><span class="html">ResourceDictionary.MergedDictionaries</span><span class="kwrd">></span><br /> <span class="kwrd"></</span><span class="html">ResourceDictionary</span><span class="kwrd">></span><br /> <span class="kwrd"></</span><span class="html">Window.Resources</span><span class="kwrd">></span><br /><br /> <span class="rem"><!-- Your contents --></span><br /><span class="kwrd"></</span><span class="html">Window</span><span class="kwrd">></span></pre><br /><br />Sometimes you make coding decisions just because you like your IDE too much to give up it's tools...Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com2tag:blogger.com,1999:blog-6252384544864418708.post-49398616698317198072008-11-03T11:25:00.000-08:002008-11-03T11:45:33.396-08:00WPF & Multithread - Part 2 and creating multiple windows on different messaging threadsIn my <a href="http://mastermynd-code.blogspot.com/2008/11/multithreading-and-wpf-windows.html">previous post</a> I talked about getting input from a user while running on a business thread. You maybe wondering what happens if I choose to just always create a new STA thread rather than check to see if the calling thread is already on an STA thread. After all, that's less code.<br /><br />Well, that's what I originally did, until I ran into a problem. You see, it all comes down to calling the Thread.Join call. This call blocks the calling thread. So, if the calling thread is the UI thread, you've just blocked it! Oops.. there goes the message pumping for that thread. So, say you have a timer on your main window. Well, suddenly it comes to a stop. In my case, I had a custom NativeWindow class that listens for keystrokes across the application to detect incoming barcode values from a barcode scanner. For my application it is essential the WndProc override of my NativeWindow always gets called. This is because I use the Raw Input API to filter keyboard input searching for barcode values. However, the Raw Input API stops all WM_KEYxx calls from being generated. The only way any of my WPF windows will get a message (and hence keystrokes) is if I manually send the WM_KEYxx messages. So, as you can see, it is essential to the application that the NativeWindow.WndProc method is always called.<br /><br />But as soon as I pop up my new WPF window to ask the user a question, they can no longer type. That's because the new window is running on the newly created STA thread and the original UI thread (and the one running the NativeWindow.WndProc) is now blocked! Users don't need to type, do they?<br /><br />So, in my original post I showed a simple way to deal with this. Just check the calling thread and see if it is a UI thread. If so, show the Dialog box on that thread and you're good to go.<br /><br />However, another option that also works is to create my NativeWindow on a different thread. The key is to call at the end System.Windows.Forms.Application.Run(). This method basically runs the old fashion message loop.. remember that one?<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">while</span>(GetMessage(&Msg, NULL, 0, 0) > 0)<br />{<br /> TranslateMessage(&Msg);<br /> DispatchMessage(&Msg);<br />}<br /></pre><br /><br />Of course, the reason I choose not to do this method was it was just too much work! First of all, now I need to worry about multiple message loops, and more cross thread issues. Secondly, an Application.Current.Shutdown() call from my WPF window doesn't shutdown the application. That's because you need to somehow communicate to the newly created window to shutdown it's thread. So, more work...<br /><br />Anyway, here's a simple example of creating a new window on a different thread, so the message loop is on a different thread. I am not saying this is the way to do things, but I wrote about it because it was a good find and maybe used later..<br /><br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">public</span> <span class="kwrd">void</span> Startup ()<br />{<br /> Thread NewThread = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ThreadStart(CreateWindow));<br /> NewThread.SetApartmentState(ApartmentState.STA);<br /> NewThread.Start();<br />}<br /><br /><span class="kwrd">private</span> <span class="kwrd">void</span> CreateWindow()<br />{<br /> <span class="rem">// Create a new native window that will be hidden. </span><br /> CreateParams cp = <span class="kwrd">new</span> CreateParams(); <br /> cp.Caption = <span class="str">"MyWindow"</span>;<br /> cp.ClassName = <span class="kwrd">null</span>;<br /> cp.Style = 0x08000000 | 0x20000000;<br /> cp.Height = 500;<br /> cp.Width = 500;<br /><br /> <span class="kwrd">this</span>.CreateHandle(cp);<br /> CreateRegistration();<br /><br /> <span class="rem">// Here is the key! Application.Run encapsulates the old standard message loop.</span><br /> Application.Run();<br />}</pre>Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com1tag:blogger.com,1999:blog-6252384544864418708.post-13959998415212057982008-11-03T10:45:00.000-08:002008-11-03T11:11:21.458-08:00Multithreading and WPF WindowsI recently had an interesting problem come up with UI threads in .NET applications and how input is processed. Here's the basic rundown...<br /><br />A user initiates an event in the UI on Thread 1<br /><br />The UI makes a call to some business layer to process the request. Note, this MAY or MAY NOT continue to execute on the UI thread.<br /><br />The business logic needs more information before it can proceed. Nicely separated, the business thread raises an event called GetAdditionalInfo. Now, the application can either provide the information directly back to to the business logic or it may need to ask the user.<br /><br />Now, here's where things get "interesting". If the business logic is running on a different thread, you've got a problem. You can't simply create a new WPF window to ask the user for the information. If you try, you'll get the following error message:<br /><br /><span style="font-weight: bold;">System.InvalidOperationException: The calling thread must be STA, because many UI components require this.</span><br /><br />Well, what are you to do? A few options come up.<br /><br />One option is to put a message onto the dispatch thread for the current window. While this method will definitely get your message across, you have a bit of a problem. That is, the business logic thread will continue to execute Problem is, you need to hold up the business logic thread until the user has responded to the question. <br /><br />The trick lies in spawning off a new thread, creating the WPF window in that new thread, and block the business logic thread until the UI finishes. Of course, if the business logic thread is already a UI thread, this isn't needed and you can just do a ShowDialog directly. Code below...<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> ShowWPFDialog(<span class="kwrd">object</span> arg)<br /> {<br /> GetAdditionalInformationWPFWindow myWindow = <span class="kwrd">new</span> GetAdditionalInformationWPFWindow(); <br /> <br /> <span class="rem">// ShowDialog will block the calling thread.. </span><br /> myWindow.ShowDialog();<br /> <br /> <span class="rem">// Presumably at this point you have the data required from the UI... So you could set it in the arguments.. </span><br /> ((BusinessRequestEventArgs)args).MyResult = myWindow.BusinessLogicResult;<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> GetAdditionalInformation(<span class="kwrd">object</span> sender, BusinessRequestEventArgs e)<br /> {<br /> <span class="rem">// If the current thread is already an STA thread we can just run on this thread.</span><br /> <span class="kwrd">if</span> (Thread.CurrentThread.ApartmentState == ApartmentState.STA)<br /> RetrieveSecondaryLogon(arg);<br /> <span class="kwrd">else</span><br /> {<br /> Thread _UIThread;<br /> _UIThread = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ParameterizedThreadStart(RetrieveSecondaryLogon));<br /> _UIThread.SetApartmentState(ApartmentState.STA);<br /> _UIThread.Start(arg);<br /> <span class="rem">// Block the caller until the UI thread ends..</span><br /> _UIThread.Join();<br /> }<br /> }</pre>Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-6732124107953331122008-10-30T18:40:00.001-07:002008-11-11T13:00:17.806-08:00RoutedEvents to CommandsMicrosoft started down a great road by introducing <a href="http://msdn.microsoft.com/en-us/library/ms752308.aspx">Commanding</a> with WPF. However, in my opinion they didn't go far enough. While it's great that some UI elements like Buttons, Menus, etc. support sending a Command when activated, there are many other places in UI design that an action taken implies a command. The most common example I can think of is when the SelectedItem value changes in a Listbox or Combobox. Perhaps you want to either display details about a selected listbox item. Maybe you want to take action if the user double-clicks the list item. Maybe you want to immediately do some action, like a user chooses a value from a ComboBox and your ready to move forward. (I won't go into whether this is really good UI design). <br /><br />Regardless, my point is, there are lots of things exposed via RoutedEvents that have no command interface, but it sure would be nice to have a command instead of a routed command.<br /><br />One great thing about WPF is the extensibility. Using the <a href="http://blogs.msdn.com/johngossman/archive/2008/05/07/the-attached-behavior-pattern.aspx">Attached Behavior pattern</a> (by John Gossman) we can create a class that will allow us to add command patterns onto UIElement for any routed command. The code is at the end of this post. <br /><br />Some interesting things I learned while making this class and then trying to use it. One, XAML is good, but it's got a long way to go to catch up to the more mature .NET languages, like C#. A difficulty in XAML is the lack of generic support, so you need to do little things like my creation of the RoutedEventCommandBindingCollection class, even though it is an empty class, it creates a concrete class of the generic ObservableCollection<>. <br /><br />The fact that attached property instances are not separately initialized also was a problem. For example, it would be great to initialize each attached property to be an empty list. However, we can't do this. So instead, we need to do the initialization in the XAML, as seen in the code example below. If you exclude the RoutedEventCommandBindingCollection wrapping, you get a NULL exception because the attached property EventCommandBinding (which is a list) hasn't been initialized to an empty list.<br /><br /><br />Using the class in XAML:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd"><</span><span class="html">UWPath:RoutedEventCommandProxy.EventCommandBinding</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">UWPath:RoutedEventCommandBindingCollection</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">UWPath:RoutedEventCommandBinding</span> <span class="attr">Event</span><span class="kwrd">="UIElement.MouseUp"</span> <span class="attr">Command</span><span class="kwrd">="{StaticResource MouseWasClicked}"</span><span class="kwrd">/></span><br /> <span class="kwrd"></</span><span class="html">UWPath:RoutedEventCommandBindingCollection</span><span class="kwrd">></span><br /><span class="kwrd"></</span><span class="html">UWPath:RoutedEventCommandProxy.EventCommandBinding</span><span class="kwrd">></span></pre><br /><br /><br />The source code in C#:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> RoutedEventCommandProxy<br /> {<br /> <span class="rem">// Fun, this will keep track of all the bindings!</span><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> Dictionary<UIElement, RoutedEventCommandBindingCollection> handlerTable =<br /> <span class="kwrd">new</span> Dictionary<UIElement, RoutedEventCommandBindingCollection>();<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> DependencyProperty EventCommandBindingProperty = <br /> DependencyProperty.RegisterAttached(<span class="str">"EventCommandBinding"</span>,<br /> <span class="kwrd">typeof</span>(RoutedEventCommandBindingCollection),<br /> <span class="kwrd">typeof</span>(RoutedEventCommandProxy),<br /> <span class="kwrd">new</span> FrameworkPropertyMetadata(<span class="kwrd">null</span>, <span class="kwrd">new</span> PropertyChangedCallback(PropertyChanged)));<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> SetEventCommandBinding(UIElement element, RoutedEventCommandBindingCollection <span class="kwrd">value</span>)<br /> {<br /> element.SetValue(EventCommandBindingProperty, <span class="kwrd">value</span>);<br /> }<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> RoutedEventCommandBindingCollection GetEventCommandBinding(UIElement element)<br /> {<br /> <span class="kwrd">return</span> (RoutedEventCommandBindingCollection)element.GetValue(EventCommandBindingProperty);<br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> PropertyChanged (DependencyObject sender, DependencyPropertyChangedEventArgs args)<br /> {<br /> UIElement element = sender <span class="kwrd">as</span> UIElement;<br /><br /> <span class="rem">// Remove any old stuff..</span><br /> <span class="kwrd">if</span> (handlerTable.ContainsKey(element))<br /> handlerTable.Remove(element); <br /><br /> RoutedEventCommandBindingCollection OldMappings = (RoutedEventCommandBindingCollection)args.OldValue;<br /> <span class="kwrd">if</span> (OldMappings != <span class="kwrd">null</span>)<br /> { <br /> <span class="kwrd">foreach</span> (RoutedEventCommandBinding mapping <span class="kwrd">in</span> OldMappings)<br /> {<br /> <span class="kwrd">if</span> (mapping.Event != <span class="kwrd">null</span>)<br /> element.RemoveHandler(mapping.Event,<span class="kwrd">new</span> RoutedEventHandler(Handler));<br /> }<br /> }<br /><br /> <span class="rem">// Add the new stuff</span><br /> RoutedEventCommandBindingCollection NewMappings = (RoutedEventCommandBindingCollection)args.NewValue;<br /> <span class="kwrd">if</span> (NewMappings != <span class="kwrd">null</span>)<br /> {<br /> handlerTable.Add(element, NewMappings);<br /> <span class="kwrd">foreach</span> (RoutedEventCommandBinding mapping <span class="kwrd">in</span> NewMappings)<br /> {<br /> <span class="kwrd">if</span> (mapping.Event != <span class="kwrd">null</span> && mapping.Command != <span class="kwrd">null</span>)<br /> element.AddHandler(mapping.Event, <span class="kwrd">new</span> RoutedEventHandler(Handler));<br /> }<br /> }<br /><br /> }<br /><br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Handler (<span class="kwrd">object</span> sender, RoutedEventArgs e)<br /> {<br /> UIElement element = sender <span class="kwrd">as</span> UIElement;<br /> <span class="kwrd">if</span> (handlerTable.ContainsKey(element))<br /> {<br /> RoutedEventCommandBindingCollection mappings = handlerTable[element];<br /> <span class="kwrd">foreach</span> (RoutedEventCommandBinding mapping <span class="kwrd">in</span> mappings)<br /> {<br /> <span class="kwrd">if</span> (e.RoutedEvent == mapping.Event)<br /> {<br /> mapping.Command.Execute(e);<br /> }<br /> }<br /> }<br /> }<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> RoutedEventCommandBindingCollection : ObservableCollection<RoutedEventCommandBinding><br /> {<br /> }<br /><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> RoutedEventCommandBinding<br /> {<br /> <span class="kwrd">public</span> RoutedEvent Event { get; set; }<br /> <span class="kwrd">public</span> ICommand Command { get; set; }<br /> }</pre>Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-57724122190449829432008-10-30T11:45:00.001-07:002008-10-30T12:04:05.157-07:00WPF and FocusSo, Control focus in WPF just frustrates me sometimes. It should be simple. Control.Focus(). But things are never as they seem. Take this code for example. It simply hides a panel asking for an ID and the presents a panel asking for a Pin. With the myPinPad variable is an instance of a custom control (inherited from UserControl) with nice buttons for a pin pad and a text field to type optionally type in a pin.<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">private</span> <span class="kwrd">void</span> ShowPinPad ()<br />{<br /> IDBadgePanel.Visibility = Visibility.Collapsed;<br /> PinPanel.Visibility = Visibility.Visible;<br /> myPinPad.Focus();<br />}</pre><br /><br />The PinPad custom control contains an override of the OnGotFocus method as shown below. The PWD variable is a PasswordBox control that will display the pin. Now, when the PinPad control gets focus, we want the PasswordBox to get focus so a person can just start typing. <br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnGotFocus(RoutedEventArgs e)<br />{<br /> <span class="kwrd">base</span>.OnGotFocus(e); <br /> PWD.Focus();<br />}</pre><br /><br />Anyway, this doesn't work the first time around! Why not? Well, after some investigation it is revealed that while PWD.IsInitialized is true, PWD.IsVisible is false. Of course, call ShowPinPad again later on and it works. This time IsVisible is set to true.<br /><br />So, what to do? Well, I think the reason it isn't visible is that despite the status of being Initialized, it really isn't yet. Since we just made the panel containing the control visible, perhaps the render engine hasn't had time to make the children (and hence the PWD control) visible yet.<br /><br />One trick is to wait a bit before sending the focus. And by wait, I mean let all the other initialization stuff finish first on the thread. This could be done with a DispatchTimer, but an even easier trick is the following:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnGotFocus(RoutedEventArgs e)<br />{<br /> <span class="kwrd">base</span>.OnGotFocus(e);<br /> <span class="kwrd">this</span>.Dispatcher.BeginInvoke((Action)<span class="kwrd">delegate</span> { PWD.Focus(); }, <br /> System.Windows.Threading.DispatcherPriority.Background);<br />}</pre><br /><br />With this trick, we create an anonymous delegate and schedule it for execution at the lowest possible priority. So, hopefully everything else will get initialized first. I've tried this with my app and it works.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com0tag:blogger.com,1999:blog-6252384544864418708.post-56369102774021924692008-10-23T17:04:00.000-07:002008-10-23T17:47:34.616-07:00Fun with SQL transactions, ADO.NETand how ExecuteScalar can bite you.Today I wanted to create a section of code that grouped a bunch of stored procedure (SP) calls into one transaction. If any of these stored procedures failed, I want to rollback the entire transaction. It basically went something like this:<br /><br />Call SP:CreateCase<br />Call SP:LinkIdentifierToCase<br />Call SP:CreatePatient<br />Call SP:LinkPatientToCase<br /> <br />Ok, first thing I tried was the .NET 2.0 TransactionScope. I won't go into details here, there are plenty of sites online how to use it. Anyway, after some digging I found that TransactionScope only works with MSDTC service enabled on the SQL server when you are running SQL 2000! Ahhh.. That's a bit heavy since it's not distributed by any means. <br /><br />So, I went back to look at the ASP.NET 1.x stuff, which is the SqlConnection.BeginTransaction method. OK, looks good on the surface.. but what's it really doing? Well, I took a look at SQL profiler to find out.. And the answer is... drum roll please... Simple sending T-SQL commands BEGIN TRANSACTION, COMMIT, and ROLLBACK.<br /><br />Well, that's not too bad, at least I understand it. However, bigger issues came up when your SPs have transactions in them. See, while SQL Server claims to support nested transactions, it really doesn't. For example, what would you expect this to do:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">begin</span> <span class="kwrd">transaction</span> trans1<br /> <span class="kwrd">select</span> <span class="preproc">@@trancount</span><br /> <span class="kwrd">begin</span> <span class="kwrd">transaction</span> trans2<br /> <span class="kwrd">select</span> <span class="preproc">@@trancount</span><br /> <span class="kwrd">rollback</span> <span class="kwrd">transaction</span> trans2<br /> <span class="kwrd">select</span> <span class="preproc">@@trancount</span><br /><span class="kwrd">commit</span> <span class="kwrd">transaction</span> trans1<br /></pre><br /><br />I would expect it to roll back the entire transaction because trans2 failed. However, <span class="kwrd">commit</span> <span class="kwrd">transaction</span> trans1 shouldn't throw an error. Guess what, as soon as rollback is executed, all nested layers are rolled back. Instead, it should nicely fall out. OK, trans2 failed, one nested layer to go. When we see another commit or rollback, we know to rollback the entire thing. Anyway, this makes things "interesting"...<br /><br />What ends up happening just isn't what you expect. So, you just need to be prepared for stuff. Luckily, it seems generally ADO.NET can handle this for you. I made a simple SP that either happily completes with a COMMIT or ends with a ROLLBACK. It is:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">CREATE</span> <span class="kwrd">Procedure</span> TestProc (@DoError <span class="kwrd">int</span>)<br /><span class="kwrd">AS</span><br /> <span class="kwrd">BEGIN</span> <span class="kwrd">TRAN</span><br /> <span class="kwrd">insert</span> <span class="kwrd">into</span> TestTable (Name) <span class="kwrd">VALUES</span> (<span class="str">'Test'</span>)<br /> <span class="kwrd">if</span> (@DoError=0)<br /> <span class="kwrd">COMMIT</span> <br /> <span class="kwrd">else</span><br /> <span class="kwrd">ROLLBACK</span><br /><span class="kwrd">GO</span><br /></pre><br /><br />Then I created my test code:<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br />SqlConnection conn = <span class="kwrd">new</span> SqlConnection(ConnectionString);<br />conn.Open();<br />SqlTransaction tran = conn.BeginTransaction();<br /><span class="kwrd">try</span><br />{<br /> SqlCommand cmd = <span class="kwrd">new</span> SqlCommand(<span class="str">"exec TestProc 0"</span>, conn);<br /> cmd.Transaction = tran;<br /> cmd.ExecuteNonQuery();<br /><br /> cmd = <span class="kwrd">new</span> SqlCommand(<span class="str">"exec TestProc 1"</span>, conn);<br /> cmd.Transaction = tran;<br /> cmd.ExecuteNonQuery();<br /><br /> tran.Commit();<br />}<br /><span class="kwrd">catch</span> (Exception)<br />{<br /> tran.Rollback();<br />} <br />conn.Close();</pre><br /><br />Here's the output of SQL profiler:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_69cXpKbaUms/SQEY95VUbCI/AAAAAAAADB0/NRc3tHH5pmA/s1600-h/SqlCommand.BeginTransaction-Profiler.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 88px;" src="http://3.bp.blogspot.com/_69cXpKbaUms/SQEY95VUbCI/AAAAAAAADB0/NRc3tHH5pmA/s320/SqlCommand.BeginTransaction-Profiler.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5260513291386776610" /></a><br /><br />As I would expect, while the first call the SP succeeded, the second one failed, and all the "test" table should be empty. In fact, it was. Luckily for us, ADO.NET executes a IF @@TRANCOUNT > 0 after executing each statement. This allows it to know when to throw an exception if a ROLLBACK occurs in the T-SQL, which I'm catching in the try/catch block. However, I still call tran.RollBack just to ensure the exception wasn't caused by something else, even maybe an error message (but not rollback!) from the SP itself. And look, ADO.NET is smart enough to check if the @@TRANCOUNT is great than zero before calling ROLLBACK. I can't say it's that smart when you call trans.Commit, but you should never be calling Commit if you get an exception.<br /><br />So, I thought my work was done, until I found another curious issue. It seems that ExecuteScalar does not throw an exception even if a rollback occurred within the SP or an error was generated by the SP. This obviously causes a problem in my book! There is a nice forum discussion about this on <a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=787232&SiteID=1">MSDN</a>. <br /><br />So, conclusion. Don't blindly use BeginTransaction, especially if you have stored procedures with transactions within them. Secondly, if you want to capture any sort of error from the SQL server, don't use ExecuteScalar.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com3tag:blogger.com,1999:blog-6252384544864418708.post-47963629324858631482008-10-22T22:59:00.000-07:002008-10-22T23:35:21.142-07:00Storing Information Per ThreadI recently ran across a situation where I wanted to store information per Thread. After doing some research I ran across the ThreadStaticAttribute class. You apply this attribute to a static field and the value for the variable is unique for each thread. Also note that a default value is useless since it will only be initialized once and the following threads will just have a null value. So, it is best to apply this attribute to a private field and have a public property that can initialize if needed.<br /><br /><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /> [ThreadStatic]<br /> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">string</span> myThreadValue;<br /><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> MyThreadValue<br /> {<br /> get<br /> {<br /> <span class="kwrd">if</span> (myThreadValue == <span class="kwrd">null</span>)<br /> myThreadValue = <span class="str">"New value"</span>;<br /> <span class="kwrd">return</span> myThreadValue;<br /> }<br /> }<br /></pre><br /><br />There are other methods to store data per thread. One is SetData / GetData methods on the class<span style="font-family:Courier New;"> </span>System.Runtime.Remoting.Messaging.CallContext. This method allows you to specify a named variable and a value. The reason I don't like this approach is that it doesn't allow you to strongly type the data since the SetData / GetDat use a Object parameter.<br /><br />Finally, the Thread.AllocateDataSlot method allows you to create a "storage slot" and use the Thread.SetData and Thread.GetData to you to store information. The reason I don't like this approach is the same as mentioned above about the lack of strong typing. Secondly, this method is is <a href="http://blogs.msdn.com/ricom/archive/2006/07/18/670314.aspx">slower</a> than the ThreadStaticAttribute.Kevin Fleminghttp://www.blogger.com/profile/12305055917481111778noreply@blogger.com1