Skip to main content

Pragmatic TSQL Programmer

Go Search
Home
  

Greg Wilson's thoughts from the trenches of TSQL and C# development
#HDC09 Demo Code and Slides

As promised, here is a link to the code and demos from my Heartland Developers Conference presentations. It was a great conference and the people there were awesome.

It contains my 60 minute talk about Creating Custom User Controls in WPF. It contains more demos than I was able to get to, and demonstrates most of the basic concepts of the various tools you can use to start building your own controls library.

Additionally, the download contains my 30 minute lightning round where I powered through the concept of how to get you WPF binding to work just as well in the real world against legacy data objects, as it does with dependency data objects.

Enjoy!

Directory Size Utility
A few weeks ago, I fooled around for a few hours to make an app that gives a decent visualization of where all the space on a drive has gone.
 
I did it as an example while I was teaching WPF to a couple of new developers, and we played with lots of things like multi-threading and databinding and it was a great lesson.
 
Since then, I've been using it over and over, and have had several people ask for a copy, so I am making available the source code and the executable.  If you just want to run it, all you need is the .exe.  If you want to play with the source code, it is there as well.
 
I'm ready for the Zombie Apocalypse!
Handling SQL Transaction retries (SQL Error 1205)

Most people writing code about databases know that in rare cases, a SQL transaction can become deadlocked and killed by the server, but still be able to be retried successfully. (I will not be going into the theory in this post. More info here.) However, most developers forget to code for this because it is typically a very rare event. (If it happens often, you have other problems.) I've gotten plenty of questions through the years about how to code for this, and I thought I would write a quick post on how to do this in C# for reference.

What you need to do, is wrap all your calls to SQL commands with the following code:

bool victimOfDeadlock;

do

{

try

{

da.Fill(ds); //<--This is any line of code that executes a sql command that might become a victim of a deadlock.

victimOfDeadlock = false;

}

catch (SqlException sex)

{

victimOfDeadlock = sex.Number == 1205;

if (!victimOfDeadlock) throw;

}

} while (victimOfDeadlock);

 

This can/should be used around any call to your database, but not around commands that call functions that call the DB. In other words, only use it when things like .Fill, .ExecuteQuery, .ExecuteNonQuery, .ExecuteReader are actually called. It is a waste to place it around code that calls code that calls the DB, unless you are calling 3rd party code that you do not control AND know that retrying the statement won't have any unintended consequences. (If that isn't clear, I'm sure I'll be getting e-mails from a few of you. 8o) )

 

(Side note: Quite obviously, this would be a nightmare if you aren't using best practices and keeping 100% of your actual SQL calls inside a reusable data access layer in our code. Having a reusable DAL is critical to most every client side thing you want to do with SQL, unless you want to quickly descend into nightmare of maintaining the same code snippets repeatedly scattered throughout your entire code base.)

 

I deliberately kept this post rather brief, and skipped over a lot of theory. If a few people post that they want me to post the theory, I can write up more later.

Iowa Code Camp - Call for speakers!

After the awesome success of the first Iowa Code Camps in 2008, it is time for another round!  We have finally locked down the facility we will be in and it is time to for speaker to sign up!

NOTE:  I do apologize that due to logistical issues with securing the location and date this call for speakers is coming much later than normal.  We, as leaders, have been working since early January on several possible locations/dates and just received confirmation on the final facility yesterday.  Please help us in getting the word out to as many potential speakers as possible as fast as possible.

The third Iowa Code Camp is going to be May 2nd in Cedar Rapids, Iowa at the Kirkwood Community College campus.  This will be a combined effort between Des Moines (www.iadnug.org) and Cedar Rapids (www.CRIneta.org) user communities.  We don't have all the details yet, but we are looking at 5 tracks with 5 sessions each.  Our previous camps in Iowa City and Des Moines had well over 100 attendees and we expect more this May in Cedar Rapids.

PLEASE FORWARD THIS E-MAIL to those you think may be interested, and please post information on your development blogs.

This is a code camp, so sessions should have:

  • Viewable, unrestricted (not copyrighted) and downloadable code and slide decks.
  • Things developers can use the next Monday, not primarily fluffy marketing knowledge of future concepts that can't be used for months. If you want to cover new or Beta tech, make sure you keep it grounded in actual code and try to keep it relevant to an audience who isn't using it on a daily basis.

Topic ideas:

We are looking for 4 basic types of sessions:

1)  We are welcoming non-.NET centric topics.  Hopefully, we can have another full track of "alternative" stuff.  Java, 'nix, Mac, Drupal, open source, etc.

