Tuesday, February 26, 2008

ICacheItemExpiration implementation for a set of Rows

Here is a little code that will create a class that you can use with Enterprise Library caching.  Basically it allows you to define a WHERE clause where any object in that WHERE clause changes (across a single table) then the cache will expire the object in the cache.  Think of it as a way to store a List<> of object that represent rows in a table in the cache and be able to detect if any row changes so that you can drop the cached list.  LastUpdate is a timestamp column that needs to be on every row.  This works since timestamp column type is always incremented by one, which means that SELECT MAX(LastUpdate) will tell you the maximum change across all rows.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Configuration;

using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Properties;

namespace ERS.Base
{
    /// <summary>
    /// 
    /// </summary>
    public class TableSqlDependency : ICacheItemExpiration
    {
        String _tableName = String.Empty;
        String _connectionString = String.Empty;
        String _where = String.Empty;
        Byte[] _lastUpdate = null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="tableName"></param>
        public TableSqlDependency(String connectionString, String tableName)
        {
            _connectionString = connectionString;
            _tableName = tableName;
        }

        public TableSqlDependency(String connectionString,
            String tableName,
            String where)
        {
            _connectionString = connectionString;
            _tableName = tableName;
            _where = where;
        }

        // Summary:
        //     Specifies if item has expired or not.
        //
        // Returns:
        //     Returns true if the item has expired, otherwise false.
        public bool HasExpired()
        {
            Byte[] lastUpdate = LastUpdate;

            if ((lastUpdate == null) && (_lastUpdate != null))
                return (true);

            if ((lastUpdate != null) && (_lastUpdate == null))
                return (true);

            if ((lastUpdate == null) && (_lastUpdate == null))
                return (false);

            if (lastUpdate.Length != _lastUpdate.Length)
                return (true);

            for (int i = 0; i < lastUpdate.Length; i++)
                if (lastUpdate[i] != _lastUpdate[i])
                    return (true);

            return (false);
        }

        private Byte[] LastUpdate
        {
            get
            {
                Byte[] lastUpdate = null;

                using (SqlConnection sqlConnection =
                    new SqlConnection(
                        ConfigurationManager.ConnectionStrings[_connectionString]
                        .ConnectionString))
                {
                    String sql = String.Empty;

                    if (!String.IsNullOrEmpty(_where))
                        sql = String.Format(
                            "SELECT MAX([LastUpdate]) 'Max' FROM [{0}] WHERE {1}",
                            _tableName, _where);
                    else
                        sql = String.Format(
                            "SELECT MAX([LastUpdate]) 'Max' FROM [{0}]",
                            _tableName);

                    using (SqlCommand sqlCommand =
                        new SqlCommand(sql, sqlConnection))
                    {
                        sqlConnection.Open();

                        sqlCommand.CommandType = CommandType.Text;

                        using (SqlDataReader sqlDataReader =
                            sqlCommand.ExecuteReader())
                        {
                            if (!sqlDataReader.HasRows)
                                lastUpdate = null;

                            sqlDataReader.Read();

                            lastUpdate = (Byte[])sqlDataReader["Max"];
                        }
                    }
                }

                return (lastUpdate);
            }
        }

        //
        // Summary:
        //     Called to give the instance the opportunity to
        //        initialize itself from information
        //     contained in the CacheItem.
        //
        // Parameters:
        //   owningCacheItem:
        //     CacheItem that owns this expiration object
        public void Initialize(CacheItem owningCacheItem)
        {
            _lastUpdate = LastUpdate;
        }

        //
        // Summary:
        //     Called to tell the expiration that the CacheItem to which
        //        this expiration
        //     belongs has been touched by the user
        public void Notify()
        {
        }
    }
}

{6230289B-5BEE-409e-932A-2F01FA407A92}

Monday, February 18, 2008

Movin' along with .net 2.0 web project in c#

I'm getting farther along in my new pet project. I had many issues with converting to a web application project. Then I balked at which style of data access/data layer to use. Then I fidgetted with notation and styles. After wasting bunches of time, I'm finally moving along. Data is going in, data is going out. It looks aweful and the backend is a SQL client. But the user functionality is moving along. The rest can be fixed after I feel some momentum.

So I'm using asp.net 2.0 c# with sql backend. Enterprise Framework from MS patterns and practices. MS Membership provider with a SQL provider. Data layer is business objects with provider model. I have nunit plugged in but haven't written in unit tests yet. Argh!

