tisdag 30 mars 2010

Cannot obtain value of local or argument as it is not available at this instruction pointer, possibly because it has been optimized away.

Ever seen this during debug and ripped your hair on how to see the locals again?


I was working in a project where we during last bug fix sprint encountered problems debugging our code. For most, if not all, locals we wanted to inspect we were shown a message like the above. Turned out there were others having stumbled with similar issues such as Scott Hanselman and Kirill Osenkov.


Unfortunately none of their suggestions worked in our case where we were having those issues for a web site project. Eventually we found the cause being the web site project’s advanced build settings being set to .pdb only as in the screen show below:


So, for us it worked like a charm again after right clicking the web site project, selecting Properties, Build, Advanced and changing Debug info to Full.


Hope this helps someone else out there!

onsdag 2 september 2009

How to get random records using LINQ to SQL

Some time ago I was in need of getting random records out of a chunk of database records. One method I found great was using the TSQL NEWID() function. The NEWID() function will create new random unique identifiers which you can use like in the sample TSQL query below:

SELECT TOP 10 * FROM Ads ORDER BY NEWID()
This query will return 10 random ads every time executed. Now, LINQ to SQL doesn’t have an equivalent to the NEWID() function so how do we accomplish the same results? So far I’ve come across two ways of doing it.

1) Use the TSQL NEWID() function

This may sound a bit strange but using a TSQL function from within LINQ to SQL is actually possible. By attaching a function to the LINQ to SQL data context that map a .Net method to a TSQL function we can use the SQL Server function right within our LINQ to SQL query. To do this we need to implement a method as a partial class to the data context and decorate it with the [Function] attribute like so:

partial class AdsDataClassesDataContext
{
[Function(Name
="NEWID", IsComposable=true)]
public Guid Random()
{
throw new NotImplementedException();
}
}

There are two parameters for the [Function] attribute, Name and IsComposable. Name is the name of the SQL Server function (or stored procedure), NEWID in this case, and IsComposable is a boolean expressing whether we’re calling a SQL function or stored procedure (true if a function; false if a stored procedure).

But why are you throwing an exception in the method? It doesn’t really matter whatever goes into the method in this case. Once the method Random is called it will call the SQL Server function NEWID() regardless - just as we’ve attributed it.

Using the above we can get a random set of records like below:

AdsDataClassesDataContext dbContext = DB.GetAdsDataContext();
var a
= from ad in dbContext.Ads
where ad.CultureId == cultureId
orderby dbContext.Random()
select ad;


2) Order an object collection using the Random class and the OrderBy extension method

Having a collection of objects we can make use of the Random class and OrderBy method like this:


Random rnd = new Random();
IEnumerable
<Ad> ads = myAdsCollection.OrderBy(r => rnd.Next());

That’s two ways. I’m all ears hearing about more ways of achieving the same!

onsdag 13 maj 2009

Top domain based web localization support

There are a couple of different ways on how to deal with web site localization. In some cases you simply want to display text and images in a given languages either by sniffing the user’s browser language setting or letting users select a language of choice. Other times you may want to have a top domain locked into a specific language. This post will discuss one method of supporting the latter.

Imagine you’re a web developer being assigned the task of creating an e-commerce web application that should support the following requirements:

  • One single application instance should allow users browse the site and retrieve the web pages translated to their language.
  • The application should emit the content in the language corresponding to the top domain, such as
    • .com –> English pages
    • .se –> Swedish pages
    • .de –> German pages
    • and so on…
  • Visiting a particular top domain of the e-commerce site you should only have that domains corresponding language displayed, i.e. selecting a different language in the event of a Select language option you should be seeing the selected language’s top domain reflected in the URI. Either you’re browsing Swedish stuff, or you’re browsing American stuff.
  • In this e-commerce site, web content like products should contain language specific prices, descriptions and the like and it should be a breeze for you, the web developer, determining how to gather product data corresponding to the users language – or rather, top domain choice.

