Monday, August 9, 2010

Silverlight Neophyte 1: Include the Include Attribute

Summary
Use the Include attribute on related types that should be returned to the client.

RIA Services supposedly simplify and accelerate n-tier ASP.NET and Silverlight development. I don't have an opinion on the matter yet because I haven't finished my Silverlight 4 application yet. I think that I'm making good progress on my project for a Silverlight neophyte. That being said, I've spent a few too many hours on problems stemming from my Silverlight / RIA Services ignorance or poor or non-existent documentation. I'm sharing these gotchas as I encounter them.

I inherited a poorly designed legacy database that Entity Framework 4 nicely abstracts. Two of the tables, TableA and TableB, really should be a single table because they merely partition a single, cohesive set of data into two different, um, parts. There are several legacy applications that operate against TableA and TableB or this design would have been changed years ago. I've created a couple of views that nicely unify the tables, and these views work well for read operations.

My Silverlight application needs to edit these tables, and that requirement is where today's topic originates. As you expect, my entity model contains types that represent TableA and TableB, and each of these types (EntityTypeA and EntityTypeB) have navigation properties related to the other type. With that in mind, I added a new method to my domain service that returned a single EntityTypeA. My thinking was that I could then use the navigation property value (EntityTypeA.EntityTypeB) to get the complete set of data.

So no big deal here. My ViewModel called the DomainContext.Load method and I got back an instance of EntityTypeA. But EntityTypeB was null. OK, I thought, I've probably not configured the loading operations properly, I'll set ObjectContext.ContextOptions.LazyLoadingEnabled = false and everything will be alright. Nope, still a null EntityTypeB. I must have done something else wrong. Fine, I'll change my query from

EntityTypeA entityA = this.ObjectContext.EntityTypeA.Include("EntityTypeB").FirstOrDefault(oo => oo.ID == Id);
to
EntityTypeA entityA = this.ObjectContext.EntityTypeA.FirstOrDefault(oo => oo.ID == Id);
if (!entityA.EntityTypeBReference.IsLoaded)
entityA.EntityTypeBReference.Load();


Still no related entity, and I could see that the property was getting successfully set on the server. It just wasn't making it back to the client.

I was able to finally conjure the correct Google search incantation and found Vincent Leung's post regarding the Include attribute. As soon as I set that in EntityTypeA's DomainService metadata class on the EntityTypeB property my problem was solved. I was able to change my code back to the following more concise format:

EntityTypeA entityA = this.ObjectContext.EntityTypeA.Include("EntityTypeB").FirstOrDefault(oo => oo.ID == Id);

That is all.

Google query

RIA Services Reference

Tuesday, August 3, 2010

Silverlight 4 "Value does not fall within the expected range"


I ported some WPF code to Silverlight 4 and started to receive a System.ArgumentException with the following message:
Value does not fall within the expected range.
Various posts indicated that this typically occurs when you dynamically add child objects with the same names to a container. However, I wasn't dynamically adding anything. After selectively commenting out portions of my XAML I was able to determine that the culprit was a DataGridTextColumn that had no binding attribute declared at all. Example:

<sdk:DataGridTextColumn Header="Pending Time" IsReadOnly="True" />
What surprised me was that when I specified a fictional binding ({Binding Foo}) I got a nice, easy to understand exception:
System.Windows.Data Error: BindingExpression path error: 'Foo' property not found on...
Granted, I am not a Silverlight expert so I might be posting something obvious. I hope that this saves someone some time.

Friday, May 28, 2010

Windows SDK 7.0A and automated builds

We altered our solution and project files to work with Visual Studio 2010. After changing the path to MSBuild.exe and altering ToolsVersion in the ccnet.config file to accommodate the framework change, CruiseControl.NET reported the following error:

C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (1917,9):
errorMSB3086: Task could not find "LC.exe" using the SdkToolsPath "" or the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A".
Make sure the SdkToolsPath is set and the tool exists in the correct processor specific location under the SdkToolsPath and that the Microsoft Windows SDK is installed

Various posts indicate that the 7.0A SDK ships with Visual Studio 2010. With that knowledge I copied the directory "Program Files\Microsoft SDKs\Windows\v7.0A" from my development machine to my build server. I then exported the "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" registry key from my development machine and merged into the registry of the build server. Problem solved.

Wednesday, May 12, 2010

TNSNAMES.ORA and spaces

Just when Oracle database and I had forged an uneasy peace, my day was derailed by my mistake.