Since I'm not a graphic designer, it looks BAD. A bad ripoff of www.xcache.com.

 

Programming to www.pandora.com.

 

Saturday, February 16, 2008

Friday, February 15, 2008

Skining Custom Controls

For the longest time I couldn't skin my custom control, background: a custom control looks like this:

public class MyGridView : GridView
{
...
}

This custom controls was in a separate class library.  Bill researched the problem and it appears that you can't skin a custom control that is in a nested namespace.  I.e. the custom control can't have this:

namespace MyNamespace.SubNameSpace
{
   public class MyGridView : GridView
   {   
   ...
   }
}

It has to be in a single namespace to work:

namespace MyNamespace
{
   public class MyGridView : GridView
   {  
   ...
   }
}

Visual Studio 2005 - .NET 2.0 - ASP.NET 2.0
{6230289B-5BEE-409e-932A-2F01FA407A92}

 

Thursday, February 14, 2008

Compare Byte Arrays

Slightly more efficient by starting off with a reference compare. If the same two arrays are passed in, no need to compare the elements. I don't think there is a better way unless you use unsafe code / pointers. The use of generics makes this more general purpose.

bool Compare<T>(T[] left, T[] right)

{

    // handles the same array

    // handles both null

    if (left == right)

        return true;

 

    // fails when either are null

    if (left == null || right == null)

        return false;

 

    if (left.Length != right.Length)

        return false;

 

    for (int i = 0; i < left.Length; i++)

    {

        if (!left[i].Equals(right[i]))

            return false;

    }

 

    return true;

}

 

Compare IEnumerable (a still better option)

My office mate Chad came up with yet an even better option. You need to be using 3.5 and include the System.Linq extension method namespace. It didn't perform quite as well but pretty close. Even more general purpose. Note that the default SequenceEqual method throws an exception when either operator is null so I handled those cases first.

bool Compare<T>(IEnumerable<T> left, IEnumerable<T> right)

{

    // handles the same array

    // handles both null

    if (left == right)

        return true;

 

    // fails when either are null

    if (left == null || right == null)

        return false;

 

    return left.SequenceEqual(right);

}

 

When a Codebase Sucks There's Always JavaScript

In working on some inherited code in a very large and complex website I was a little bit skeptical of touching the code.  Let's just say the codebase was dubious at best.  This presented a problem as I had 3 days to make a lot of changes in the admin section of the site.  When inheriting code there is always a learning curve.  Unfortunately I didn't have this luxury as I spent 1.5 days getting the code running locally (still haven't COMPLETELY finished this).  This left me with about another half-day to learn the handful of tables I was to be using.  One day to actually write the code.  No problem. 

So the client relayed to the PM what needed to be done which was ultimately relayed to me.  "When a manager selects a value from the whatever dropdownlist the values for the FileUpload control disappears and the user has to re-enter this value (which is by design as this would be a huuuuge security risk. Think if you could programmatically set the postedfile for the FileUpload control!).  Different sections are displayed depending on the value of such-and-such dropdownlist, etc..." I then ask myself, "WTF are there so many postbacks to simply hide / show sections?"  This sounded  like a perfect opportunity to utilize my new favorite property: Control.ClientID.  The goal was to move the functionality from server-side to client-side while making minimal changes to the server-side code ( VB* ;-) ). Half of the dropdownlists had AutoPostBack enabled.  I expected to see a handful of handlers when I viewed the code-behind. Nope. Why is it that developers feel the need to always post back to the server even if nothing is happening? Maybe they were planning to implement the handlers in the future?  A postback is kind of a big deal and I believe they should be used sparingly, but that is just me.  Anyway, my server-side code consisted of maybe 6 lines where I added Attributes to server-side controls similar to:

dropdownlist.Attributes.Add("onchange",

   string.Format("clientSide('{0}', '{1}', this.value)",

   someDiv.ClientID, anotherDiv.ClientID))

With ClientID I am shoving the ID of the rendered control into my dropdownlist's onchange event so I can guarantee the control Id on the client-side.  This is extremely important since this particular site uses a series of nested masterpages and you can never be too sure what the output control id will be.  I then wrote some utility JavaScript functions to set CSS display style to "none" or "" depending on the values selected.  I also use client-side JavaScript to enable / disable appropriate validators (which is pretty cool).