2)  Beginning 100-level sessions targeted towards students and/or developers from another technology.  Things like:  LAMP Programming 101, Getting started in the .NET world, What college doesn't teach you, Developing Java with Eclipse 101, User Interfaces 101

3)  Nice, meaty .NET sessions - The core of any code camp

4)  Audience driven sessions.  We are planning to have various format sessions of experts that the community can ask questions to.   We need volunteers to be in the sessions as "experts".  We have various discussion groups (fishbowl, open topics, etc.) and may try some 1 on 1 help-them-with-their-code type of stuff.

I (greg@solidDONTSPAMMErockstable.com) need to know as soon as reasonable who is interested in speaking.  Please let me know if you are definite or tentative, and what you intend to speak on.  (Title/Description/Bio)  I will be making the final schedule of speakers and tracks in mid-April.  we already have more than 10 speakers committed, so please respond soon.  If we have more speakers than sessions, we will work (per topic) on a first come/first served basis.

Code camps are primarily volunteer driven events.  They are free to attendees, and we don't expect to have money to reimburse for travel expenses.  If you are affiliated with  an organization that  would like to pay your expenses and be listed as a sponsor (or just plain sponsor the event), contact Nick Parker (nickp@developerDONTSPAMHIMnotes.com) about sponsorships.

   

Greg Wilson

Aka, The Pragatic TSQL Programmer

My animated .gif control for WPF

Since WPF 1.0 dropped the ball on supporting animated .gif files, I spent some time assembling various ideas that I found on the MSDN WPF Forums into a nice custom control with a few unique features. Firstly, my control allows you to use a .gif that you have compiled as an Embedded Resource in your project, and secondly, my control allows you to pause/unpause the animation by clicking on the .gif. You can turn this second feature off by setting AllowClickToPause to false, but it is on by default. Other than that, it inherits from the Image control and should act just like you would expect a WPF control to act like.

You may download the full source code, and a demo app if you would like. (Props to Wikipedia for the Stirling Engine animation I used for the demo.)

