Thoughts from Dan Miser RSS 2.0
 Monday, July 31, 2006
I'm using the Enterprise Library Data Access Application Block in order to use a variety of different databases on the backend without changing my code. One thing that recently came up was how to properly use a TIMESTAMP field in MSSQL. I don't want to use SqlDbType.Timestamp, as that refers to a specific DBMS implementation, and there is no DbType.Timestamp at the base class level for me. The following code snippet does work, though, so use this to get unstuck:


    db.AddOutParameter(cmd, "@newLastChanged", DbType.Binary, 8);
Monday, July 31, 2006 3:37:00 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
ADO.NET
 Wednesday, July 05, 2006
Time to confess: I'm a fan of data binding. I've loved it ever since Delphi 3 made it workable by introducing TClientDataset. It's powerful, but makes application code fairly simple. Yes, it can be - and often, is - abused when used incorrectly, but overall, it's a good concept.

I recently worked on getting data binding in a .NET 2.0 application to work with a lookup combobox. The concept is pretty straight-forward (and very analogous to Delphi's TDBLookupCombobox). Databinding in .NET is pretty impressive, and a step forward from where Delphi currently is. For example, you can bind straight to business objects as opposed to being required to consume database resources/components to complete data binding. One big snag was in getting the lookup relationship to respect null values properly. For example, assume you have 2 very simple classes, Order and Supplier, that are bound via BindingSource components. Furthermore, assume you have your data binding set up properly to have a ComboBox set with DataSource=orderBindingSource, DisplayMember=Name, ValueMember=SupplierID, and nameComboBox.DataBindings.Add(new Binding("SelectedValue", this.orderBindingSource, "SupplierID", true)); (see this reference or this reference for more details). Lastly, if you populate your objects as in the example below, you will notice that the original display of the combobox is populated with the first item in the supplier list. If you scroll to the next record and then back to the first record, the combobox will display properly.


    private void btnPopulate_Click(object sender, EventArgs e)
    {
      orderBindingSource.Add(new Order(1, "Test1", null));
      orderBindingSource.Add(new Order(2, "Test2", 1));
      supplierBindingSource.Add(new Supplier(1, "Supplier X"));
      supplierBindingSource.Add(new Supplier(2, "Supplier Y"));
    }

There are a couple of ways to fix this behavior. First, you could just reverse the order and populate the supplierBindingSource first. Alternatively, you can leave the population order alone and just call ResetBindings() after you're done populating all of the data.


    private void btnPopulate_Click(object sender, EventArgs e)
    {
      orderBindingSource.Add(new Order(1, "Test1", null));
      orderBindingSource.Add(new Order(2, "Test2", 1));
      supplierBindingSource.Add(new Supplier(1, "Supplier X"));
      supplierBindingSource.Add(new Supplier(2, "Supplier Y"));
      orderBindingSource.ResetBindings(false);
    }

One other quick note. When you want to set the Order.SupplierID field to null, you cannot write code like this:


SupplierNameCombo.SelectedValue = null;

Instead, you can either set the SelectedIndex to -1, or (IMO) more elegantly, write code like this:


SupplierNameCombo.SelectedValue = DBNull.Value;
Wednesday, July 05, 2006 12:47:00 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
Delphi
 Wednesday, June 28, 2006
I've been writing a lot of test cases and projects in VS.NET lately. (Ed note: No, this doesn't mean I've abandoned Delphi. I still love Delphi, and use it as my full-time tool. However, I always have - and always will - keep abreast on the entire world of development tools.) One thing that I thought would be cool to have would be a simple expert - or "addin", in VS.NET parlance - to ZIP up all of the source files automatically. I thought this would be a good opportunity to learn about the addin framework for VS.NET, but like a good developer, I thought I'd check to see if anyone else has written this already. In short order, I found an article detailing a tool named ZIPStudio. That article also provides source and a setup msi file to install the addin, but it only works for older versions of VS.NET. A few clicks later, I found the author's web site with an update of ZIPStudio that will work in VS.NET 2005.

After installing the tool, and testing it on a few solutions, it appears to be exactly what I was after. Highly recommended for those of you who want to move project source around between machines.

Wednesday, June 28, 2006 8:47:00 AM (Central Standard Time, UTC-06:00)  #    Comments [3] -
Delphi
 Tuesday, June 27, 2006
I just spent some time checking out how SqlDependency works. SqlDependency is an ADO.NET 2.0 class that is a high level wrapper for detecting changes in a database and getting automatic notification back to your application. This technology is very useful for caching rarely changing data. Essentially, you register interest in a query, and if something changes that would make that query different, you get a callback to your application to let you know that you need to update your local cache.

All in all, it's a pretty mixed review right now. It's pretty stringent on the requirements, not terribly efficient, and probably not the most practical thing for a multi-tier system. However, what it does, it does well. Here is my quick list of things learned:

  • You need to make sure that the DB is compatible with MSSQL2005. You can set the compatibility level in SQL Server Management Studio by selecting the Properties page of the database.
  • You need to SET ENABLE_BROKER on the database, along with making sure other OPTIONS are in compliance, to allow Query Notifications to work.
  • Be sure to prefix the table in the select with the schema information (e.g. select CategroyId, CategoryName from dbo.Categories). Also be sure to check out the documentation for other limitations on queries.
  • The OnChange event fires once and then gets consumed, so you need to hook up the event again after it fires.
  • OnChange runs in a separate thread, so be sure to update the UI properly.
  • The Queues and Services in MSSQL 2005 are not being automatically deleted when you call SqlDependency.Stop. This is a known issue, and the query to delete the extra objects can be found in this discussion.
  • It appears that the notification fires if ANY field in the table tied to the query is changed - even if that field is not part of the query you registered for notification. This seems like a bug to me.
  • Query Notifications are not very granular in reporting WHAT changed. Right now, this essentially forces you to invalidate an entire cache as opposed to just updating individual elements that have changed.
  • SqlDependency is the high-level wrapper. You can also use the low-level SqlNotificationRequest class to get more control over the process, if you so choose.
  • For ASP.NET, you will most likely use the SqlCacheDependency class.
  • Oracle also has support for this technology. Check out the article, Following the changes. Part I and Part II.

Other resources:

Tuesday, June 27, 2006 9:08:00 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -

 Friday, June 23, 2006
The following code snippet shows how to pick up the SQL that will be generated by a given LINQ query. The DataContext.GetQueryText() method makes this very easy. However, what we REALLY need is an easy way to go the other way, too. For example, given an adhoc string, generate the DLINQ query to allow further processing. I've looked through the Interactive Query sample, but that's not exactly what I want. The 2 main things wrong with it are that the baseQuery is already defined as an IQueryable variable, as opposed to a simple string; and the code to build up the expression tree is much too complex for every day needs. If we had a generic string to IQueryable method, we wouldn't need all of the expression code.


        static void Main(string[] args)
        {
            string s;
            var q  = from e in db.Employees select e.FirstName;
            
            s = db.GetQueryText(q);

            Console.WriteLine(s);
            Console.ReadLine();
        }
Friday, June 23, 2006 11:08:00 AM (Central Standard Time, UTC-06:00)  #    Comments [5] -
LINQ
 Thursday, June 22, 2006
I noticed Captain Jake wrote about his experience with AOL cancellation recently. It appears that he is not alone. Listen to the mp3 and be prepared to just be amazed.

It looks like Vincent has become a minor celebrity over this incident. I think the funniest part of this is the AOL executive that decided to use the press release for AOL's apology.

Thursday, June 22, 2006 10:35:00 AM (Central Standard Time, UTC-06:00)  #    Comments [6] -

 Tuesday, June 20, 2006
OK, so it doesn't have the same ring as Eminem's song, but it is accurate. :-) I was going through some of the older sections of my hard drive looking to reorganize and cleanup unwanted files. While I was doing that, I came across a project, TerraService, that I did ages ago. To the best of my recollection, it may have been ported from a VB application that I found somewhere on MSDN, but a search on that site isn't turning up any positive hits. Sorry for any lack of proper attribution. If this was written by someone else in another language, let me know, and I'll give the proper credit.