When Oracle tells you that "[t]he service name must begin in the first space of a line to be parsed correctly" they are not kidding. I received a request from one of our DBA's to change a server's TNSNAMES.ORA file and copied and pasted the new entry. The three (3) leading spaces on that entry caused me to get "ORA-12154: TNS: could not resolve the connect identifier specified" errors for an hour until I realized my mistake.

Don't let this happen to you. Heed the warning of Oracle.

Friday, April 23, 2010

Using jQuery to avoid work

I've got an old ASP.NET 1.1 app that I've been meaning to rewrite for years but have never had the time. Well, that's not the entire story: it hasn't needed attention in about 3 years. It just does its thing with no intervention on my part.

Until now.

Some recent data changes have caused a critical DropDownList on the landing page to stop being sorted correctly. It's not a huge deal but annoying to the users. I could certainly dive into the underlying T-SQL or install Visual Studio 2003 to modify the code, but that would be a lot of fiddly work. Since the only problem is the sort order of the

Saturday, March 13, 2010

Droid Gmail not synchronizing

For the past 24 hours I've not been receiving new Gmail on my Droid. All of the other apps were still working, even Google Calendar and Contacts. But not the Gmail app.

Manual synchronization didn't work. I deactivated synchronization, turned phone off and on, removed battery. Still no new mail. Looked at the items with the Outbox label and noticed an item, which had a photo attachment, from the day before. I tried to send it and 'No Connection' was the message that I received. Deleted it and new mail started appearing on my phone.

It appears that there was an 'unresolved' item that hadn't been reconciled with the server. This was probably partially my fault because I had tried to send the message from a parking garage, and as soon as I sent the message I deleted the photo from my phone. It was the perfect storm as far as my phone was concerned.

Tuesday, March 9, 2010

Linked Oracle Server configuration pain

For the past day I've been forcing myself to work with the Visual Studio Team System 2008 Database Edition GDR R2 for a small SQL Server 2000 database that needs some attention. I wanted Visual Studio to generate a SQL Server 2005 deployment script that I could execute against a local SQL Server 2008 Express instance in order to test a possible migration. During the initial execution of the script I was notified of an error involving a linked Oracle server. No problem, I thought. I'll just create the linked server and run the script again. As happens so often in software development, though, a seemingly quick and easy task turns into a quagmire.

It's been a while since I set up a linked server and I was a little foggy on the setup steps. I was able to determine by examining the existing SQL Server 2000 server that I needed to use the 'Microsoft OLE DB Provider for Oracle' provider. Still using the existing server, I was able to figure out how to fill in the 'Linked Server Properties' dialog and the Security options. As soon as I clicked the OK button, though, I was presented with an error:

The Oracle client and networking components were not found. These components are supplied by Oracle Corporation and are part of the Oracle Version 7.3 (or greater) client software installation.

OK- maybe I needed to set the 'Provider string' value. Using this page as a reference (though I'm not configuring IIS), I was able to determine the correct Provider value ("Provider=MSDASQL;DRIVER={Microsoft ODBC for ORACLE};UID=User;PWD=Password;Server=Your_TNSNames_Alias") under item 9.

I recreated the linked server but it still didn't work. I looked in the Registry, and in fact created an ORACLE_HOME string value at HKLM\Software\Oracle. That didn't help either, so I removed that value. (I did notice that setting this value fixed something in Toad 9.7.2 but that story is out of scope for this post.) I even restarted my workstation a couple of times in an effort to appease the Oracle Client God. Nothing worked. My linked server was still broken.

Finally I examined my PATH environment variable. Now, I've struggled mightily with configuring Oracle clients because my company has versions of Oracle ranging from 8i-11. My PATH was collateral damage, and contained references to two Oracle installations. The first reference was to an 11 client's root, and the second was to a 10 client's bin directory. At some point in the past I think that I read that the probing / search for an Oracle client stops when the first client home installation is found. With this in mind, I altered the 11 client path element to point to the bin directory rather than the 11 client root. Restarted the SQL Server 2008 Express service and my linked server was alive and kicking.

So what have I learned after 4 hours of tinkering with SQL Server and Oracle client interaction? Well, there's got to be an easier way. It seems to me that the Oracle client setup and configuration process is opaque. Example: is ORACLE_HOME needed in the registry, as an environment variable, both places, or neither one? The answer seems to be that it depends on the application. I've always been lucky that my installations have worked on a server, but it seems like a fragile process for a volatile developer workstation.