LINQ: Quickly Create Dictionaries with ToDictionary

Donn Felker recently blogged about a neat little extension method in LINQ called Any().  If you simply want to know if a sequence contains any elements, many people use ".Count() > 0" which will walk the entire sequence to compute the count whereas .Any() will stop walking as soon as it finds a single element.  Easy and much more efficient.

It reminded me about another LINQ method I've used from time to time: ToDictionary().  This method will allow you to quickly create a dictionary from any IEnumerable<T>.  Let's start with some sample data that is in a List<T>:

IList<Person> people = new List<Person>
                       {
                        new Person {FirstName = "Bob", LastName = "Smith", SSN = "1"},
                        new Person {FirstName = "Jane", LastName = "Doe", SSN = "2"},
                        new Person {FirstName = "Mike", LastName = "Johnson", SSN = "3"}
                       };

Converting this to a dictionary is pretty trivial without LINQ.  Suppose we want to index these by SSN:

var d = new Dictionary<string, Person>();
foreach(var p in people)
{
    d.Add(p.SSN, p);
}

But why waste our time doing all that when we can simply use LINQ's ToDictionary()?  Just give it a lambda that selects the key and you're all set:

var indexedBySSN = people.ToDictionary(k => k.SSN);

Or perhaps you don't want the entire Person object.  Maybe you just want a collection of last names indexed by Social Security Number (SSN).  No problem --there's an overload that accepts two lambdas: one to select the key and one to select the value.

var lastNamesIndexedBySSN = people.ToDictionary(k => k.SSN, e => e.LastName);

There's also two more overloads that work the same as the two above, but allow you to also provide an IEqualityComparer<T> used to compare your keys.

Everyday I find more and more stuff in LINQ that helps me eliminate the mundane code and make my source more readable.

Technorati Tags: ,
Posted by PSteele | 1 comment(s)
Filed under: ,

SRT Presents Software Stimulus Lab to Support Economic, Business Growth

I've been so busy recently I totally forgot to blog about this.  We (SRT) are going to be hosting a Software Stimulus Lab at Automation Alley next Monday, June 15th.  We've got a press release that covers the details better than I can but the important things are:

  1. Seats are limited!  Register now – it's only $75.
  2. This is a hands-on workshop.  Bring your problems and we'll help you solve them in addition to teaching you how to solve them in the future.
  3. This is not about .NET.  Sure, we've got a great collection of C#, WPF and Silverlight folks, but we've also got some really talented Java, Scala and Python gurus.  And the tools aren't everything – learn techniques and methodologies to help drive your solutions to completion.

So check out the press release for all of the details and register here.

Technorati Tags: ,
Posted by PSteele | with no comments
Filed under:

ActiveRecord: Loading Records by Primary Key

I was reviewing some code today for a project that uses ActiveRecord.  One of the things that stood out for me was the use of a query to find objects by their primary key.  There's two reasons this raised a red flag for me:

  1. ActiveRecord already contains a built-in method for locating objects by their primary key: Find().
  2. Ayende just made a post about a month ago about why you shouldn't use queries to find objects by their primary key in NHibernate (which ActiveRecord uses under the hood).  You loose some optimizations that are built-in to NHibernate.  Read Ayende's post for more details.

So if you're an ActiveRecord user, how can you control which Session method to use – Get() or Load()?  Easy:

  • ActiveRecordBase.Find() uses Session.Load to load objects by primary key.
  • ActiveRecordBase.TryFind() uses Session.Get to load objects by primary key.

And if you're ever wondering how ActiveRecord works under the hood (or how some NHibernate concepts are used), grab the source and look around!

Technorati Tags: ,,
Posted by PSteele | with no comments
Filed under: ,

NHibernate Queries: HQL vs. Criteria API

As someone who did a lot of SQL a few years ago, I was immediately more comfortable using HQL for my ActiveRecord queries than the Criteria API.  But from a documentation/samples standpoint, I see a much higher percentage of the Criteria API being used vs. HQL.  I still use HQL most of the time.

This morning, Ayende had a post that answered the question I've always wondered: Which should I use?

Technorati Tags: ,,,
Posted by PSteele | with no comments
Filed under: ,

Ajax Survey

From BradA: Simone Chiaretta is doing another Ajax survey to see how things have changed since his last survey a couple of years ago.  I just filled it out (you should too!).  The survey can be found here.

Oh, and if the suspense is killing you, I'll give you my answers:

  1. I'm using AJAX in a production application.
  2. It's part of a MonoRail application.
  3. I'm using the Prototype on the client.
Technorati Tags: ,,
Posted by PSteele | with no comments
Filed under: ,

Fabulous Adventures In Coding

If you don't read Eric Lippert's Fabulous Adventures In Coding, you're really missing out on some great stuff.

I've been reading his blog for years and it's always an entertaining read.  I caught a presentation Eric gave at the MVP Summit in 2008 and also had an opportunity to speak with him one-on-one that year as he attended the C# dinner at Maggianos.  He's a guy that has so much knowledge, you wonder why his head doesn't explode!  :)

I decided to write about Eric's blog today because I only take time to read his posts if I'm sure I have time to let them soak in.  Some blogs I subscribe to just get a quick glance-over looking for good material.  But Eric's is always good so I've got a number of his posts from the past few weeks that I just caught up on this morning.  A few gems:

"foreach" vs. "ForEach": I always wondered why .NET didn't provide a ForEach extension method.  Now I know.

In Foof We Trust: A Dialogue: A great Q&A style post where Eric answers a question on why implementing an obviously cool and useful feature can quickly become very complicated.

Enjoy!

Technorati Tags: ,,
Posted by PSteele | 2 comment(s)
Filed under: ,