Here is the code I used: (As you will see I began with the code from Sergey Ukraine's posts)

using System;

using System.Drawing;

using System.IO;

using System.Reflection;

using System.Runtime.InteropServices;

using System.Windows;

using System.Windows.Input;

using System.Windows.Interop;

using System.Windows.Media.Imaging;

using System.Windows.Threading;

using Image=System.Windows.Controls.Image;

 

namespace UI

{

public class GIFImageControl : Image

{

public static readonly DependencyProperty AllowClickToPauseProperty =

DependencyProperty.Register("AllowClickToPause", typeof (bool), typeof (GIFImageControl),

new UIPropertyMetadata(true));

 

public static readonly DependencyProperty GIFSourceProperty =

DependencyProperty.Register("GIFSource", typeof (string), typeof (GIFImageControl),

new UIPropertyMetadata("", GIFSource_Changed));

 

public static readonly DependencyProperty PlayAnimationProperty =

DependencyProperty.Register("PlayAnimation", typeof (bool), typeof (GIFImageControl),

new UIPropertyMetadata(true, PlayAnimation_Changed));

 

private Bitmap _Bitmap;

 

private bool _mouseClickStarted;

 

public GIFImageControl()

{

MouseLeftButtonDown += GIFImageControl_MouseLeftButtonDown;

MouseLeftButtonUp += GIFImageControl_MouseLeftButtonUp;

MouseLeave += GIFImageControl_MouseLeave;

Click += GIFImageControl_Click;

//TODO:Future feature: Add a Play/Pause graphic on mouse over, and possibly a context menu

}

 

public bool AllowClickToPause

{

get { return (bool) GetValue(AllowClickToPauseProperty); }

set { SetValue(AllowClickToPauseProperty, value); }

}

 

public bool PlayAnimation

{

get { return (bool) GetValue(PlayAnimationProperty); }

set { SetValue(PlayAnimationProperty, value); }

}

 

public string GIFSource

{

get { return (string) GetValue(GIFSourceProperty); }

set { SetValue(GIFSourceProperty, value); }

}

 

private void GIFImageControl_Click(object sender, RoutedEventArgs e)

{

if (AllowClickToPause)

PlayAnimation = !PlayAnimation;

}

 

private void GIFImageControl_MouseLeave(object sender, MouseEventArgs e)

{

_mouseClickStarted = false;

}

 

private void GIFImageControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)

{

if (_mouseClickStarted)

FireClickEvent(sender, e);

_mouseClickStarted = false;

}

 

private void GIFImageControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

_mouseClickStarted = true;

}

 

private void FireClickEvent(object sender, RoutedEventArgs e)

{

if (null != Click)

Click(sender, e);

}

 

public event RoutedEventHandler Click;

 

private static void PlayAnimation_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)

{

var gic = (GIFImageControl) d;

if ((bool) e.NewValue)

{

//StartAnimation if GIFSource is properly set

if (null != gic._Bitmap)

ImageAnimator.Animate(gic._Bitmap, gic.OnFrameChanged);

}

else

//Pause Animation

ImageAnimator.StopAnimate(gic._Bitmap, gic.OnFrameChanged);

}

 

 

private void SetImageGIFSource()

{

if (null != _Bitmap)

{

ImageAnimator.StopAnimate(_Bitmap, OnFrameChanged);

_Bitmap = null;

}

if (String.IsNullOrEmpty(GIFSource))

{

//Turn off if GIF set to null or empty

Source = null;

InvalidateVisual();

return;

}

if (File.Exists(GIFSource))

_Bitmap = (Bitmap) System.Drawing.Image.FromFile(GIFSource);

else

{

//Support looking for embedded resources

Assembly assemblyToSearch = Assembly.GetAssembly(GetType());

_Bitmap = GetBitmapResourceFromAssembly(assemblyToSearch);

if (null == _Bitmap)

{

assemblyToSearch = Assembly.GetCallingAssembly();

_Bitmap = GetBitmapResourceFromAssembly(assemblyToSearch);

if (null == _Bitmap)

{

assemblyToSearch = Assembly.GetEntryAssembly();

_Bitmap = GetBitmapResourceFromAssembly(assemblyToSearch);

if (null == _Bitmap)

throw new FileNotFoundException("GIF Source was not found.", GIFSource);

}

}

}

if (PlayAnimation)

ImageAnimator.Animate(_Bitmap, OnFrameChanged);

}

 

private Bitmap GetBitmapResourceFromAssembly(Assembly assemblyToSearch)

{

string[] resourselist = assemblyToSearch.GetManifestResourceNames();

if (null != assemblyToSearch.FullName)

{

string searchName = String.Format("{0}.{1}", assemblyToSearch.FullName.Split(',')[0], GIFSource);

if (resourselist.Contains(searchName))

{

Stream bitmapStream = assemblyToSearch.GetManifestResourceStream(searchName);

if (null != bitmapStream)

return (Bitmap) System.Drawing.Image.FromStream(bitmapStream);

}

}

return null;

}

 

private static void GIFSource_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)

{

((GIFImageControl) d).SetImageGIFSource();

}

 

 

private void OnFrameChanged(object sender, EventArgs e)

{

Dispatcher.BeginInvoke(DispatcherPriority.Normal,

new OnFrameChangedDelegate(OnFrameChangedInMainThread));

}

 

