<feed xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
    <title>ALNERNETIVE</title>
    <link rel="self" type="application/atom+xml" href="http://blog.alner.net/Atom.aspx" />
    <subtitle type="html">public blog Me : ISuppose</subtitle>
    <id>http://blog.alner.net/Default.aspx</id>
    <author>
        <name>Nathan Allen-Wagner</name>
        <uri>http://blog.alner.net/Default.aspx</uri>
    </author>
    <generator uri="http://subtextproject.com" version="Subtext Version 2.0.0.43">Subtext</generator>
    <updated>2013-02-11T21:26:26Z</updated>
    <entry>
        <title>Healthy Debate on “Software Craftsmanship” and Elitism</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2013/02/11/healthy_debate_on_software_craftsmanship_and_elitism.aspx" />
        <id>http://blog.alner.net/archive/2013/02/11/healthy_debate_on_software_craftsmanship_and_elitism.aspx</id>
        <published>2013-02-11T15:10:02Z</published>
        <updated>2013-02-11T15:10:02Z</updated>
        <content type="html">&lt;p&gt;A good debate between &lt;a href="http://blogs.tedneward.com/"&gt;Ted Neward&lt;/a&gt; and &lt;a href="http://blog.8thlight.com/uncle-bob/archive.html"&gt;Uncle Bob Martin&lt;/a&gt; regarding "Software Craftsmanship".&lt;/p&gt;