ValidatorEnable("validatorId", false); // disable
ValidatorEnable("validatorId", true); // enable

It may seem like a bit more work solving problems on the client-side, but in the end it definitely makes the user experience more fluid.

* I have found that VB can be quite pleasant when written correctly.  I am not the definitive authority on correct programming but I'm pretty sure immuting a string object while enumerating an ArrayList with a series of nested if statements and for loops is not the correct way to display SQL data in tabular form.  I also can't think of a good reason to have 400+ lines in Page_Load. These practices aren't language-specific and would probably piss me off in any .NET platform.

Here Is A Little Code That I Simplified

Here is a little code that I simplified:

public Boolean Compare(Byte[] a, Byte[] b)
{
   return(a=b);
}

Seems like it should work right? Compare each Byte in a with the same Byte position in b and return if the two arrays have equal values in each position? It doesn't do that -- it compares the two objects to see if they are equal. My solution:

public Boolean Compare(Byte[] a, Byte[] b)
{
    if ((a == null) && (b != null))
        return (false);

    if ((a != null) && (b == null))
        return (false);

    if ((a == null) && (b == null))
        return (true);

    if (a.Length != b.Length)
        return (false);

    for (int i = 0; i < a.Length; i++)
        if (a[i] != b[i])
            return (false);

    return (true);
}
Is there a better solution? {6230289B-5BEE-409e-932A-2F01FA407A92}

Thursday, February 7, 2008

Build Issues with Web Projects vs Web Applications in Visual Studio 2005 (Windows 2003)

My virtual dev server was running out of hard drive space. Wayne’s preferred solution was a new and different dev server. I called him a few days ago about a build problem but I don’t remember what that was. He dinked with my solution. One of things he turned on was signing. I didn’t notice and at the time everything kept building. But I needed to move to the new server. The major apps were installed. I just needed to move all my VS projects, and whatever else I had on the old server. This part is the drudgery. Move everything and then see if it builds.

 

Well it built but I didn’t notice that my business object dll wasn’t getting moved up to the web site. So the ObjectDataSource wasn’t finding my new class methods for the business object. Of course, I didn’t figure that out immediately. I thought the docs for the ODS were just missing something. Wayne looked at the project and couldn’t figure out how to solve the problem immediately because of the type of project I had for the web server. He was used to dealing with Web Application projects that look and feel more like Windows application projects. I didn’t know that I had an old-style web project instead with the app_code directory.

 

In order to fix the problem, I tried to move the files of the project into a Web Application project. No nothing built. It started saying I needed signed dll’s for two specific 3rd party libraries (assembly generation failed ... does not have a strong name). I knew I didn’t so I waited until Wayne came home from Tamales class. He had set the signed setting in order to fix the original problem of getting the object into the GAC, however gave up when he realized I was referencing third party object that also needed signing. The business object built but the web application didn’t. The new project type didn’t know anything about app_code so those files were moved into a new Classes directory off the root of the web application project. The next project was that the .aspx files couldn’t find those classes so we had to put the classes into a namespace. This meant all code files regardless of type were now in the same name space for both the business object library and the web application project. Next problem was that the controls on the aspx.cs pages were undefined or some error like that. We had to “convert” the web project files so that the “.designer” page was behind as well. Then we changed each “.designer” code page to also be in the same name space as everything else. Once that happened, the whole solution built.

Back To Anonymous Types

C# .NET 3.0 has anonymous types, since I am working on some legacy projects I have the experience of using anonymous types already in VBScript.  Remember classic ASP? Not having to Dim your variables, and being able to assign a variable to an int, then a string.  Has it been so long ago that you forgotten all the fun you have had with anonymous types in classic ASP?

I have a project that is classic ASP and SQL Server, if we change the SQL Server column (i.e. rename it or change the type) we have to scan the classic ASP (Find In Files) then make the changes to all inline SELECTS, UPDATES, and DELETES.

So then we got smart and changed to stored procedures, now if the type changes the stored procedures doesn't compile, easier to find places that need to be changed, however we had to adjust the classic ASP to handle the new type as an output -- really not a problem becuase all VBScript is anonymous types. 

So then we got really smart and used ASP.NET CLR 2.0, a class library to talk to our database, and SQL Server.  We generated the class library from CodeSmith using the database schema as a template for the library.  Now we are doing really good.  If the database type changes, the class library changes (we regenerate it), and any code behind that is calling the class library will break becuase of the type change.  Strongly typed language how nice.