private void OnFrameChangedInMainThread()

{

if (PlayAnimation)

{

ImageAnimator.UpdateFrames(_Bitmap);

Source = GetBitmapSource(_Bitmap);

InvalidateVisual();

}

}

 

[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]

public static extern IntPtr DeleteObject(IntPtr hDc);

 

private static BitmapSource GetBitmapSource(Bitmap gdiBitmap)

{

IntPtr hBitmap = gdiBitmap.GetHbitmap();

BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(hBitmap,

IntPtr.Zero,

Int32Rect.Empty,

BitmapSizeOptions.FromEmptyOptions());

DeleteObject(hBitmap);

return bitmapSource;

}

 

private delegate void OnFrameChangedDelegate();

}

}

WPF - The visualization tool of the future
I fell bad that I haven't posted a lot of what had been on my mind lately, and i wanted to share what is going on.

In my mind, I am realizing that there is a new technology that I believe is going to be making a BIG, BIG impact on developers who work with lots of data: WPF. Over the last 18 months or so, I've been experimenting with WPF, and have created several major applications at work using WPF. And, the more I use it, the more I realize that this is really the future of UI work, especially for the people, like me, who work with lots of data heavy apps.

WPF had a pretty rough start. The initial demos of the technology highlighted ridiculous and worthless things like spinning buttons and the WPF support in Visual Studio is buggy and far behind the tool support for things like WinForms. It didn't even have basic controls like a non-beta rich data grid until October 2008.

But, despite all of the warts that the "1.0" version of WPF has, it is a technology that is very easy to fall in love with. I will begin elaborating on why in future posts.

I am currently writing my first big developer talk on how WPF and SQL can go hand in hand. I'll be presenting it in April to the Cedar Falls user group and then again at the Iowa Code Camp in May.

Most importantly for this blog, I have added a new category for my thoughts on WPF, and you can expect to see good content here soon.
Another reason to keep those boxes patched

Microsoft Security Advisory (961040)

Vulnerability in SQL Server Could Allow Remote Code Execution

In 2008, I've met 3 organizations that STILL do not have an automatic patching strategy for their SQL machines. Bad idea. If you are still patching them manually, get 'em done now, before this one bites you.

Iowa Code Camp was amazing this year!

I'm still struggling to get caught up from helping organize the Iowa Code Camp, but I had to write a quick post. The event was awesome for more reasons than I can count. The sessions were top notch, the facility was great, but most of all the developers that showed up made the event. We pulled a great crowd of engaged and talented developers from Iowa and most of the surrounding states. Numerous people drove well over 3 hours to make it to West Des Moines, and every session was full of smart, interactive professionals who really made the sessions more interesting and fun that what you typically see at these events. Can't wait until the next one in May!

Free and Easy Source Control for SQL Server

This is a re-link to my HDC07 presentation. I've gotten a few e-mails from people who have looked here for my demo of how to get SQL Object (Stored Procedures, Functions, Table Definitions, etc.) to be automatically placed into source control without paying for any 3rd party tools. Apparently, my original posting of it wasn't very descriptive, and several people didn't realize it was the presentation I told them was on my site.

Everything is explained in this presentation, along with sample code. The only thing you need to provide is the scripts to move files placed on the file system into your particular flavor of source control. (sadly, there is no way for me to provide scripts for this to everyone. I don't have access to every source control flavor, and there is no way to do this in a general manner for all systems.) Everything else is done with Service Broker, SQL CLR, SMO and a Windows Service, with all the code provided for you in the sample code.

The end result will be that any time anyone runs a SQL command (via tool or command line) to create/update/delete a SQL object, you will get it automatically moved into source control, and the appropriate code reviewer will receive notification that things have changed. Say goodbye to undocumented changes that happen during deployments that make things work and "we'll get it entered into source control tomorrow. Seriously, we will. . ."

1 - 10 Next

 What am I doing?

     ‭(Hidden)‬ Admin Links