&lt;p&gt;I find the debate to be very worth the (long) read.    &lt;br /&gt;
- Ted points out that we need to not be Elitist and egotistical about our approach and skills. Amen.     &lt;br /&gt;
- Bob's goal is to institute some principles that help the industry mature; that help us all improve. &lt;/p&gt;
&lt;p&gt;Ted's Original Article:    &lt;br /&gt;
&lt;a href="http://blogs.tedneward.com/2013/01/24/On+The+Dark+Side+Of+Craftsmanship.aspx"&gt;"On The Dark Side Of Craftsmanship"&lt;/a&gt;     &lt;br /&gt;
&lt;br /&gt;
Bob's Response:     &lt;br /&gt;
&lt;a href="http://blog.8thlight.com/uncle-bob/2013/01/30/The-Craftsman-And-The-Laborer.html"&gt;The Craftsman And The Laborer&lt;/a&gt;     &lt;br /&gt;
&lt;br /&gt;
Ted's Reply:     &lt;br /&gt;
&lt;a href="http://blogs.tedneward.com/2013/01/26/More+On+Craftsmanship.aspx"&gt;More On Craftsmanship&lt;/a&gt;     &lt;br /&gt;
&lt;br /&gt;
Bob's Reply:     &lt;br /&gt;
&lt;a href="http://blog.8thlight.com/uncle-bob/2013/02/01/The-Humble-Craftsman.html"&gt;The Humble Craftsman&lt;/a&gt;     &lt;br /&gt;
&lt;br /&gt;
Ted's Final thoguhts:     &lt;br /&gt;
&lt;a href="http://blogs.tedneward.com/2013/02/02/Last+Thoughts+On+Craftsmanship.aspx"&gt;Last Thoughts On Craftsmanship&lt;/a&gt;     &lt;br /&gt;
&lt;br /&gt;
Bob's clarification of Craftsmanship (not a direct reply, but related):     &lt;br /&gt;
&lt;a href="http://blog.8thlight.com/uncle-bob/2013/02/10/ThePrinciplesOfCraftsmanship.html"&gt;The Principles Of Craftsmanship&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Can we find a way to move things forward without thumping our own chest and putting others down? Can we improve ourselves and find pride in our work without being too inwardly focused? Are we able to “Git’r done” with some “low quality code” if that’s what the client really needs? I think so, but it takes awareness of the issues and the world around us. It requires that we pull out heads out of the &lt;strike&gt;code&lt;/strike&gt; sand to see what’s appropriate for the task at hand.&lt;/p&gt;
&lt;p&gt;GK Chesterton loved paradox. I think that is fitting here. We are best when we can simultaneously embrace both, seemingly opposing sides… when we can embrace a seeming paradox. We find balance, not by watering either side down, but by letting both positions flourish. &lt;/p&gt;
&lt;p&gt;In the end, I appreciate the above debate because it forced some skeletons out of the closet. And as the last response from Bob shows, it forced some clarification and specificity around this “hot new thing” called the Craftsmanship movement.&lt;/p&gt;
&lt;p&gt;Thanks Ted and Bob!&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/200.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/200.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/200.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/200.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Going Offline-Online with VS Missed a File</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2012/12/13/tfs_offline_missed_a_file.aspx" />
        <id>http://blog.alner.net/archive/2012/12/13/tfs_offline_missed_a_file.aspx</id>
        <published>2012-12-13T20:07:00Z</published>
        <updated>2012-12-13T20:07:00Z</updated>
        <content type="html">&lt;p&gt;I really appreciate Visual Studio’s “Go Offline” with TFS feature. Saves me a bunch of headache when I’m disconnected. And for the most part it works great.&lt;/p&gt;  &lt;p&gt;Yesterday, I discovered that somehow, the “Go Online” had not picked up all my changes. Why?&lt;/p&gt;  &lt;p&gt;It seems that the “Go Online” logic traverses the solution tree to find files that it should consider. That’s all well and good, but I have some files that are conditionally included in the solution. VS always seems to treat these as not part of the solution. But they are in source control and they are part of the compilation.&lt;/p&gt;  &lt;p&gt;I edited these files while offline and then, when going online, they were skipped. Now TFS had a different copy that on my local machine. Had I not seen some strange behavior, I probably never would have caught it.&lt;/p&gt;  &lt;p&gt;My mistake, and yes, I see that this is how the feature works, but I still stumbled on this one. &lt;/p&gt;  &lt;p&gt;Cheers&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/193.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/193.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/193.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/193.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Standing to Code</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2012/03/20/standing-to-code.aspx" />
        <id>http://blog.alner.net/archive/2012/03/20/standing-to-code.aspx</id>
        <published>2012-03-20T15:12:00Z</published>
        <updated>2012-03-20T15:12:00Z</updated>
        <content type="html">&lt;p&gt;Today I tried a Standing Desk for the day. I've heard about this a number of times, mostly on Twitter. The idea's not new, but it is gaining attention due to the health concerns around so much sitting.&lt;/p&gt;  &lt;p&gt;I started standing at 7am. It's currently 3pm, and I'm still standing here. So far so good. My muscles are a little tired, but my mind feels more awake than most other days!&lt;/p&gt;  &lt;p&gt;Another thing I'm noticing is that it's a lot easier to switch gears. If I need to step over for a cup of coffee, I'm already standing. No big deal. And getting back to coding is just as easy. Just walk up and get to it. No need to try and find that comfortable position in the chair, scoot it up to the desk, etc.&lt;/p&gt;  &lt;p&gt;As for my desk… Well, it's the same desk I usually use… plus some boxes and a board to elevate my laptop to standing height. &lt;/p&gt;  &lt;p&gt;Cost = $0. Adding years to my life and energy to my day… priceless.&lt;/p&gt;  &lt;p&gt;(I'll report back soon to let you know how things are going after a week of standing)&lt;/p&gt;  &lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/191.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/191.aspx</wfw:comment>
        <slash:comments>3</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/191.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/191.aspx</trackback:ping>
    </entry>
    <entry>
        <title>SqlTransaction Ain't Always Transactional</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2012/03/03/sqltransaction_aint_always_transactional.aspx" />
        <id>http://blog.alner.net/archive/2012/03/03/sqltransaction_aint_always_transactional.aspx</id>
        <published>2012-03-03T22:03:00Z</published>
        <updated>2013-02-11T21:26:26Z</updated>
        <content type="html">&lt;p&gt;Q: "SQL run using a &lt;font face="Courier New"&gt;SqlTransaction&lt;/font&gt; is part of a SQL Server Transaction and can be rolled back."&lt;/p&gt;  &lt;p&gt;A) True    &lt;br /&gt;B) False&lt;/p&gt;  &lt;p&gt;The answer is of course "A", right? That's what I thought too.&lt;/p&gt;  &lt;h4&gt;Basic SqlTransaction Usage&lt;/h4&gt;  &lt;p&gt;Most of us assume that we can write this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;using (var con = new SqlConnection(".."))      &lt;br /&gt;{       &lt;br /&gt;  con.Open();       &lt;br /&gt;  &lt;br /&gt;  using (var tran = con.BeginTransaction())       &lt;br /&gt;  {       &lt;br /&gt;    var cmd = con.CreateCommand();       &lt;br /&gt;    cmd.CommandText = "Update dbo.Customer ...";       &lt;br /&gt;    cmd.Transaction = tran;       &lt;br /&gt;      &lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;    try      &lt;br /&gt;    {       &lt;br /&gt;      cmd.ExecuteNonQuery();       &lt;br /&gt;      tran.Commit();       &lt;br /&gt;    }  &lt;br /&gt;    &lt;/font&gt;&lt;font face="Courier New"&gt;catch      &lt;br /&gt;    &lt;/font&gt;&lt;font face="Courier New"&gt;{      &lt;br /&gt;      tran.Rollback();       &lt;br /&gt;    }&lt;/font&gt;&lt;font face="Courier New"&gt;     &lt;br /&gt;  }       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Arial"&gt;This is plain and simple SqlTransaction based logic. Exec the command. If it completes without error, call Commit(). If it has an issue, then call Rollback();&lt;/font&gt;&lt;/p&gt;  &lt;h4&gt;But ... What Does This Do?&lt;/h4&gt;  &lt;p&gt;&lt;font face="Arial"&gt;I challenge you to predict the behavior of the following "Retry" scenario. &lt;/font&gt;&lt;font face="Arial"&gt;The code may seem a bit odd… Why would you execute more SQL after an exception? But it shows what one might do if the code implemented Retry semantics inside a transaction. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Arial"&gt;For retries, one might want to open a transaction, run a set of statements, and then retry any statements that had failed. The SQL transaction should remain in force in spite of any errors thrown by SQL server. For example, a foreign key violation does not automatically abort the transaction. Rather, the code would catch the FK violation and queue it for subsequent execution after completing the 1st pass. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Arial"&gt;This does in fact work… &lt;u&gt;most of the time&lt;/u&gt;. I say most of the time, because &lt;u&gt;deadlock errors&lt;/u&gt; in SQL Server cause some interesting behavior.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Arial"&gt;Here's a snippet that should easily run in LinqPad without too much work. The only pre-requisite is to create a DB in SqlExpress named "Scratch". &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Arial"&gt;&lt;em&gt;Pay close attention to lines 144-145. How will they behave after the deadlock? What is their impact on the database?&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;    &lt;span class="kwrd"&gt;void&lt;/span&gt; Main()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;       var connectionString = &lt;span class="str"&gt;@"Data Source=.\sqlexpress;Initial Catalog=Scratch;Integrated Security=True"&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;       &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;       var sqlSchema = &lt;span class="str"&gt;@"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;         DROP TABLE dbo.orders;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;         DROP TABLE dbo.customer2;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;         DROP TABLE dbo.customer;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;         &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;         CREATE TABLE [dbo].[customer](&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;            [customerid] [int] NOT NULL,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;            [firstname] [nvarchar](256) NULL,&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;            [lastname] [nvarchar](256) NULL,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;            CONSTRAINT [PK_customer] PRIMARY KEY CLUSTERED&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;               ([customerid] ASC) ON [PRIMARY]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;         ) ON [PRIMARY];&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;         &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;         CREATE TABLE [dbo].[orders](&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;            [orderid] [int] NOT NULL,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;            [customerid] [int] NOT NULL,&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;            [shippingid] [int] NOT NULL,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;            [otherid] [int] NULL,&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;            CONSTRAINT [PK_orders] PRIMARY KEY CLUSTERED&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            ([orderid] ASC) ON [PRIMARY]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;         ) ON [PRIMARY];&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;         &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;         ALTER TABLE [dbo].[orders] WITH CHECK&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;            ADD CONSTRAINT [FK_orders_customer] FOREIGN KEY([customerid])&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;            REFERENCES [dbo].[customer] ([customerid]);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;         &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;         CREATE TABLE [dbo].[customer2](&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;            [customerid] [int] NOT NULL,&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;            [firstname] [nvarchar](256) NULL,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;            [lastname] [nvarchar](256) NULL,&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;            CONSTRAINT [PK_customer2] PRIMARY KEY CLUSTERED&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;               ([customerid] ASC) ON [PRIMARY]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;         ) ON [PRIMARY];&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;         &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;         insert into customer (customerid, firstname, lastname) values (111, 'FN', 'LN');&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;         insert into orders (orderid, customerid, shippingid, otherid) values (221, 111, 0, 0);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;         insert into customer2 (customerid, firstname, lastname) values (111, 'FN', 'LN');&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;         insert into customer2 (customerid, firstname, lastname) values (112, 'FN', 'LN');&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;      ";&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;       &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;       &lt;span class="rem"&gt;// Change this to a different value in order to see&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;       &lt;span class="rem"&gt;//whether this run affected rows in the database.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;       var runId = &lt;span class="str"&gt;"9"&lt;/span&gt;;  &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;       &lt;span class="rem"&gt;// The following statements will force a deadlock.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;       var sql1a = &lt;span class="str"&gt;@"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;         UPDATE Customer SET LastName = 'John_Updated" + runId + &lt;span class="str"&gt;@"' WHERE CustomerId=111&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;         WAITFOR DELAY '00:00:03' -- Wait for 5 ms&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;         UPDATE Orders SET OtherId = " + runId + &lt;span class="str"&gt;@" WHERE OrderId = 221"&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;       var sql2a = &lt;span class="str"&gt;@"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;         UPDATE Orders SET ShippingId = 1" + runId + &lt;span class="str"&gt;@" WHERE OrderId = 221&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;         WAITFOR DELAY '00:00:03' -- Wait for 5 ms&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;         UPDATE Customer SET FirstName = 'Mike_Updated" + runId + &lt;span class="str"&gt;@"' WHERE CustomerId=111"&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;       &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt;       &lt;span class="rem"&gt;// These two statements affect a table that should not be locked by the deadlock.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  62:  &lt;/span&gt;       var sql1c = &lt;span class="str"&gt;@"UPDATE Customer2 SET LastName = 'Updated 1_"&lt;/span&gt; + runId + &lt;span class="str"&gt;@"' WHERE CustomerId = 111"&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  63:  &lt;/span&gt;       var sql2c = &lt;span class="str"&gt;@"UPDATE Customer2 SET LastName = 'Updated 1_"&lt;/span&gt; + runId + &lt;span class="str"&gt;@"' WHERE CustomerId = 112"&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  64:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  65:  &lt;/span&gt;       &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  66:  &lt;/span&gt;       &lt;span class="kwrd"&gt;using&lt;/span&gt; (var con1 = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlConnection(connectionString))&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  67:  &lt;/span&gt;       &lt;span class="kwrd"&gt;using&lt;/span&gt; (var con2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlConnection(connectionString))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  68:  &lt;/span&gt;       &lt;span class="kwrd"&gt;using&lt;/span&gt; (var con3 = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlConnection(connectionString))&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  69:  &lt;/span&gt;       {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  70:  &lt;/span&gt;          con1.Open();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  71:  &lt;/span&gt;          con2.Open();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  72:  &lt;/span&gt;          con3.Open();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  73:  &lt;/span&gt;          &lt;span class="kwrd"&gt;using&lt;/span&gt; (var tran1 = con1.BeginTransaction(System.Data.IsolationLevel.RepeatableRead))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  74:  &lt;/span&gt;          &lt;span class="kwrd"&gt;using&lt;/span&gt; (var tran2 = con2.BeginTransaction(System.Data.IsolationLevel.RepeatableRead))&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  75:  &lt;/span&gt;          {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  76:  &lt;/span&gt;             &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  77:  &lt;/span&gt;             {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  78:  &lt;/span&gt;                &lt;span class="rem"&gt;// Create tables and insert sample data.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  79:  &lt;/span&gt;                SqlRunner.RunSQL(con3, &lt;span class="kwrd"&gt;null&lt;/span&gt;, sqlSchema);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  80:  &lt;/span&gt;               &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  81:  &lt;/span&gt;                &lt;span class="rem"&gt;// Show sample data&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  82:  &lt;/span&gt;                SqlRunner.GetDataTable(con3, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"Select * from CUSTOMER"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  83:  &lt;/span&gt;                         .Dump(&lt;span class="str"&gt;"Data in CUSTOMER before changes"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  84:  &lt;/span&gt;                SqlRunner.GetDataTable(con3, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"Select * from ORDERS"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  85:  &lt;/span&gt;                         .Dump(&lt;span class="str"&gt;"Data in ORDERS before changes"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  86:  &lt;/span&gt;                SqlRunner.GetDataTable(con3, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"Select * from CUSTOMER2"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  87:  &lt;/span&gt;                         .Dump(&lt;span class="str"&gt;"Data in CUSTOMER2 before changes"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  88:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  89:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Running SQL 1A"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  90:  &lt;/span&gt;                var t1 = Task.Factory.StartNew(() =&amp;gt; SqlRunner.RunSQL(con1, tran1, sql1a));  &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  91:  &lt;/span&gt;               &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  92:  &lt;/span&gt;                &lt;span class="rem"&gt;// Allow slight delay to ensure deadlock.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  93:  &lt;/span&gt;                System.Threading.Thread.Sleep(1000);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  94:  &lt;/span&gt;               &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  95:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Running SQL 2A"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  96:  &lt;/span&gt;                var t2 = Task.Factory.StartNew(() =&amp;gt; SqlRunner.RunSQL(con2, tran2, sql2a));&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  97:  &lt;/span&gt;               &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  98:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Waiting"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  99:  &lt;/span&gt;                Task.WaitAll(t1, t2);   &lt;span class="rem"&gt;// This should throw SqlException for Deadlock.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 100:  &lt;/span&gt;                t1.Wait();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 101:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 102:  &lt;/span&gt;                &lt;span class="rem"&gt;// The following should not run.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 103:  &lt;/span&gt;                &lt;span class="rem"&gt;// But it's what would run if things succeeded.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 104:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Committing"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 105:  &lt;/span&gt;                tran1.Commit();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 106:  &lt;/span&gt;                tran2.Commit();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 107:  &lt;/span&gt;             }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 108:  &lt;/span&gt;             &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 109:  &lt;/span&gt;             {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 110:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Error:"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 111:  &lt;/span&gt;                Console.WriteLine(ex.ToString());&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 112:  &lt;/span&gt;               &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 113:  &lt;/span&gt;                var sqlEx = ex.InnerException &lt;span class="kwrd"&gt;as&lt;/span&gt; SqlException;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 114:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != sqlEx)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 115:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 116:  &lt;/span&gt;                   Console.WriteLine(&lt;span class="str"&gt;"SqlException Details:"&lt;/span&gt;);   &lt;span class="rem"&gt;// Should be deadlock&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 117:  &lt;/span&gt;                   Console.WriteLine(&lt;span class="str"&gt;"Class     = {0}"&lt;/span&gt;, sqlEx.Class);   &lt;span class="rem"&gt;// 13&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 118:  &lt;/span&gt;                   Console.WriteLine(&lt;span class="str"&gt;"Number    = {0}"&lt;/span&gt;, sqlEx.Number); &lt;span class="rem"&gt;// 1205 = Deadlock&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 119:  &lt;/span&gt;                   Console.WriteLine(&lt;span class="str"&gt;"Procedure = {0}"&lt;/span&gt;, sqlEx.Procedure); &lt;span class="rem"&gt;// ""&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 120:  &lt;/span&gt;                   Console.WriteLine(&lt;span class="str"&gt;"Server    = {0}"&lt;/span&gt;, sqlEx.Server); &lt;span class="rem"&gt;// .\sqlexpress&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 121:  &lt;/span&gt;                   Console.WriteLine(&lt;span class="str"&gt;"Source    = {0}"&lt;/span&gt;, sqlEx.Source); &lt;span class="rem"&gt;// .Net SqlClient Data Provider&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 122:  &lt;/span&gt;                   Console.WriteLine(&lt;span class="str"&gt;"State     = {0}"&lt;/span&gt;, sqlEx.State);    &lt;span class="rem"&gt;// 51&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 123:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 124:  &lt;/span&gt;               &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 125:  &lt;/span&gt;                &lt;span class="rem"&gt;// Should be open. Deadlocks don't close the connection.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 126:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Connection States (Should be Open):"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 127:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Con1 State = {0}"&lt;/span&gt;, con1.State);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 128:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Con2 State = {0}"&lt;/span&gt;, con1.State);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 129:  &lt;/span&gt;               &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 130:  &lt;/span&gt;                Console.WriteLine(&lt;span class="str"&gt;"Transaction States Before 'C' SQL Statements:"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 131:  &lt;/span&gt;                SqlRunner.GetDataTable(con1, tran1,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 132:  &lt;/span&gt;                         &lt;span class="str"&gt;"SELECT @@TRANCOUNT TranCount, XACT_STATE() TranState"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 133:  &lt;/span&gt;                         .Dump(&lt;span class="str"&gt;"Con1 State After Exception, Before '1C'"&lt;/span&gt;);        &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 134:  &lt;/span&gt;                SqlRunner.GetDataTable(con2, tran2,&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 135:  &lt;/span&gt;                        &lt;span class="str"&gt;"SELECT @@TRANCOUNT TranCount, XACT_STATE() TranState"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 136:  &lt;/span&gt;                        .Dump(&lt;span class="str"&gt;"Con2 State After Exception, Before '2C'"&lt;/span&gt;);        &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 137:  &lt;/span&gt;               &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 138:  &lt;/span&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 139:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 140:  &lt;/span&gt;                   &lt;span class="rem"&gt;// ******************************************&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 141:  &lt;/span&gt;                   &lt;span class="rem"&gt;// THESE ARE THE IMPORTANT LINES.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 142:  &lt;/span&gt;                   &lt;span class="rem"&gt;// How will they behave after the deadlock&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 143:  &lt;/span&gt;                   &lt;span class="rem"&gt;// ******************************************&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 144:  &lt;/span&gt;                   SqlRunner.RunSQL(con1, tran1, sql1c);        &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 145:  &lt;/span&gt;                   SqlRunner.RunSQL(con2, tran2, sql2c);        &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 146:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 147:  &lt;/span&gt;                &lt;span class="kwrd"&gt;finally&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 148:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 149:  &lt;/span&gt;                   Console.WriteLine(&lt;span class="str"&gt;"Transaction States After 'C' SQL Statements:"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 150:  &lt;/span&gt;                   SqlRunner.GetDataTable(con1, tran1,&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 151:  &lt;/span&gt;                            &lt;span class="str"&gt;"SELECT @@TRANCOUNT TranCount, XACT_STATE() TranState"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 152:  &lt;/span&gt;                            .Dump(&lt;span class="str"&gt;"Con1 State After Run '1C' SQL"&lt;/span&gt;);        &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 153:  &lt;/span&gt;                   SqlRunner.GetDataTable(con2, tran2,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 154:  &lt;/span&gt;                            &lt;span class="str"&gt;"SELECT @@TRANCOUNT TranCount, XACT_STATE() TranState"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 155:  &lt;/span&gt;                            .Dump(&lt;span class="str"&gt;"Con2 State After Run '2C' SQL"&lt;/span&gt;);        &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 156:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 157:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 158:  &lt;/span&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt; { Console.WriteLine(&lt;span class="str"&gt;"Rolling Back 1"&lt;/span&gt;); tran1.Rollback(); }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 159:  &lt;/span&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex1) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 160:  &lt;/span&gt;                  Console.WriteLine(&lt;span class="str"&gt;"Rollback 1 Error:"&lt;/span&gt;); Console.WriteLine(ex1.ToString()); }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 161:  &lt;/span&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt; { Console.WriteLine(&lt;span class="str"&gt;"Rolling Back 2"&lt;/span&gt;); tran2.Rollback(); }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 162:  &lt;/span&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex2) {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 163:  &lt;/span&gt;                  Console.WriteLine(&lt;span class="str"&gt;"Rollback 2 Error:"&lt;/span&gt;); Console.WriteLine(ex2.ToString()); }        &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 164:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 165:  &lt;/span&gt;                &lt;span class="rem"&gt;//try { Console.WriteLine("Committing 1"); tran1.Commit(); }&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 166:  &lt;/span&gt;                &lt;span class="rem"&gt;//catch (Exception ex1) {&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 167:  &lt;/span&gt;                &lt;span class="rem"&gt;//  Console.WriteLine("Commit 1 Error:"); Console.WriteLine(ex1.ToString()); }&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 168:  &lt;/span&gt;                &lt;span class="rem"&gt;//try { Console.WriteLine("Committing 2"); tran2.Commit(); }&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 169:  &lt;/span&gt;                &lt;span class="rem"&gt;//catch (Exception ex2) {&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 170:  &lt;/span&gt;                &lt;span class="rem"&gt;//  Console.WriteLine("Commit 2 Error:"); Console.WriteLine(ex2.ToString()); }        &lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 171:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 172:  &lt;/span&gt;                SqlRunner.GetDataTable(con3, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"Select * from CUSTOMER"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 173:  &lt;/span&gt;                         .Dump(&lt;span class="str"&gt;"Data in CUSTOMER after ROLLBACK"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 174:  &lt;/span&gt;                SqlRunner.GetDataTable(con3, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"Select * from ORDERS"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 175:  &lt;/span&gt;                         .Dump(&lt;span class="str"&gt;"Data in ORDERS after ROLLBACK"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 176:  &lt;/span&gt;                SqlRunner.GetDataTable(con3, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"Select * from customer2"&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 177:  &lt;/span&gt;                         .Dump(&lt;span class="str"&gt;"Data in CUSTOMER2 after ROLLBACK"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 178:  &lt;/span&gt;             }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 179:  &lt;/span&gt;          }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 180:  &lt;/span&gt;       }  &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 181:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 182:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 183:  &lt;/span&gt;    &lt;span class="rem"&gt;// Define other methods and classes here&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 184:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 185:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 186:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SqlRunner&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 187:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 188:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 189:  &lt;/span&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; RunSQL(SqlConnection con, SqlTransaction tran, &lt;span class="kwrd"&gt;string&lt;/span&gt; sql)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 190:  &lt;/span&gt;       {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 191:  &lt;/span&gt;          SqlCommand cmd = con.CreateCommand();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 192:  &lt;/span&gt;          cmd.CommandText = sql;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 193:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 194:  &lt;/span&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != tran)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 195:  &lt;/span&gt;             cmd.Transaction = tran;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 196:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 197:  &lt;/span&gt;          &lt;span class="kwrd"&gt;return&lt;/span&gt; cmd.ExecuteNonQuery();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 198:  &lt;/span&gt;       }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 199:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 200:  &lt;/span&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; DataTable GetDataTable(SqlConnection con, SqlTransaction tran, &lt;span class="kwrd"&gt;string&lt;/span&gt; sql, &lt;span class="kwrd"&gt;params&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] parameters)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 201:  &lt;/span&gt;       {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 202:  &lt;/span&gt;          var cmd = con.CreateCommand();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 203:  &lt;/span&gt;          cmd.CommandText = sql;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 204:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 205:  &lt;/span&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != tran)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 206:  &lt;/span&gt;             cmd.Transaction = tran;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 207:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 208:  &lt;/span&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != parameters &amp;amp;&amp;amp; parameters.Length &amp;gt; 0)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 209:  &lt;/span&gt;          {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 210:  &lt;/span&gt;             &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; parameters.Length; i++)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 211:  &lt;/span&gt;             {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 212:  &lt;/span&gt;                cmd.Parameters.AddWithValue(&lt;span class="str"&gt;"@p"&lt;/span&gt; + i.ToString(CultureInfo.InvariantCulture), parameters[i]);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 213:  &lt;/span&gt;             }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 214:  &lt;/span&gt;          }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 215:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 216:  &lt;/span&gt;          SqlDataAdapter da = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlDataAdapter(cmd);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 217:  &lt;/span&gt;          DataTable tbl = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataTable();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 218:  &lt;/span&gt;          tbl.Locale = CultureInfo.CurrentCulture;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 219:  &lt;/span&gt;          da.Fill(tbl);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 220:  &lt;/span&gt;          &lt;span class="kwrd"&gt;return&lt;/span&gt; (tbl);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 221:  &lt;/span&gt;       }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 222:  &lt;/span&gt;     &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt; 223:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;&lt;font face="Arial" /&gt;&lt;/p&gt;