Now we have LINQ -- back to anonymous types, we can jump on the bandwagen and rewrite all our code behind to call LINQ.  Now if we make a database change we are back to find In files.  Full circle to our VBScript days. Yippee.

{6230289B-5BEE-409e-932A-2F01FA407A92}

 

Comma Delimited String From An Array -- The Final Word

In response to the previous postingJames Arendt has comment the final word:

static internal String AredntWay(String[] list)
{
   return(String.Join(',',list));
}

Thanks James Arendt!

{6230289B-5BEE-409e-932A-2F01FA407A92}

Wednesday, February 6, 2008

Where do you put your code?

I have a friend who is constantly saying he can write code much faster by configuring the various data controls with the SQL insert, select, update, and delete statements. I tried this. It is true the page was much faster built. A few clicks, a few typed attributes. However, and this is a big however, that style of coding makes several assumptions. Under each assumptions, I'll also list why I think a middle layer needs to exist between the GUI and the database. For those of you who are laughing that I even need to make this argument, beware what project you take over. Look at the code first.

you configured the controls correctly the first time

   In order for the process to truely be fast, you can only touch it once. With a code library, you can easily grow the middle layer to suit all your needs without having to retouch that page using a data control.

you don't have any need to use that code again in that web app, ever

   Whatever you write is what the user, admin, etc see - one interface only. I know this is bogus but it's the only thing that backs up a "much faster" arguement. With a code library, you can have as many views into the data as you need. But, yes, you do have to write that code.

you don't test your code beyond it's first unit test

   In order to test this type of code, it's either by hand or a high-end gui/web tester. With a code library, there are several tools to unit test including nUnit or it's new version xUnit. Once you have the unit test, you can run your tests against every build. The unit tests will find error before your customers do - which is so much nicer.

no one else will ever touch your code

   Few decent programmers would work this way. It says you are lazy and work alone.

those controls will never change or be removed

   In order to get the full benefit of time savings, it has to live for the life of the project. However, with the middle layer, the logic can live beyond that app to any other app or variant. Of course, you could totally munge the library into a piece of #$% but both approaches assume the design skills are solid.

 

ObjectDataSource and GridView

I'm working on the infrastructure for a new web site. Lots of data layer so I can test. But I don't want to spend loads of time with the UI for insert/update/delete from an admin standpoint. Sure the UI for customers will get plenty of time but my own interface can be functional but not pretty. I already have robust classes for the data layer. Do I build my own pages with calls to the data layer in the code behind? I want to remove as much testable code from the UI (aspx and aspx.cs) as possible. So I'm going to try to use the GridView with a DataSourceObject. Make the GridView and ObjectDataSource do most of the work since they are far more tested than any UI code I could write.

That's my logic anyway.

 

Tuesday, February 5, 2008

Email Newsletter SQLServerCentral.com

The one newsletter that arrives in my inbox that is bound to perk me up anytime is from http://www.sqlservercentral.com/. It is sort of an older style newsletter but the contents are great. The editorials (yes, there are editorials) are also great. The main articles might not be right for me at the time but then there is the question and the community-submitted help code as a featured script.

Monday, February 4, 2008

Comma Delimited String From An Array

Creating a comma delimited string from an array came up yesterday, here is a couple of methods, one from our junior developer and one that I did.  I entitled mine old school, because of the C coding that shaped my programming.

static internal String Junior(String[] list)
{
    String output = String.Empty;

    foreach (String item in list)
    {
        output += item + ",";
    }

    output.TrimEnd(',');

    return (output);
}

static internal String OldSchool(String[] list)
{
    StringBuilder output = new StringBuilder();

    foreach (String item in list)
    {
        if (String.IsNullOrEmpty(item))
            continue;

        if (output.Length > 0)
            output.Append(",");

        output.Append(item);
    }

    return (output.ToString());
}

Which one do you like?

{6230289B-5BEE-409e-932A-2F01FA407A92}

 

 

Comma Delimited String From An Array using LINQ

In response to the previous posting. A few weeks ago, I would certainly have solved this the same way that you did in "OldSchool" with the exception of using IEnumerable<string>. Why limit your code to just string arrays? Now that we have LINQ, we can get pretty fancy! Technically one line within the method but I split it up to aid readability.

 

