<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devplanet.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">What are we going to do tomorrow night, Brain? </title><subtitle type="html" /><id>http://devplanet.com/blogs/brianr/atom.aspx</id><link rel="alternate" type="text/html" href="http://devplanet.com/blogs/brianr/default.aspx" /><link rel="self" type="application/atom+xml" href="http://devplanet.com/blogs/brianr/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.30912.2823">Community Server</generator><updated>2008-01-11T19:34:00Z</updated><entry><title>Work Harder</title><link rel="alternate" type="text/html" href="/blogs/brianr/archive/2008/10/21/work-harder.aspx" /><id>/blogs/brianr/archive/2008/10/21/work-harder.aspx</id><published>2008-10-21T15:26:00Z</published><updated>2008-10-21T15:26:00Z</updated><content type="html">&lt;p&gt;Work Harder!&amp;nbsp; That is a statement I find myself repeating daily.&amp;nbsp; People often wonder what makes one person better at a certain task than others.&amp;nbsp; There is a truly simple answer, practice.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Natural ability is a myth. &amp;nbsp;With the exception of physical limitations, all ability is gained through practice.&amp;nbsp; No infant is born with the innate ability to walk.&amp;nbsp; No musician picks up an instrument for the first time and performs a flawless number.&amp;nbsp; Everything &amp;lsquo;great&amp;#39; is preceded by countless not-so-great attempts.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The human race is a term that to some is a simple definition of our status as homosapiens.&amp;nbsp; To me, it is a bit more literal.&amp;nbsp; I recognize that there are billions of people in this world, all of whom want the same things I do.&amp;nbsp; What sets certain individuals apart from the pack is their willingness to work harder than the rest.&amp;nbsp; So for me, it&amp;#39;s the race of humans.&amp;nbsp; Who wants to work harder?&amp;nbsp; Who wants to spend that extra effort day after day to be the best at what they do.&amp;nbsp; Someone who doesn&amp;#39;t work as hard as I do does not deserve the same things I deserve, just as I do not deserve the same benefits of the people who work harder than I am willing to.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;I hear complaints from people about the state of their lives, every argument of which never focuses on their lack of effort.&amp;nbsp; It is always the result of some innocuous outside influence.&amp;nbsp; Bunk.&amp;nbsp; People who work hard, achieve more.&amp;nbsp; Good things happen to good people who work hard.&amp;nbsp; Being good isn&amp;#39;t enough.&amp;nbsp; There are lots of &amp;quot;good&amp;quot; people, if the definition of &amp;quot;good&amp;quot; can be simplified to &amp;quot;not being bad&amp;quot;.&amp;nbsp; Spend a few more hours with your face buried in a book rather than a pint of beer.&amp;nbsp; Unless, of course, your goal is to be the best drinker on earth.&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Everything that has gone right in my life happened to me when I went the extra mile.&amp;nbsp; Every real accomplishment didn&amp;#39;t come from the 8 to 5 daily grind.&amp;nbsp; Good things happened during the hundred-hour weeks of work.&amp;nbsp; Times when 8 to 5 wouldn&amp;#39;t have been enough to get the job done, allowing the opportunity to pass right by.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;There have been many times I have explained to people that epiphanies have come to me in my sleep.&amp;nbsp; Though I was not lying, this is not a result of me having some abnormal super power.&amp;nbsp; It is a result of me wrapping my mind so deeply around a problem that I am consumed by it even during my few hours of sleep.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;I like to think that everything that has happened to me in my life, I&amp;#39;ve earned.&amp;nbsp; This, of course, includes all of the bad things.&amp;nbsp; For many years my interests were simply in having fun, so my career took a nose-dive.&amp;nbsp; Then I focused entirely on work which destroyed countless relationships, as well as my physical health. So while balance has become important, I have recognized that&amp;nbsp;every decision&amp;nbsp;comes with consequences;&amp;nbsp;consequences which I hope to never complain about.&lt;/p&gt;
&lt;p&gt;People make choices in their lives.&amp;nbsp; If your choice is to pursue a career or path in your life that will never financially stabilize, you have no right to complain about finances.&amp;nbsp; You have chosen to sacrifice financial success for your love or interest in what it is you do.&amp;nbsp; It is not society&amp;#39;s responsibility to fill in for your financial woes.&amp;nbsp; If you choose to sacrifice your personal life for professional glory, then do not cry about your lack of intimacy.&amp;nbsp; You chose that path.&amp;nbsp; Just realize that everything requires hard work.&amp;nbsp; Even if an individual&amp;#39;s goal in life is to be the best parent their child could have, then they must work for it.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;This is not to say that I am better or worse than anyone else in this world.&amp;nbsp; What I am attempting to say is that I take responsibility for what happens in my life.&amp;nbsp; I will not give up, I will not rest until I am the best I can be at what I do, regardless of what this life throws at me.&amp;nbsp; The best I can be at anything will require a lifetime of effort.&amp;nbsp; So I suppose it is a valid assumption to say that I will only achieve this in the moment immediately before my death.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;I truly wish more people would take responsibility for their lives.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=12160" width="1" height="1"&gt;</content><author><name>BrianR</name><uri>http://devplanet.com/members/BrianR/default.aspx</uri></author></entry><entry><title>Thread Safe Dictionary Update</title><link rel="alternate" type="text/html" href="/blogs/brianr/archive/2008/09/29/thread-safe-dictionary-update.aspx" /><id>/blogs/brianr/archive/2008/09/29/thread-safe-dictionary-update.aspx</id><published>2008-09-29T16:14:00Z</published><updated>2008-09-29T16:14:00Z</updated><content type="html">&lt;p&gt;
&lt;p&gt;For those of you that have read my post about the Thread Safe Dictionary, I have a few updates.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;In recent months, I have done a ridiculous amount of multi-threaded work.&amp;nbsp; This has forced me to expand my threading libraries.&amp;nbsp; One of the primary objects that required changes\fixes was my dictionary.&amp;nbsp; &lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;The dictionary uses ReaderWriterLockSlim locks.&amp;nbsp; These are clean, lightweight locks that MS has provided.&amp;nbsp; Most importantly, they allow upgradeable read locks.&amp;nbsp; I now use simple IDisposable locking wrappers.&amp;nbsp; This allows us to use the &amp;quot;using&amp;quot; syntax to ensure lock releases.&lt;/p&gt;
&lt;p&gt;It is important to note that no safe dictionary can provide safe inserts without the caller forcing a lock.&amp;nbsp; This is because by the time you check for the existence of an object and then insert it, it may have been inserted by another thread.&amp;nbsp; The only way to prevent this is by doing a &amp;quot;blind&amp;quot; merge.&amp;nbsp; The reason&amp;nbsp;I call it blind, is that when you do a merge, we check for existence, and do a replace\insert within the scope of a single write lock.&amp;nbsp; This means you cannot control which objects get replaced in the dictionary.&amp;nbsp; This is rarely important in caching situations.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the code:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:8pt;font-family:&amp;#39;Verdana&amp;#39;,&amp;#39;sans-serif&amp;#39;;"&gt;&lt;a href="http://devplanet.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brianr.Code+Snippets/ThreadSafeDictionary.zip"&gt;ThreadSafeDictionary.zip&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=12123" width="1" height="1"&gt;</content><author><name>BrianR</name><uri>http://devplanet.com/members/BrianR/default.aspx</uri></author><category term="Threading" scheme="http://devplanet.com/blogs/brianr/archive/tags/Threading/default.aspx" /><category term="C#" scheme="http://devplanet.com/blogs/brianr/archive/tags/C_2300_/default.aspx" /></entry><entry><title>Thread Safe Dictionary in .NET with ReaderWriterLockSlim</title><link rel="alternate" type="text/html" href="/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx" /><id>/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx</id><published>2008-09-26T15:14:00Z</published><updated>2008-09-26T15:14:00Z</updated><content type="html">&lt;p&gt;Since&amp;nbsp;MS has decided to not include a thread-safe dictionary in the .NET framework, many of us have been forced to implement our own.&amp;nbsp; What MS has done&amp;nbsp;now with .NET 3.5 is given us a newer locking mechanism which makes this task easier.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Previously, we had 2 lock mechanisms, neither of which worked very well for my uses.&amp;nbsp; The first is the Lock statement.&amp;nbsp; While this method is effective, it causes serious contention issues with simultaneous reads\writes.&amp;nbsp; Since it is generally safe to execute multiple concurrent reads from a dictionary, this was a huge performance flaw as the Lock statement was forcing us to perform all actions against the object in a serial fashion.&lt;/p&gt;
&lt;p&gt;So that left ReaderWriterLock, which would allow us to take out Reader &amp;amp; Writer locks independently.&amp;nbsp; This seemed to be the answer.&amp;nbsp; Unfortunately, after further testing and review, MS and the dev communities warned against this lock type&amp;nbsp;as it could have unintended consequences in certain situations.&amp;nbsp; The explanations for these I will not go in to, a simple Google search will answer those questions.&amp;nbsp; For the most part, I don&amp;#39;t have the mental capacity to understand, much less explain the failures.&amp;nbsp; I will tell you that I have tested this method, and ran in to some issues, and subsequently abandoned the approach.&lt;/p&gt;
&lt;p&gt;With&amp;nbsp;.NET 3.5 comes the brand-spankin-new ReaderWriterLockSlim.&amp;nbsp;&amp;nbsp;ReaderWriterLockSlim is similar to the ReaderWriterLock in functionality, minus some of the drawbacks.&amp;nbsp; Of course any new approach will bring on its own consequences, and if you do a little research, you will find that Slim isn&amp;#39;t infallible either.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Many of our applications implement the Factory model.&amp;nbsp; Factory models are great, they are extensible, and they can be extremely performant.&amp;nbsp; With that said, any data driven application that uses the Factory model without a caching model, will most likely perform poorly.&amp;nbsp; So, in our factories, we build in a caching mechanism.&amp;nbsp; A very simple type and ID based cache that allows us to persist commonly used objects to in-memory cache for a specific amount of time.&amp;nbsp; I won&amp;#39;t go in to the implementation of this model here as every caching implementation has its own needs and wants.&lt;/p&gt;
&lt;p&gt;At the heart of this&amp;nbsp;and likely any caching model is inevitably a Dictionary or Dictionary like structure.&amp;nbsp; MS programmers have spent countless hours fine-tuning the Dictionary class to make it as performant as possible.&amp;nbsp; I challenge anyone to write a managed Dictionary that performs as well in such a wide variety of scenarios.&amp;nbsp; I&amp;#39;ve tried and failed.&amp;nbsp; Unfortunately, MS has not provided a thread-safe implementation.&amp;nbsp; Generally when you run into the question of thread-safety, most people have no idea what you are talking about.&amp;nbsp; The problem with writing truly thread-safe code that can work in any scenario is that you will sacrifice performance.&amp;nbsp; If you tailor your thread-safe mechanisms to your particular problem, you can generally maintain a higher level of performance.&lt;/p&gt;
&lt;p&gt;The reason we need thread-safety is not that we are specifically spawning threads.&amp;nbsp; In IIS, worker processes are inherently multi-threaded.&amp;nbsp; Therefore, using static objects in a web-farm generally requires some level of thread safety, otherwise you will get dreaded &amp;quot;An item with the same key has already been added&amp;quot; errors.&amp;nbsp; This is because between the time you check to see if a key already exists in your dictionary and the time you insert it, some other thread may have inserted this key.&amp;nbsp; This is especially the case in object factories, because you have multiple threads attempting to access/create objects and subsequently cache them.&lt;/p&gt;
&lt;p&gt;This is the code I&amp;#39;ve written.&amp;nbsp; This has not been tested yet, so please use it carefully.&amp;nbsp; I will keep this post updated with any changes and test results.&amp;nbsp; I also have not made this class utilize lock escalation, which ReaderWriterLockSlim supports.&amp;nbsp; As always, &lt;strong&gt;please perform your own testing&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://devplanet.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brianr.Code+Snippets/ThreadSafeDictionary.zip" class="null"&gt;ThreadSafeDictionary.cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[Update]&lt;br /&gt;Through some testing, I found the need to update the ThreadSafe Dictionary.&amp;nbsp; I changed all of the locking to use IDisposables to ensure lock creation and destruction.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=13" width="1" height="1"&gt;</content><author><name>BrianR</name><uri>http://devplanet.com/members/BrianR/default.aspx</uri></author><category term="Dictionary" scheme="http://devplanet.com/blogs/brianr/archive/tags/Dictionary/default.aspx" /><category term="Threading" scheme="http://devplanet.com/blogs/brianr/archive/tags/Threading/default.aspx" /><category term="C#" scheme="http://devplanet.com/blogs/brianr/archive/tags/C_2300_/default.aspx" /></entry><entry><title>Microsoft 2008 Platform Launch - Heroes Happen {Here}</title><link rel="alternate" type="text/html" href="/blogs/brianr/archive/2008/03/01/microsoft-2008-platform-launch-heroes-happen-here.aspx" /><id>/blogs/brianr/archive/2008/03/01/microsoft-2008-platform-launch-heroes-happen-here.aspx</id><published>2008-03-01T20:28:00Z</published><updated>2008-03-01T20:28:00Z</updated><content type="html">&lt;p&gt;For those of you that live under a rock, the Microsoft 2008 Platform Launch has kicked off.&amp;nbsp; It is the launch event for Sql Server 2008, Windows Server 2008, and Visual Studio 2008.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The company I work for, Big Hammer, has been featured in the event.&amp;nbsp; As well of some of my products.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a class="" title="Case Study" href="http://www.microsoft.com/casestudies/casestudy.aspx?casestudyid=4000001474" target="_blank"&gt;case study&lt;/a&gt; to get an idea of what I do all day.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=305" width="1" height="1"&gt;</content><author><name>BrianR</name><uri>http://devplanet.com/members/BrianR/default.aspx</uri></author><category term="Heroes Happen Here" scheme="http://devplanet.com/blogs/brianr/archive/tags/Heroes+Happen+Here/default.aspx" /><category term="Launch Event" scheme="http://devplanet.com/blogs/brianr/archive/tags/Launch+Event/default.aspx" /><category term="Microsoft" scheme="http://devplanet.com/blogs/brianr/archive/tags/Microsoft/default.aspx" /></entry><entry><title>SQL Server Constants... The Constant Struggle..</title><link rel="alternate" type="text/html" href="/blogs/brianr/archive/2008/02/13/sql-server-constants-the-constant-struggle.aspx" /><id>/blogs/brianr/archive/2008/02/13/sql-server-constants-the-constant-struggle.aspx</id><published>2008-02-13T22:13:00Z</published><updated>2008-02-13T22:13:00Z</updated><content type="html">&lt;p&gt;Sql Server does not allow for user defined constants.&amp;nbsp; So we are forced to take other routes like hard-coded values, scalar udf&amp;#39;s, settings tables, etc.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Unfortunately, all methods are &lt;strong&gt;not&lt;/strong&gt; equal.&amp;nbsp; You need to carefully consider your use of different methods, and test the results as all of these methods result in different approaches by the query optimizer.&lt;/p&gt;
&lt;p&gt;We use an object factory that is tightly coupled to database tables.&amp;nbsp; To simplify data access we have a single view that becomes, in essence, a partitioned table.&amp;nbsp; We&amp;#39;ll call it dbo.Object&lt;/p&gt;
&lt;p&gt;This view looks something like this:&lt;/p&gt;
&lt;p&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
2
3
4
5
6
7
8
9
10
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;create&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;view&lt;/span&gt; dbo.Object
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;as&lt;/span&gt;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;select&lt;/span&gt; 1 &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;as&lt;/span&gt; ObjectType_ID, ID, Description &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.[&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;User&lt;/span&gt;]
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;union&lt;/span&gt; &lt;span style="color:Silver;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;all&lt;/span&gt; 
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;select&lt;/span&gt; 2 &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;as&lt;/span&gt; ObjectType_ID, ID, Description &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.object2
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;union&lt;/span&gt; &lt;span style="color:Silver;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;all&lt;/span&gt; 
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;select&lt;/span&gt; 3 &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;as&lt;/span&gt; ObjectType_ID, ID, Description &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.object3
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;union&lt;/span&gt; &lt;span style="color:Silver;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;all&lt;/span&gt; 
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;select&lt;/span&gt; 4 &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;as&lt;/span&gt; ObjectType_ID, ID, Description &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.object4
&lt;span style="color:Teal;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;--etc..&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt; &lt;/p&gt;
&lt;p&gt;Now to query against that view, you can simply predicate on objecttype.&amp;nbsp; If you check the IO statistics, it is only looking up against the one table, provided you query it properly.&amp;nbsp; Don&amp;#39;t bother looking at the Query Plan as it does not truly reflect what the server does to fetch the data.&lt;/p&gt;
&lt;p&gt;So the idea is, we have a table which directly related concrete types in code to database object types.&amp;nbsp; This way objects can very simply load themselves from the DB.&amp;nbsp; Poor coding practices aside, for many applications this is a perfectly legitimate model.&lt;/p&gt;
&lt;p&gt;The problem comes in when writing queries against these partitioned views.&amp;nbsp; We were looking for a way to not have to hard-code type ID&amp;#39;s into sprocs or queries.&amp;nbsp; This is where constants would be a big help.&amp;nbsp; I could potentially define a constant called @@UserType and equate it to it&amp;#39;s corresponding database object type.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;This way when writing a query to extract all user info, I could simply write:&lt;/p&gt;
&lt;p&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; * &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.Object &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;where&lt;/span&gt; ObjectType_ID = @@UserType&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;Here are the multiple ways we have tried to accomplish this, each has it&amp;#39;s own unique performance outcomes:&lt;br /&gt;&lt;br /&gt;First, turn IO statistics output on for your connection.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;set&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;statistics&lt;/span&gt; io &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;on&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;This query works properly, unfortunately we are hardcoding the ID, which is what we are trying not to do.&amp;nbsp; This is the baseline.&amp;nbsp; We want results identical to this.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; * &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.Object &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;where&lt;/span&gt; ObjectType_ID = 2&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;So lets try creating a UDF&amp;nbsp;that returns that ObjectType_ID&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;create&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;function&lt;/span&gt; [ObjectType].[&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;User&lt;/span&gt;]()
returns &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;as&lt;/span&gt;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;begin&lt;/span&gt;
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt;(1) 
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;This query unfortunately evaluates each table, but at least it doesn&amp;#39;t scan them&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;declare&lt;/span&gt; @objtype &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;set&lt;/span&gt; @objtype = ObjectType.[&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;User&lt;/span&gt;]() &lt;span style="color:Teal;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;-- a udf that returns a value&lt;/span&gt;