&lt;p&gt;(&lt;a href="http://pastebin.com/ZHPpcKXe" target="_blank"&gt;Download from Pastebin&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;Shocked, Stupefied, and Generally Stumped&lt;/h4&gt;

&lt;p&gt;If you run the above code and look at the data that ends up in &lt;font face="Courier New"&gt;[dbo].[customer2]&lt;/font&gt;, you'll notice a very strange thing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;The transactions were rolled back, but one of the "C" statement was still applied! &lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;WHY???&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face="Arial"&gt;Short Answer…&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face="Arial"&gt;The Deadlock aborts the underlying transaction on SQL Server, but SqlTransaction and SqlCommand happily continue to execute more commands &lt;strong&gt;&lt;u&gt;outside of any transaction&lt;/u&gt;&lt;/strong&gt;. &lt;/font&gt;&lt;/p&gt;

&lt;h4&gt;Hindsight is 20/20&lt;/h4&gt;

&lt;p&gt;After diagnosing and fixing this issue, it almost makes sense, but it's &lt;u&gt;not at all intuitive&lt;/u&gt; up front. I asked a couple colleagues to guess the outcome of the code, and both guessed wrong. I suspect that most of you will also be surprised by the results. Hindsight is 20/20, but up front, this one is nonsense.&lt;/p&gt;

&lt;p&gt;Deadlocks in SQL server mean that SQL will kill one of the transactions and roll it back. This frees the locks and allows the other transaction to proceed. In the scenario above, we force a deadlock, meaning that one of the transactions is ROLLED BACK on the server. &lt;u&gt;It's not just "zombied"&lt;/u&gt;, which would cause "SELECT XACT_STATE()" to return "-1". No, in this case, the transaction is done. &lt;u&gt;There is no more transaction&lt;/u&gt;.&lt;/p&gt;

&lt;p&gt;So, how does one of those "C" statements get applied? Basically, &lt;u&gt;SqlCommand doesn't know that there is a problem with the transaction on the server&lt;/u&gt;, nor does it ask the SqlTransaction object to check. Instead, it just sends the statement to the server, assuming that the server still has a transaction open on the current connection. But there is no transaction. As a result, those &lt;u&gt;statements are executed with no transaction at all&lt;/u&gt;. The subsequent Rollback() has no means to undo their work.&lt;/p&gt;

&lt;h4&gt;Is This a Bug?&lt;/h4&gt;

&lt;p&gt;Calling something a bug is rather severe. In this case, I suspect that the framework can do better. &lt;/p&gt;

&lt;p&gt;The system does some checks to ensure proper &amp;amp; safe usage of the SqlTransaction, but not enough. After a deadlock, the client still has a reference to a SqlTransaction object. This object still thinks that it has a transaction on the server. It will even allow you to call Rollback() on this transaction object after the deadlock. But it won't let you call Commit(). It seems that SqlTransaction knows that the transaction can't commit, and throws an error back at you. Additionally, if you use a SqlConnection with a SqlCommand, but don't pass the associated SqlTransaction, then it will throw an error. &lt;/p&gt;

&lt;p&gt;So the system does some internal checks, but it doesn't check for the deadlock scenario. &lt;em&gt;Well, I think it should do better.&lt;/em&gt; Before executing a command, it should check whether the associated transaction is gone. If the server transaction is gone, it shouldn't even run the command. It should just error. Otherwise, SqlCommand will continue to run the statements outside of any transaction.&lt;/p&gt;

&lt;p&gt;I don't know if this is possible, or if it has some sever side-effects, but the current behavior of SqlTransaction is a very dangerous and sharp edge on the API surface of the .NET framework. A transaction that doesn't actually roll back the associated commands is not good.&lt;/p&gt;

&lt;h4&gt;Solution: Catch Deadlock Errors and Halt&lt;/h4&gt;

&lt;p&gt;The solution seems to require catching the SqlException, inspecting the Number to see if it's a deadlock, and then taking an alternate course of action. In the case of retry logic, the processing should immediately stop and rollback to prevent any subsequent commands from executing outside a transaction.&lt;/p&gt;

&lt;p&gt;To catch a deadlock, look for SqlException.Number == 1205. This indicates a deadlock occurred.&lt;/p&gt;

&lt;p&gt;Happy (Transaction) Coding!&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/190.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/190.aspx</wfw:comment>
        <slash:comments>23</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/190.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/190.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Updated version of Monitored Undo Framework released</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2012/01/31/updated-version-of-monitored-undo-framework-released.aspx" />
        <id>http://blog.alner.net/archive/2012/01/31/updated-version-of-monitored-undo-framework-released.aspx</id>
        <published>2012-01-31T10:24:00Z</published>
        <updated>2012-01-31T10:24:00Z</updated>
        <content type="html">&lt;p&gt;Today I released an updated version of the &lt;a href="http://muf.codeplex.com"&gt;Monitored Undo Framework&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Changes include:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;A new parameter on the DefaultChangeFactory's methods for specifying the "description of the change". This can be helpful in cases where the UI shows a list of the undo / redo changes.&lt;/li&gt;    &lt;li&gt;A new WPF sample that shows, in a simpler codebase, how to use the framework.&lt;/li&gt;    &lt;li&gt;Updated build script that compiles all solutions, run the tests, and package the NuGet package.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;These changes are also available via NuGet.&lt;/p&gt;  &lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/189.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/189.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/189.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/189.aspx</trackback:ping>
    </entry>
    <entry>
        <title>&amp;quot;tfpt unshelve /migrate&amp;quot; Doesn't Account for Renames</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2012/01/26/tfpt_unshelve_migrate_missed_changes_due_to_file_renames.aspx" />
        <id>http://blog.alner.net/archive/2012/01/26/tfpt_unshelve_migrate_missed_changes_due_to_file_renames.aspx</id>
        <published>2012-01-26T16:14:00Z</published>
        <updated>2012-01-26T16:14:00Z</updated>
        <content type="html">&lt;p&gt;A quick note about Team Foundation Power Tools (TFPT)'s "Unshelve" command…&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;tfpt unshelve&lt;/font&gt; has a &lt;font face="Courier New"&gt;/MIGRATE&lt;/font&gt; switch that will allow unshelving changes into a different branch / location than the one where they were originally shelved. I won't re-iterate the many articles describing how to use this command.&lt;/p&gt;  &lt;p&gt;One issue that I ran into is unshelving a set of changes into a branch where some of the shelved files had been renamed / moved. It seems that the /migrate switch doesn't go back into TFS version history to locate the renames. Instead, it simply pulls out the changes and re-applies them to the new location. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;For Example:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Let's say that I start with &lt;font face="Courier New"&gt;Branch A&lt;/font&gt;. One user (John Doe) get's latest and starts making changes.&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Branch A     &lt;br /&gt;    Src      &lt;br /&gt;        File1.txt&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Then… a different user (Jane Smith) renames &lt;font face="Courier New"&gt;File1.txt&lt;/font&gt;&lt;font face="Arial"&gt; and checks that in.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Branch A     &lt;br /&gt;    Src      &lt;br /&gt;        File1_RENAMED.txt&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Arial"&gt;Then… (for some reason), they need to move John's changes from &lt;font face="Courier New"&gt;Branch A&lt;/font&gt; to another branch. (Let's pretend that Branch A is the main branch, but the changes are too large for this iteration, so they want to move them to a separate branch for a future release.) So they create &lt;font face="Courier New"&gt;Branch B&lt;/font&gt;, which looks like this:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Branch B     &lt;br /&gt;    Src      &lt;br /&gt;        File1_RENAMED.txt&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Then… John shelves his changes and they attempt to use &lt;font face="Courier New"&gt;tfpt unshelve /migrate&lt;/font&gt; to move the changes to &lt;font face="Courier New"&gt;Branch B&lt;/font&gt;. &lt;/p&gt;  &lt;p&gt;But a strange thing happens. They end up with this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Branch B     &lt;br /&gt;    Src      &lt;br /&gt;        File1.txt      &lt;br /&gt;        File1_RENAMED.txt&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Huh? How'd that happen? &lt;/p&gt;  &lt;p&gt;Someone who knows version control well could probably explain why, and suggest that this is obvious. But it wasn't to me, and as a result, some of the changes in the shelveset did not make it into the target solution.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;How I should have done it…&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If I was going to do this again, I think I'd:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Get the source and the target branches to the same version. (Merge changes as needed between the branches.)&lt;/li&gt;    &lt;li&gt;In the source branch, get latest version so that the local workspace has the latest version.&lt;/li&gt;    &lt;ol&gt;     &lt;li&gt;This should propagate any pending renames / moves that were made in that source branch, or it's parent branches.&lt;/li&gt;   &lt;/ol&gt;    &lt;li&gt;Shelve the changes that should be moved.&lt;/li&gt;    &lt;li&gt;In the target branch, get latest version.&lt;/li&gt;    &lt;li&gt;Run &lt;font face="Courier New"&gt;tfpt unshelve /migrate …&lt;/font&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/188.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/188.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/188.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/188.aspx</trackback:ping>
    </entry>
    <entry>
        <title>A Visual Studio Extesion to make Scrolling Better!</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2012/01/23/vs_extension_keyboard_scrolling_buffer.aspx" />
        <id>http://blog.alner.net/archive/2012/01/23/vs_extension_keyboard_scrolling_buffer.aspx</id>
        <published>2012-01-23T22:37:54Z</published>
        <updated>2012-01-23T22:37:54Z</updated>
        <content type="html">&lt;p&gt;Hi All,&lt;/p&gt;
&lt;p&gt;A friend of mine (&lt;a href="http://jnastase.alner.net/"&gt;John Nastase&lt;/a&gt;) saw a &lt;a href="http://twitter.com/#!/nathanaw/status/160416144199647232"&gt;tweet&lt;/a&gt; or &lt;a href="http://twitter.com/#!/nathanaw/status/160416480838692864"&gt;two&lt;/a&gt; of mine complaining about scrolling in Visual Studio.&lt;/p&gt;
&lt;p&gt;What did he do? He wrote a VS extension to make it happen!!! &lt;/p&gt;
&lt;p&gt;Here's &lt;a href="http://visualstudiogallery.msdn.microsoft.com/03e6b964-0f7c-4556-8300-8dc857bb9a10"&gt;the extension that he just published in the VS extension gallery.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It basically adds a "cursor buffer" space to the top and bottom of the window so that as arrow down the page, the page starts to scrolling before the cursor hits the VERY BOTTOM OF THE PAGE. Instead, it starts scrolling a little earlier so that you can see what's coming. This saves you from scrolling too far and then having to arrow back up to where you want to be.&lt;/p&gt;
&lt;p&gt;Brilliant!&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/187.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/187.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/187.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/187.aspx</trackback:ping>
    </entry>
    <entry>
        <title>EF Inserts Failing Because of Missing Association in SSDL</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2012/01/19/ef-inserts-failing-because-of-missing-association-in-ssdl.aspx" />
        <id>http://blog.alner.net/archive/2012/01/19/ef-inserts-failing-because-of-missing-association-in-ssdl.aspx</id>
        <published>2012-01-19T16:37:00Z</published>
        <updated>2012-01-19T16:37:00Z</updated>
        <content type="html">&lt;p&gt;I just found that Entity Framework (4.0) can stumble on One-To-One relationships if the EDMX's schema storage layer (SSDL) is missing the association that represents the Foreign Key in the database. I suppose this makes sense, but it's only obvious to me in hindsight.&lt;/p&gt;  &lt;p&gt;I don't know how my EDMX ended up missing the SSDL association for the Foreign Key, but it was missing. However the the Conceptual Layer had the relationship, so the diagram made it look like it was associated. And because this is a supported scenario, it didn't complain at me that I was missing anything.&lt;/p&gt;  &lt;p&gt;But…&lt;/p&gt;  &lt;p&gt;When I went to save the records, EF stumbled on the insert. In my case, I had two entities that were related by a "1 to 0..1" relationship. I'm guessing that EF saw this, evaluated the SSDL layer's metadata and decided that order of insert didn't matter. As a result, it inserted them in alphabetical order… &lt;em&gt;and failed&lt;/em&gt;. It failed because in my DB, I did have a foreign key.&lt;/p&gt;  &lt;p&gt;The fix was to manually add the association into the SSDL layer.&lt;/p&gt;  &lt;p&gt;Note: Editing EDMX files by hand SUCKS!&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/185.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/185.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/185.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/185.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Microsoft's MVP program and Rob Eisenberg</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2012/01/05/ms_mvp_program_and_eisenberg.aspx" />
        <id>http://blog.alner.net/archive/2012/01/05/ms_mvp_program_and_eisenberg.aspx</id>
        <published>2012-01-05T14:34:00Z</published>
        <updated>2012-01-05T14:34:00Z</updated>
        <content type="html">&lt;p&gt;This is a long read, but it's got some detailed insight on the MVP program at Microsoft. I've heard these sentiments before, and I'm sure that it's not black and white. Regardless, Microsoft's actions in this case are unacceptable.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://devlicio.us/blogs/rob_eisenberg/archive/2012/01/04/how-i-lost-regained-and-then-turned-down-an-mvp-award.aspx" href="http://devlicio.us/blogs/rob_eisenberg/archive/2012/01/04/how-i-lost-regained-and-then-turned-down-an-mvp-award.aspx"&gt;http://devlicio.us/blogs/rob_eisenberg/archive/2012/01/04/how-i-lost-regained-and-then-turned-down-an-mvp-award.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If you don't know Rob Eisenberg, he's the creator of &lt;a href="http://caliburn.codeplex.com/" target="_blank"&gt;Caliburn&lt;/a&gt; and &lt;a href="http://caliburnmicro.codeplex.com/" target="_blank"&gt;Caliburn Micro&lt;/a&gt; frameworks for XAML based platforms (WPF, Silverlight, WP7). If you want to have your mind blown, take a look at his source code for Caliburn Micro (and even more so for Caliburn). While you're at it, watch his "&lt;a href="http://channel9.msdn.com/events/MIX/MIX10/EX15" target="_blank"&gt;Build your own MVVM framework&lt;/a&gt;" presentation. I reviewed a lot of WPF frameworks, but Caliburn Micro stands alone in it's elegance, simplicity, and amazing use of the C# / .NET platform.&lt;/p&gt;  &lt;p&gt;I seriously hope that MS addresses whatever is behind this story. We need people like Rob! They should be rewarded for their amazing contributions to the community.&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/184.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/184.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/184.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/184.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Good Times at the .NET SIG&amp;hellip;</title>
        <link rel="alternate" type="text/html" href="http://blog.alner.net/archive/2011/12/14/good_times_at_net_sig_craftsmanship.aspx" />
        <id>http://blog.alner.net/archive/2011/12/14/good_times_at_net_sig_craftsmanship.aspx</id>
        <published>2011-12-14T08:15:00Z</published>
        <updated>2011-12-14T08:15:00Z</updated>
        <content type="html">&lt;p&gt;Had a great time at the &lt;a href="http://www.bennettadelson.com/AllEvents.aspx?sig=1e77a027-e2c4-df11-a738-001f29c6fb82" target="_blank"&gt;.NET SIG&lt;/a&gt; last night where we talked about Software Craftsmanship and did Katas together. We had a good turn out (~40 attendees), and we spent a majority of the time doing Katas. &lt;/p&gt;  &lt;p&gt;I was quite impressed by the group's willingness to try Pair Programming. Here's pic that Andrew Thorne snapped of one side of the room. You can see people working on a kata, mostly in pairs!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.alner.net/images/blog_alner_net/Windows-Live-Writer/Good-Times-at-the-.NET-SIG_746D/image_2.png" rel="lightbox"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.alner.net/images/blog_alner_net/Windows-Live-Writer/Good-Times-at-the-.NET-SIG_746D/image_thumb.png" width="244" height="139" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="https://twitter.com/#!/Bennett_Adelson/status/146744206772281345/photo/1/large" href="https://twitter.com/#!/Bennett_Adelson/status/146744206772281345/photo/1/large"&gt;https://twitter.com/#!/Bennett_Adelson/status/146744206772281345/photo/1/large&lt;/a&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Thanks to those of you who came out. Hope you enjoyed the time and got something out of it.&lt;/p&gt;  &lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://blog.alner.net/aggbug/183.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://blog.alner.net/comments/183.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.alner.net/comments/commentRss/183.aspx</wfw:commentRss>
        <trackback:ping>http://blog.alner.net/services/trackbacks/183.aspx</trackback:ping>
    </entry>
</feed>