One way of fulfilling the requirements listed is by making use of the IHttpModule interface. One great aspect of the IHttpModule interface is that it allows you to hook up with events such as BeginRequest and perform whatever you need to before the page and subsequent requests and events happen. Not too seldom I’ve used http modules to gather and set some members frequently needed by many pages and controls in order to avoid having to run the same calls from every single page and/or control. Doing this one time at the beginning and keep the result readily available for later often comes handy.

So, let’s see how we solve the issue at hand, namely create a web application supporting the requirements listed above by using the IHttpModule interface. Below is an example implementation snippet of a http module that sets the threads culture members in addition to a static CultureInfo object that we can use from any page within the web application.

public static CultureInfo Culture { get; set; }

public void Init(HttpApplication context)
{
// Hook up the BeginRequest event.
context.BeginRequest += new EventHandler(this.context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpContext context
= ((HttpApplication)sender).Context;
string fileExtension = VirtualPathUtility.GetExtension(context.Request.FilePath).ToLower();

// We only want to run this once for each .aspx page being loaded.
if (fileExtension.Equals(".aspx"))
{
string topDomain;
try
{
// Determine the hosts top domain
topDomain = context.Request.Url.Host.Substring(context.Request.Url.Host.LastIndexOf('.'),
context.Request.Url.Host.Length);
}
catch (Exception)
{
// We do this for 2 reasons.
// 1) Make sure we can fall back on a language should it happen so we have better
// host header support than actual localization material
// 2) Under localhost development we need to be able to set a default language,
// and also be able to change between them for test, debug and other.
topDomain = "se";
}
// Switch through some supported top domains and set Culture member to the corresponding language.
// Note! default sets Culture to Swedish. This could as well be configurable through an AppSetting
// rather than hardcoded here.
switch (topDomain)
{
case "se":
Culture
= new System.Globalization.CultureInfo("sv-SE");
break;
case "com":
Culture
= new System.Globalization.CultureInfo("en-US");
break;
case "de":
Culture
= new System.Globalization.CultureInfo("de-DE");
break;
default:
Culture
= new System.Globalization.CultureInfo("sv-SE");
break;
}

// Set the culture properties for both UICulture and Culture
System.Threading.Thread.CurrentThread.CurrentUICulture = Culture;
System.Threading.Thread.CurrentThread.CurrentCulture
= Culture;
}
}



As you may have noticed there is certainly room for improvements to this code but I hope it illustrates the purpose. This particular implementation will fall back on Swedish if you’d visit the site using a host like http://www.yourdomainname.fi/.


Having set the Culture member we can now use it in .aspx pages and .ascx user controls like below:

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
gvProducts.DataSource
= DAL.GetProducts(InstanceModule.Culture.Name, dataFilePath);
gvProducts.DataBind();
}
}

Pretty nice!

In order to not become an overly wordy post I created a tiny sample application using the http module implementation above so you can play around and see how it works. Change the line topDomain = "com"; to topDomain = "se"; in the catch statement above and notice how the Swedish products are picked up instead of the English ones. The thourough observer may also notice there is no .resx file specific for Swedish but due to the fallback mechanism built into the framework we’ll still get Swedish cause the default .resx contains Swedish.


Download code

About time entering cyber space!

Reading this? Welcome to my blog!

Although having spent half my life around computing I never really got hooked on the latest and greatest social computing technologies and forums like blogging, Facebook, Twitter, Live spaces and other. I guess I considered myself busy enough on other things but producing text for blog posts, posting status updates like being stuck in traffic jam, mowing the lawn or other no one would ever care reading anyway.

- Or would they? No clue. Better test this out or be stuck in uncertainty forever.

For now I’ll use this place to share some stuff I hope might be of interest to others that may run into similar issues as I’ve done myself. I think it’s fair to say I’ve gotten (or should have gotten) a fairly good understanding of a few areas such as:

  • Software globalization and localization
  • Web development using primarily Microsoft technologies
  • Database development
  • .Net Framework developing using C#
  • And other random software related areas

So, them postings ain’t gonna post themselves. Better get going! Stay tuned for the first one. Think it’ll be something related to software localization from a web development perspective.

Välkommen! (Welcome!)