&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; * &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.Object &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;where&lt;/span&gt; ObjectType_ID = @objtype &lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;This query is closer, but it is creating a working table and is evaluating for every row&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; * &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.Object &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;where&lt;/span&gt; ObjectType_ID = ObjectType.[&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;User&lt;/span&gt;]()&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;I modified the UDF to take a&amp;nbsp;useless param,&amp;nbsp;in hopes that the deterministic decisions were based on the input param to output, but to no avail.&lt;br /&gt;The results were same as above.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; * &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.Object &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;where&lt;/span&gt; ObjectType_ID = ObjectType.[&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;User&lt;/span&gt;](0)&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;I changed the UDF to take the string Type name as an input, and a simple CASE or IF statement is user to return the correct ID.&lt;br /&gt;This would be optimal, as it would prevent me from having to create a UDF for each Type.&amp;nbsp; I also tried it with looking up the value in a table.&lt;br /&gt;Unfortunately we get the same result.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; * &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.Object &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;where&lt;/span&gt; ObjectType_ID = ObjectType.GetType(&lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;#39;User&amp;#39;&lt;/span&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;Lets try a subquery.&lt;br /&gt;This is the worst, as it scans each table.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
2
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; * &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;from&lt;/span&gt; dbo.Object 
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;where&lt;/span&gt; ObjectType_ID = (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; ObjectType.[&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;User&lt;/span&gt;]())&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt; &lt;/p&gt;
&lt;p&gt;Joining on a settings table is an option, unfortunately as we may be doing multiple joins on tables requiring these constants, we would have to do multiple joins on the settings table, which turns out to be very inefficient.&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://devplanet.com/blogs/memydatabaseandi/default.aspx" title="Chuck Heinzelman"&gt;Chuck Heinzelman&lt;/a&gt; pointed out an intersting function to call to check if the UDF is being treated as deterministic:&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;select&lt;/span&gt; objectpropertyex(&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;object_id&lt;/span&gt;(&lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;#39;objecttype.user&amp;#39;&lt;/span&gt;), &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;#39;isdeterministic&amp;#39;&lt;/span&gt;) &lt;span style="color:Teal;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;-- returns 0&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;This returns &lt;strong&gt;False&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So taking Chuck&amp;#39;s advice,&amp;nbsp;I schema bound the function:&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;alter&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;function&lt;/span&gt; [ObjectType].[&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;User&lt;/span&gt;]()
returns &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;with&lt;/span&gt; schemabinding
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;as&lt;/span&gt;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;begin&lt;/span&gt;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt;(1) 
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;end&lt;/span&gt; &lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;Now, we try this again:&amp;nbsp;&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
    &lt;tr style="vertical-align:top;line-height:normal;"&gt;
        &lt;td style="width:40px;text-align:right;"&gt;
            &lt;pre style="font-family:courier new;font-size:11px;color:gray;margin:0px;padding:2px;border-right:solid 1px #e7e7e7;"&gt;1
&lt;/pre&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;Select&lt;/span&gt; objectpropertyex(&lt;span style="color:Fuchsia;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;object_id&lt;/span&gt;(&lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;#39;objecttype.user), &amp;#39;&lt;/span&gt;isdeterministic&amp;#39;) &lt;span style="color:Teal;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;-- returns 1&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;Excellent, now it returns &lt;strong&gt;True&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately, we get almost the same results if we re-run the queries.&amp;nbsp; &lt;br /&gt;I did not, however, profile it to see if it is truly evaluating the function for every row.&amp;nbsp; I suspect it is not.&amp;nbsp; So the use of the UDF may be not so bad if the only result is that it is using a worktable.&amp;nbsp; Unfortunately, every place i use the UDF in a query, it creates another worktable.&lt;/p&gt;
&lt;p&gt;So until we have a better &lt;strong&gt;CONST&lt;/strong&gt; struct in SQL we will be forced to hardcode values for some of our queries.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=83" width="1" height="1"&gt;</content><author><name>BrianR</name><uri>http://devplanet.com/members/BrianR/default.aspx</uri></author><category term="Sql 2005" scheme="http://devplanet.com/blogs/brianr/archive/tags/Sql+2005/default.aspx" /></entry><entry><title>Media Center Woes</title><link rel="alternate" type="text/html" href="/blogs/brianr/archive/2008/01/26/media-center-woes.aspx" /><id>/blogs/brianr/archive/2008/01/26/media-center-woes.aspx</id><published>2008-01-26T19:46:00Z</published><updated>2008-01-26T19:46:00Z</updated><content type="html">&lt;p&gt;So about a year ago&amp;nbsp;i began my quest for the ultimate home media experience.&amp;nbsp; I have the A/V components(TV&amp;#39;s, Projectors, Speakers, Etc.) but i needed to tie all of my installations together.&amp;nbsp; I have a Projector with a 110+ inch screen in my basement, and a 73&amp;quot; DLP in my great room. I also have flat panel LCD&amp;#39;s scattered throughout my home.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The goal was&amp;nbsp;to provide live TV, recorded TV, music, and DVD access to all stations through one component.&amp;nbsp; Whether that component was an xbox 360, a Vista Media Center PC, or whatever, i wanted one at each station.&amp;nbsp; So i sat and chatted with a friend from work, &lt;a class="" title="Casey Chesnut" href="http://www.brains-n-brawn.com/" target="_blank"&gt;Casey Chesnut&lt;/a&gt;&amp;nbsp;who is a former Media Center MVP.&amp;nbsp; We decided to try a few approaches.&lt;/p&gt;
&lt;p&gt;So I started with the primary media center pc.&amp;nbsp; This was going to be my focal point, my connector to my digital cable, and the center for any DVR.&amp;nbsp; I did some research and found that the legal jackals at the digital cable companies are ensuring that only qualified (read paid-up)&amp;nbsp;manufacturers can sell media center pc&amp;#39;s with digital cable tuner cards.&amp;nbsp; So after some digging, i made a choice and purchased a &lt;a class="" title="s1Digital" href="http://www.s1digital.com/"&gt;s1Digital&lt;/a&gt; media center with&amp;nbsp;two digital cable tuner cards.&amp;nbsp; This thing was flaky as could be for the first few weeks.&amp;nbsp; After some configuration changes, uninstalling the Intel Viiv garbage, and a firmware update for my the tuner cards, it is finally stable.&amp;nbsp; The only thing that is left is that the machine has a built-in IR receiver that works only half of the time.&amp;nbsp; So i was forced to connect an external IR port.&amp;nbsp; The only problem is that now, half of the time, the machine is registering double button&amp;nbsp;actions from the remote.&amp;nbsp; This sucks.&amp;nbsp; So after an hour of looking around in the case for the cable or port to disconnect the built-in IR sensor, i just decided to cover the front face with tape.&amp;nbsp; Black Gaffers tape is the ultimate visual enhancement for a high-end home A/V setup.&amp;nbsp; The good news is that the machine is pretty slick.&amp;nbsp; Lots of processing power, and the video quality from digital cable is incredible.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Now, on to the second part of this install.&amp;nbsp; I have somewhere around 500 DVD&amp;#39;s that i&amp;#39;ve acquired over the past years.&amp;nbsp; I previously had them most of them in a 400 disc changer that was controlled via a pretty slick Escient media interface.&amp;nbsp; The Escient did all of the cataloging, and only twice did it fail to recognize a DVD.&amp;nbsp; Unfortunately, i found myself shuttling DVD&amp;#39;s from my upstairs to my downstairs or to my bedroom to watch them.&amp;nbsp; This is a hassle, and since i am a big lazy goon, i&amp;#39;m generally not too careful with them.&amp;nbsp; So, i decided to rip all of my DVD&amp;#39;s to a giant drive array.&amp;nbsp; So i bought 2 NAS devices, one is a ReadyNAS, and the other is a linksys.&amp;nbsp; The ReadyNAS is great, and i haven&amp;#39;t used the linksys yet, so i have no verdict.&amp;nbsp; Either way, i have something in the range of 5TB+ of RAID 5 storage.&amp;nbsp; This is great.&amp;nbsp; The only pain is that you can&amp;#39;t just copy most DVD&amp;#39;s to a file structure, as DRM prevents it.&amp;nbsp; The good news is that Slysoft AnyDVD fixes this problem and strips of all DRM.&amp;nbsp; I could have converted or compressed the DVD&amp;#39;s and saved some space, but i&amp;#39;m one of those people who prefers to have an exact copy of my hard media.&lt;/p&gt;
&lt;p&gt;Excellent, so now i have my movies all in one place.&amp;nbsp; Scratch that.&amp;nbsp; I will have them in one place once i&amp;#39;ve finished ripping them all.&amp;nbsp; Anyways, now i have a huge directory structure with &lt;em&gt;many &lt;/em&gt;of my dvd&amp;#39;s.&amp;nbsp; Unfortunately, coming from the Escient, i want a better and prettier interface than a folder structure.&amp;nbsp; Casey recommended the &lt;a class="" title="My Movies" href="http://www.mymovies.dk/" target="_blank"&gt;My Movies&lt;/a&gt; plugin for Media Center.&amp;nbsp; I installed it and it works fairly well.&amp;nbsp; It&amp;#39;s&amp;nbsp;a little buggy, but acceptable for a free community initiative.&amp;nbsp; This cataloged my DVD&amp;#39;s and allowed me to play them on my media center.&amp;nbsp; Sweet.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;So my Primary TV is mostly set.&amp;nbsp; Now lets get this lovely media piped to other rooms!&amp;nbsp; My first plan of attack was an xbox 360.&amp;nbsp; This worked really well.&amp;nbsp; I could connect to my media center and&amp;nbsp;watch live and recorded TV through my xbox!&amp;nbsp; This was awesome, such a simple solution.&amp;nbsp; Not only are 360 consoles fairly cheap, but they have great video and sound capabilities and i could play a game anywhere in the house.&amp;nbsp; Excellent, order up 5 xbox consoles right?&amp;nbsp; Negative.&amp;nbsp; The 360 console will not allow you to play a DVD format movie from a network share.&amp;nbsp; They have been recently extended to allow divx though.&amp;nbsp; Unfortunately at 110&amp;quot; divx looks like crap.&amp;nbsp; Also, i&amp;#39;ll be damned if i&amp;#39;m going to convert and store every movie i have to divx.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Casey, so intrigued by this debacle, began trying to circumvent this limitation.&amp;nbsp; Custom media streams, on-the-fly conversions, etc.&amp;nbsp; Nothing looked or worked very well.&amp;nbsp; Thanks for the effort though bud.&lt;/p&gt;
&lt;p&gt;On to plan B.&amp;nbsp; A media center PC at every TV.&amp;nbsp; Sounds like a winner if i can find a cheap enough PC to warrant using just for this purpose.&amp;nbsp; Enter HP Slimline Refurbs.&amp;nbsp; It turns out that buy.com was selling these very capable, very nice looking refurbs for just over $300.&amp;nbsp; Excellent.&amp;nbsp; Order a couple and give em a shot.&amp;nbsp; The machines themselves are impressive, great stats for a cheap machine, and they come with Vista Home Premium.&amp;nbsp;&amp;nbsp; Excellent.&amp;nbsp; Yes!&amp;nbsp;I can play my dvd&amp;#39;s!&amp;nbsp; &lt;/p&gt;
&lt;p&gt;But wait... i can&amp;#39;t use a Media Center PC as an extender, just like the xbox?&amp;nbsp; Nope! MS has failed me again.&amp;nbsp; The initiave in MS to provide a software based extender has been stalled or flat-out cancelled according to Casey.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;So, on these nice Media Center PC&amp;#39;s, i cannot watch live TV or recorded TV from my primary media center.&amp;nbsp; And because the cable companies won&amp;#39;t allow a home-built user to buy and install his own digital cable tuners, I cannot just use them independently.&amp;nbsp; Even if i play some tricks and share the saved files for recorded TV, the drm prevents me from watching Whose Line at any TV i want.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;Damn...&amp;nbsp; So, i&amp;#39;m going to try a few non-MS methods.&amp;nbsp; There are a few independant Media Center clones out there, even a few open-source ones in C#.&amp;nbsp; I&amp;#39;ll keep you all posted.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=17" width="1" height="1"&gt;</content><author><name>BrianR</name><uri>http://devplanet.com/members/BrianR/default.aspx</uri></author><category term="Casey" scheme="http://devplanet.com/blogs/brianr/archive/tags/Casey/default.aspx" /><category term="Media Center" scheme="http://devplanet.com/blogs/brianr/archive/tags/Media+Center/default.aspx" /></entry><entry><title>MS DTC Configuration for SQL 2005 in a Distance-Cluster on Windows Server 2003 Datacenter IA64</title><link rel="alternate" type="text/html" href="/blogs/brianr/archive/2008/01/14/ms-dtc-configuration-for-sql-2005-in-a-distance-cluster-on-windows-server-2003-datacenter.aspx" /><id>/blogs/brianr/archive/2008/01/14/ms-dtc-configuration-for-sql-2005-in-a-distance-cluster-on-windows-server-2003-datacenter.aspx</id><published>2008-01-14T18:01:00Z</published><updated>2008-01-14T18:01:00Z</updated><content type="html">&lt;p&gt;&lt;a href="http://devplanet.com/blogs/brianr/MSDTC1.jpg"&gt;&lt;/a&gt;As does everyone from time-to-time, we had a lovely &amp;quot;learn as you go&amp;quot; moment in the middle of a deployment recently.&amp;nbsp; As it turns out there are some very specific rules for setting up MS DTC in a clustered environment.&amp;nbsp; As always, individual results may very.&lt;/p&gt;
&lt;p&gt;First of all, most DTC changes don&amp;#39;t require an operating system restart.&amp;nbsp; Unfortunately, it would appear, in a clustered environment this is not true.&amp;nbsp; We did, however, find that if you bring down services in the correct order, you can successfully make changes to DTC without a system restart.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;Offline SQL Instances&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Offline DTC&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Offline Backup Agents(we use SQL Safe from Idera)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Make DTC changes&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Online Backup Agents&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Online DTC&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Online SQL Instances&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now that we have that out of the way, we can get to the settings.&amp;nbsp; For this example, lets assume we have 3 servers, 2 of them are distance-clustered, the 3rd is not a member of the cluster but will be executing distributed transactions to the cluster itself.&lt;/p&gt;
&lt;p&gt;First of all, if you don&amp;#39;t know where the DTC settings are they exist in the &amp;quot;Component Services&amp;quot; snap-in for MMC(run:mmc; add snap-in:&amp;quot;Component Services&amp;quot;).&amp;nbsp; For me, I RDP into the console on the server itself, so the default &amp;quot;My Computer&amp;quot; node that appears works, otherwise connect to the appropriate server.&amp;nbsp; Then, right-click &amp;#39;Properties&amp;quot; on the server name and you have a window which gives you a tab labeled &amp;quot;MSDTC&amp;quot;.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;This tab looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devplanet.com/blogs/brianr/MSDTC1.jpg"&gt;&lt;img border="0" src="http://devplanet.com/blogs/brianr/MSDTC1.jpg" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So this screen tells us some things.&amp;nbsp; First make sure that DTC is started on all the servers involved(unless you brought them offline purposely as described above).&amp;nbsp; If not, nothing is going to work.&amp;nbsp; You will probably want to make sure that service starts automatically.&amp;nbsp; Your cluster group should probably handle this.&lt;/p&gt;
&lt;p&gt;Now the fun stuff.&amp;nbsp;Like&amp;nbsp;I said, individual results may vary but these settings worked for us.&lt;/p&gt;
&lt;p&gt;Open the Security Configuration dialog:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://devplanet.com/blogs/brianr/dtc.jpg"&gt;&lt;img border="0" src="http://devplanet.com/blogs/brianr/dtc.jpg" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This dialog shows the configuration as works for our Server 1 &amp;amp; 2(the clustered servers), &amp;quot;Mutual Authentication Required&amp;quot; will &lt;strong&gt;NOT&lt;/strong&gt; work in a clustered environment. Not sure if &amp;quot;Incoming Caller Authentication Required&amp;quot; works, we couldn&amp;#39;t make it work properly.&lt;/p&gt;
&lt;p&gt;On the non-clustered server, you must also &lt;strong&gt;NOT &lt;/strong&gt;use &amp;quot;Mutual Authentication Required&amp;quot;, however &amp;quot;Incoming Caller Authentication Required&amp;quot; authentication seems to be sufficient for the non-clustered servers.&lt;/p&gt;
&lt;p&gt;What this means then is that all servers that will be opening or receiving distributed transactions to or from a clustered environment, must have their DTC settings changed.&amp;nbsp; We found this out the hard way, as DTC transactions were working in one direction, and not the other.&amp;nbsp; So it is possible that if your transactions are only being initiated in one direction you may not need to mess with certain servers.&amp;nbsp; Test it, you&amp;#39;ll be glad you took the time.&lt;/p&gt;
&lt;p&gt;If you are reading this post, you&amp;#39;ve probably already seen the DTCPing.exe app that is on the Microsoft site.&amp;nbsp; It is important to note that DTCPing happily returned no errors even when our authentication settings&amp;nbsp;were jacked.&amp;nbsp; So, while this utility may help diagnose certain DTC issues, i&amp;#39;m not sure that it helps in this scenario.&lt;/p&gt;
&lt;p&gt;Some of this information is outlined very obscurely in this KB article &lt;a href="http://support.microsoft.com/kb/899191/"&gt;http://support.microsoft.com/kb/899191/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I am not sure as to the security implications of these settings in an exposed environment.&amp;nbsp; As our servers are safely sitting in an internal network, I&amp;#39;m not too concerned.&amp;nbsp; You will have to research and evaluate that decision on your own.&lt;/li&gt;
&lt;li&gt;I did not have to change any settings on the second machine in the cluster, as cluster manager did it for me when I initiated a test fail-over.&amp;nbsp; Once again, run your own test.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=12" width="1" height="1"&gt;</content><author><name>BrianR</name><uri>http://devplanet.com/members/BrianR/default.aspx</uri></author><category term="Distance Clustering" scheme="http://devplanet.com/blogs/brianr/archive/tags/Distance+Clustering/default.aspx" /><category term="64 bit" scheme="http://devplanet.com/blogs/brianr/archive/tags/64+bit/default.aspx" /><category term="Clustering" scheme="http://devplanet.com/blogs/brianr/archive/tags/Clustering/default.aspx" /><category term="Itanium" scheme="http://devplanet.com/blogs/brianr/archive/tags/Itanium/default.aspx" /><category term="Sql 2005" scheme="http://devplanet.com/blogs/brianr/archive/tags/Sql+2005/default.aspx" /><category term="DTC" scheme="http://devplanet.com/blogs/brianr/archive/tags/DTC/default.aspx" /><category term="MS DTC" scheme="http://devplanet.com/blogs/brianr/archive/tags/MS+DTC/default.aspx" /><category term="IA64" scheme="http://devplanet.com/blogs/brianr/archive/tags/IA64/default.aspx" /><category term="Distributed Transaction Coordinator" scheme="http://devplanet.com/blogs/brianr/archive/tags/Distributed+Transaction+Coordinator/default.aspx" /></entry><entry><title>Sql 2005 Datacenter Cluster Issues</title><link rel="alternate" type="text/html" href="/blogs/brianr/archive/2008/01/11/sql-2005-datacenter-cluster-issues.aspx" /><id>/blogs/brianr/archive/2008/01/11/sql-2005-datacenter-cluster-issues.aspx</id><published>2008-01-11T23:34:00Z</published><updated>2008-01-11T23:34:00Z</updated><content type="html">&lt;p&gt;I&amp;#39;m sitting at my office desk waiting for our distance cluster to finish failing back over to our local server.&amp;nbsp; For the second time today, the our SQL cluster decided to fail over to our remote location.&amp;nbsp; My suspicion is that due to the ungodly number of SQL instances we have on these servers, we consumed the available 64gb of ram and caused the splitter driver to fail.&lt;/p&gt;
&lt;p&gt;For a little background, we utilize monster 64bit Unisys ES7000 Itanium 2&amp;nbsp;servers at work.&amp;nbsp; These bad boys are wonderful. The only complaint&amp;nbsp;I have ever had is that the distance clustering solution by EMC has done some questionable things, but when it works, it is one of the slickest clustering implementations I&amp;#39;ve ever seen.&lt;/p&gt;
&lt;p&gt;We just moved the remainder of our databases&amp;nbsp;to this cluster on Wednesday, which due to our failure in throttling the memory usage, must have pushed it over the limit.&lt;/p&gt;
&lt;p&gt;We work with a million technologies that the majority of people never come across in their work, each of which presents it&amp;#39;s own set of challenges.&amp;nbsp; We have a fairly large server farm, 2 of them really.&amp;nbsp; We utilize Windows Auth for pretty much all authentication.&amp;nbsp; This creates all sorts of wonderful issues as well.&amp;nbsp; We do constrained delegation via SQL CLR stored procedures from server-to-server.&amp;nbsp; This is a fun trick.&amp;nbsp; We actually use a SQL Server as a routing engine for database calls, most people would call this questionable architecture, but once you look at the scale of what we accomplish with it, you&amp;#39;ll see it is quite a brilliant solution.&amp;nbsp; So setting up SPN&amp;#39;s and MS DTC in a cluster is in interesting challenge.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;When&amp;nbsp;I get some time, I&amp;#39;ll post some specifics about our infrastructure and some of the hurdles we&amp;#39;ve had to jump to make it all work.&amp;nbsp; Topics i plan to touch on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;MS DTC in a cluster&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;SPN&amp;#39;s and delegation&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;SQL CLR (cross-server calls &amp;amp; impersonation)&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;SQL Performance&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Multi-Tenant DB&amp;#39;s&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;etc. &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Till then...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=7" width="1" height="1"&gt;</content><author><name>BrianR</name><uri>http://devplanet.com/members/BrianR/default.aspx</uri></author><category term="Distance Clustering" scheme="http://devplanet.com/blogs/brianr/archive/tags/Distance+Clustering/default.aspx" /><category term="64 bit" scheme="http://devplanet.com/blogs/brianr/archive/tags/64+bit/default.aspx" /><category term="Clustering" scheme="http://devplanet.com/blogs/brianr/archive/tags/Clustering/default.aspx" /><category term="Itanium" scheme="http://devplanet.com/blogs/brianr/archive/tags/Itanium/default.aspx" /><category term="Sql 2005" scheme="http://devplanet.com/blogs/brianr/archive/tags/Sql+2005/default.aspx" /></entry></feed>