The reason I'm making the Delphi source available is that it shows how Delphi has improved over the years. I originally wrote this application using Delphi 6. As a result, I had to manually deal with the TByteDynArray types to decode them from base64 before display. Using Delphi 2006, this is no longer necessary - the types come back decoded and in usable fashion without any extra work on your part. This sample shows several interesting concepts: stream to variant conversion, drawing tiled images, calling a webservice, dealing with GIF and JPG files, and interception of webservice traffic for debugging.

While I don't know which specific version of Delphi fixes the TByteDynArray/Base64 de/encoding, this much I know for certain: Delphi 2006 makes web services very easy to do.

Tuesday, June 20, 2006 2:06:00 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
Delphi
 Thursday, June 01, 2006
In the last in the series of posts on writing a .NET application to communicate over HTTP, I thought I'd talk about HtmlAgilityPack (download available here). This tool allows you to write XPATH-like expressions to parse HTML files easily.

In my application, I upload a file and some form variables to a web server, which then responds with an HTML page. On that HTML page, buried in the middle, is a confirmation ID. In order to easily grab that ID and store it for later use, I use code like the following:


        private string CheckResponse(string response)
        {
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(response);
            HtmlNodeCollection coll = doc.DocumentNode.SelectNodes("//td[@id]");
            if (coll == null) 
                return null;

            foreach (HtmlNode node in coll)
            {
                if (node.Attributes["id"].Value.Equals("confirmation"))
                {
                    return node.InnerText;
                }
            }

            return null;
        }
Thursday, June 01, 2006 8:18:00 AM (Central Standard Time, UTC-06:00)  #    Comments [2] -

Navigation
Archive
<August 2006>
SunMonTueWedThuFriSat
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008
Dan Miser
Sign In
Statistics
Total Posts: 310
This Year: 25
This Month: 1
This Week: 0
Comments: 605
All Content © 2008, Dan Miser
DasBlog theme 'Business' created by Christoph De Baene (delarou)