static void Main(string[] args)

{

    string[] names = new string[] { "Andy", "Marcy", "Cindy", "Jennifer", "Aaron" };

 

    Console.WriteLine(NewSchool(names));

}

 

static string NewSchool(IEnumerable<string> list)

{

    return list.Aggregate(new StringBuilder(),

        (sb, n) => sb.Length == 0 ? sb.Append(n) :

         sb.Append(",").Append(n),

        sb => sb.ToString());

}

 

And for even more fun, I built a simple test harness for each of these three methods. The test: 10000 itterations where I concatenate a string array that contains 8192 elements. Junior ran 36 minutes and 41.5 seconds*. OldSchool ran 8.453 seconds. NewSchool ran 9.484 seconds. NewSchool is likely slightly slower than OldSchool because of the use of the delegate. * I was only able to run 100 itterations on Junior which ran 22.015 seconds. I then extrapolated from there. The actual result would likely be even longer given its use of memory.

Saturday, February 2, 2008

Seattle Code Camp: xUnit.net

This presentation was given by Brad Wilson and James Newkirk, Microsoft. I sat in on Brad's Pair Programming Agile presentation at the first Seattle Code camp which I enjoyed alot. The first code camp had more Agile presentations. Apparently Agile is no longer the shinny new toy because there was only one presentation on saturday in that area. James has been with xUnit, since some part of it's JUnit days, through NUnit and now the new version of XUnit. He went through the history which explained some of the wierdness the process has had. He also went through a discussion of what they were concerned about when they decided to build a new TDD framework. It was nice to hear real world examples of bad logic or implementation. My favorite they mentioned was using the framework for code coverage. Code coverage is the process make making sure every line of code is executed. The idea being that the more executed code that goes through testing, the fewer bugs the release product will have. These two said that blank tests or non-functional nUnit tests were created in some environments they saw just to reach code coverage percentage requirements. The only place I have ever seen code coverage as a metric for quality was microsoft while working as a tester on OLEDB.  They wrote issues on the board people wanted to cover and they covered all of them. Very impressive.

During the code samples and execution, it was obvious these two preferred TestDriven.Net over any other runner of the framework.

I had to feel for the guy that asked about UI testing. He obviously didn't know anything about TDD. In response, the discussion for UI testing covered watiN.

Other linkable names mentioned during the discussion:

MBUnit

CruiseControl

Windows Presentation Foundation

Jeremy Miller

 

 

 

 

Friday, February 1, 2008

Reason #1 Not To Use Open Source

I have several reasons not to use open source and I will be posting all in short order.  By open source, I mean a free assembly I can get on the web that includes the source, usually a development tool that is build by a group of people.

For some time I have been debating weather to use open source projects for my C# programming, or to buy professional components.  By debating, I mean thinking about, trying, and experimenting with both -- however now it is time to put my ideas to paper and share.  Disclaimer: in a year I might change my mind, or a posted comment might change my mind.  However here is one tought to chew on:

We reference assemblies so that we can gain functionality without having to code the funtionality ourselves.  Microsoft provides some great functionality in the CLR and it allows us to make significant gains in productivitiy by not making up write the stuff in the CLR.  However, if Microsoft is missing the functionality and it isn't specific to your vertical or product -- there is a tendency to get the functionality from the web as a open source project.  I tend to get the source, recompile it and make it a project within my solution, instead of using the assembly already compiled -- this can be a whole other discussion.  Ok, to recap: I reference an assembly from the Internet because I don't want to write the code myself.

However, it is my experience that the open source projects are very buggy, which leaves me fixing them to get them to work.  Which means I am coding in someone elses code just to get the thing to work correctly.  If I purchased a professional product, I could just write customer support, provide a reproduction, and get a fix.  Which leads me to reason #1: There is no support, I would rather buy (and I mean have my company buy) a $1000 per license product and get support for bugs then fix and worry about the open source.  

Just to drive the point home, even popular projects like ICSharpCode.SharpZLib have bugs, I just fixed three of them.  And, no I am not going to submit the changes to the open source project -- it takes to much time, they will not like my changes (since I patched it and didn't fix it like I would my own code), and usually those developers are hard to reach (hiding from doing customer service) and snobby (not SharpZLib in paricular just open source developer in genderal).

{6230289B-5BEE-409e-932A-2F01FA407A92}