It's Tuesday, which is double post day over here at 10K Monkeys. Exciting times for those of you reading along at home. Tonight's topic is something I've been eagar to play with, LINQ and C# 3.0. Although its been hard to find time between the frequent cat naps and reruns of Jag. So what is LINQ? MS defines it as Unified Language Features for Object and Relational Queries. But thats not all, you can also query objects using unified language features.
To get started, download and install the LINQ preview. Be warned, it's not for the faint of heart. VS 2005 doesn't fully recognize all of the syntax in intellisense and the compiler will display errors like its Y2K. Step aside compiler, I'm an IT Professional.
So open up VS 2K5 and make a new LINQ console app using one of your newly installed templates. Then paste this little gem into the Program.cs class.
using System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.Xml.XLinq;
using System.Data.DLinq;
namespace LINQConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
GetEmployees();
}
static void GetEmployees()
{
var employees = new List<Employee>() {
new Employee { Name = "Kevin", HireDate = new DateTime(2000, 11, 18)},
new Employee { Name = "Jeff", HireDate = new DateTime(1999, 5, 7)},
new Employee { Name = "Bryan", HireDate = new DateTime(1995, 1, 12)},
new Employee { Name = "Ryan", HireDate = new DateTime(2003, 5, 1)},
new Employee { Name = "Steve", HireDate = new DateTime(2002, 12, 1)}
};
var rookies =
from r in employees
where r.HireDate > new DateTime(2001, 1, 1)
orderby r.HireDate
select r;
var veterans =
from v in employees
where v.HireDate < new DateTime(2001, 1, 1)
orderby v.HireDate
select v;
Console.WriteLine("Rookies:");
foreach(var val1 in rookies)
{
Console.WriteLine(" Name = {0}, Hire Date = {1}", val1.Name, val1.HireDate.ToShortDateString());
}
Console.WriteLine("Veterans:");
foreach(var val2 in veterans)
{
Console.WriteLine(" Name = {0}, Hire Date = {1}", val2.Name, val2.HireDate.ToShortDateString());
}
Console.ReadLine();
}
}
class Employee
{
public string Name;
public DateTime HireDate;
}
}
Don't worry about the errors, it'll run. Tell the compiler "You will respect my authoritah!" (Or not depending on the location of your cubicle)
Here is the output if you don't believe me
How great is that? So let's check out some of the new syntax. First off is the new var type. You might be thinking, at long last, the power of Javascript in C#. But no, it allows the compiler to infer the types. employees is initialized in the right hand side as a generic list of employee objects. Notice also, how the employee class doesn't need a constructor. The declartion of the list also includes several new features like populating the list directly within the curly braces without having to call add on the list and employees are created by explicitedly setting the fields (object initializers). Note, you can also set only a subset of the fields if you are too lazy to set them all. But wait, there is more, check out the sql like syntax to query a list. Behold, the same SQL syntax from 1965, is now in C#. The great feature of the var keyword is that it allows the sql-like keywords to infer what type the query will return.
This seems like it will be a very cool addition to the next version of C#. It makes getting specific items from a list very simple. No more for loops and if checks to find items. LINQ also has some cool syntax for creating table objects directly from a db that you can query or syntax for querying XML. I didn't have time yet to check out performance, but I imagine it's probably not good to use huge lists. Although being able to use object querying on a table's data is almost like having an object oriented database. When are those coming out anyway? Its amazing how slow database technology is to change. Oh, wait we can have XML in databases. Thats a recent addition from the 1990's. I wonder what it's like to use DLINQ to query a table that has XML so that I can XLINQ that. The possibilities are endless.
This could make a great addition to the Foos Server. Watch out Foos DBA, I can now write inefficient queries INSIDE my app.
Sometimes the 10K monkeys staff is too busy on mission critical projects like foosball stat trackers and comic book managers to keep up new C# syntax like nullable ints. How did I not notice earlier that you could declare an int as "int? in" Plus how great does "int?" look? I previously felt there wasn't enough use of the question mark in my code. So how is this useful and why did you waste 10 minutes blogging about this? Well to answer the first question, I personaly found them useful in data access classes where I have an update stored proccedure may update value that can be null. For example:
public void UpdateEmployee(int employeeID, int? age, string firstName, string lastName)
{
Database db = DatabaseFactory.CreateDatabase();
string sqlCommand = "UpdateEmployee;
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);
db.AddInParameter(dbCommand, "@EmployeeID", DbType.Int32, employeeID);
db.AddInParameter(dbCommand, "@Age", DbType.Int32, age);
db.AddInParameter(dbCommand, "@FirstName", DbType.String, firstName);
db.AddInParameter(dbCommand, "@LastName", DbType.String, lastName);
db.ExecuteNonQuery(dbCommand);
}
Now I can just pass null into my data class and let the db field stay null. I've also been working with the MS Enterprise Application block lately as you can see from the sample code. I'm sure I'll have much to complain about there in future blog entries. As for the second question, I have no idea.
The latest gadget to join the 10,000 Monkey gadget collection is the intel Mac Mini. Not that I or my credit card needed another computer, but after the recent demise of my iBook, a roster spot opened up. I have a queue full of projects in the works for the mac mini, time permiting.
Project #1: Digital Picture Frame
So another vetern of the 10K Monkey gadget collection, the successful 3Com Audrey was sitting unused.
A bagrain at only $400, on its release, I got it for $50 on ebay about a year later. There are lots of hacks you can apply to the Audrey, most of which are shown here. With its 6inch sceen and small form factor it makes a perfect picture frame. The web browser on the Audrey goes into fullscreen mode so nothing besides the page is displayed. My plan was to point the web bowser on the audrey to a web page that auto refreshes and loads a random picture every 15 seconds.
I enabled Personal Web Sharing under the Sharing section in the Mac Minis preferences. Next was enable PHP. Mac OS X has PHP installed but not enabled by default on its apache web server. To enable PHP:
1. Open the Terminal app located in the utilities folder.
2. Type "cd /etc/httpd"
3. Type "sudo pico httpd.conf" and enter your admin password
4. Locate this line: # LoadModule php4_module libexec/httpd/libphp4.so and delete the "#"
5. Locate this line: # AddModule mod_php4.c and delete the "#"
6. Restart apache by typing "sudo apachectl restart"
Now PHP is enabled so we can build a random picture script. There are tons available, so save yourself some coding time. I found this one to be pretty good. You can copy this file into a new folder called slideshow under /Library/WebServer/Documents (root dir of apache) and change the extension to php. Now make a new page called index.html and put the following code:
<html>
<head>
<META HTTP-EQUIV="Refresh" CONTENT="15">"
</head>
<body bgcolor="black">
<center>
<img border=0 height=603 width=461 src="rotate.php">
</center>
</body>
By setting the dimensions of the image to 603x461, you can put the audrey in fullscreen boweser mode and there won't be any scrollbars. The next step is to set execute permissions on the rotate.php file by typing "chmod 755 rotate.php" in Terminal from the /Library/WebServer/Documents/slideshow directory.
In iPhoto you can export all you photos to the the slideshow directory and resize them to 640x480. Then point the Audrey's web browser to the index.html on the Mac mini and voila, a digital picture frame that displays a new random picture every 15 seconds. Now I need to take some more pictures so it can stop rotating between the two I took when I first bought the camera.