XmlSerializer ignores Culture

I'm working with an automotive client that has a couple of data formats for some of their files.  One is a simple CSV format and the other is XML using .NET's XML Serializer (nothing fancy).  The CSV format is handy as it's easy for the engineers to quickly load it into Excel and view in a columnar format.  The XML format was implemented as a much more "full featured" version of the data and contains additional metadata to describe the data.  All of the maintenance of these files is very easy as we have a library for dealing with them.

One of the issues that was found early on in the development of the library was that, being a global automotive company, the CSV wasn't always "comma separated".  Most european countries use the period (".") as a thousands separator and comma (",") as a decimal separator (i.e. three thousand dollars in this format would be "3.000,00").  A lot of work was put into trying to infer the culture of the machine that created the file so it could be read by any other culture.  There were bugs from time to time and we found a few anomalies that made things more difficult.  But it worked okay for the most part.

Recently, a decision was made (by people much higher than me) that going forward, the file formats (both CSV and XML) will always be in the English/US format (en-US).  This made exchange of these files easier all around as our library wasn't the only application that read these files and some other apps were having problems with the multi-culture issue.  Standardizing on the en-US format made things a lot simpler in the CSV read/write code as well as other applications.

In the XML code, I wanted to write some unit tests to make sure it also would always read/write in en-US format.  To my surprise, no matter what I set my Thread's CurrentCulture to, the XML always came out in en-US format.  I did some digging and found a thread about this on the ASP.NET forums.  One particular post cleared things up for me.  Martin Honnen (XML MVP) stated:

Well XML serialization uses a standardized number and date/dateTime format, the standard is the W3C schema datatype specification http://www.w3.org/TR/xmlschema-2/.

So don't expect XmlSerializer to pay attention to the thread's CultureInfo, it intentionally uses a standardized format to ensure you can serialize/deserialize independent of the culture/locale.

Sweet!  Culture isn't an issue with the XML Serializer!  Thanks Martin.

Technorati Tags: ,,
Posted by PSteele | 1 comment(s)
Filed under:

OutputDebugStringAppender in a web app?

I spent a couple of hours yesterday trying to get log4net to log to an OutputDebugStringAppender with no success.  At first, I thought I had a configuration error in log4net so I added a file appender and that works fine.  It's a Monorail application that uses ActiveRecord for database access.  There's a couple of spots where I wanted to check out the SQL being generated by ActiveRecord (NHibernate).  I did all my set up for log4net and even got it logging to a FileAppender.  But I wanted to log the SQL to an OutputDebugStringAppender.

Here's my logging set up:

   1: <log4net>
   2:     <!-- Define some output appenders -->
   3:     <appender name="logfile" type="log4net.Appender.FileAppender, log4net">
   4:         <file value="log-file.txt" />
   5:         <appendToFile value="true" />
   6:         <layout type="log4net.Layout.PatternLayout">
   7:             <conversionPattern value="%d [%t] %-5p %c - %m%n"/>
   8:         </layout>
   9:     </appender>
  10:     <appender name="ods" type="log4net.Appender.OutputDebugStringAppender, log4net">
  11:         <layout type="log4net.Layout.PatternLayout,log4net">
  12:             <conversionPattern value="%d [%t] %-5p %c - %m%n"/>
  13:         </layout>
  14:     </appender>
  15:     <logger name="NHibernate.SQL">
  16:         <level value="ALL" />
  17:         <appender-ref ref="logfile" />
  18:         <appender-ref ref="ods" />
  19:     </logger>
  20:     <root>
  21:         <!-- priority value can be set to ALL|INFO|WARN|ERROR -->
  22:         <priority value="ALL" />
  23:         <appender-ref ref="ods" />
  24:     </root>
  25: </log4net>

The log-file.txt gets all the logging I want, but I really just wanted to be able to view these statements in DebugView (gives me a bit more control in clearing out past queries, setting filters/highlight colors, etc…)

I'm positive I had something like this working before but I get NOTHING in DebugView.  Anyone have any ideas as to what I'm doing wrong?  Is there a permission issue that makes this not possible?

Posted by PSteele | 2 comment(s)

New CodeMash Website

As you've probably heard (via Twitter), there's a new look to the CodeMash website.  SRT Solutions and inner circle media have been working on the website for a while now getting things organized.  Much of the praise for the new look goes to inner circle media – Catherine Hayes and Alaine Karoleff have put a lot of thought and design into the new site and it shows!

As Brian pointed out in his tweet, this is just the beginning – there's more to come as CodeMash get closer and closer.  And check out the news – CodeMash 2011 already has a date!  Start your planning now!  I'm thinking that an 18-month notice is more than enough time for your employer to give you the time off.

Technorati Tags: ,
Posted by PSteele | with no comments
Filed under: ,

Be careful where you place your images on your website

Just found something interesting while researching a problem Dianne was having with a website SRT was working on.  In checking various browsers throughout the office (FireFox, IE, Opera), a page looked ok on most of the browsers, but not all.  In fact, there were just a couple of machines running Firefox that had problems (others, running the same version of Firefox had no problem viewing the page correctly).

Then Dianne asked me if I was running Adblock Plus (which, of course, I was).  This was the key.  Once we realized some of our images were being blocked by Adblock Plus, I checked the image as well as Adblock's filter rules.  It turns out the images were placed in a folder on the website called "ads".  Adblock Plus, by default, has a rule to block images found in a folder called "ads" (with some exceptions):

clip_image002

I disabled the rule to verify my hunch.  Once disabled, the page displayed correctly.  So, be careful where you place your images on your website!

Posted by PSteele | with no comments
More Posts Next page »