Tuesday, January 22, 2008

Successor to Windows Vista

Not sure for how many this will come as a shock. For me, it definitely did!

The next edition of Windows, i.e. the successor to Vista, is not only under development umbrella but started to ship too. The first milestone (M1) has been shipped to MS partners and is available in English only for both x86 and x64 machines. And it's scheduled to do a RTM in H2 2009. It was originally supposed to RTM in 2010 but looks like MS is pulling strings pretty hard.

Not much of information is available as of yet as to what all the new version carries. But since we have some tie-ups with MS, looks-like I can get my hands-on it. 09-10 is going be one heck of a year for us as well as MS, with Rosario also set to be released.

Keep watching this space for more information on what the new OS is all about.

By the way, it's called Windows 7 (previously code-named Blackcomb Vienna)

Source: http://www.tgdaily.com

How many still read books?

An interesting discussion is brewing up at codeproject.com. The discussion is about how many people still read those "hard paper books"? How many of us still do it? I do it. Probably 1 book a week :) I know it sounds unbelievable but its true. No doubt, I have started this initiative pretty recently. I have 4 books now under this belt. But, anyway, that's not the topic right now.

Most of the time people think that, in this blog-savvy world, there is hardly anyone left who reads books (for whatever reason!). But I was surprised to see that MS MVPs (people chipping-in to the discussion at codeproject) still find time to read books, around 10-50 per year. thats a pretty good score, considering that an year has around 52 weeks. So a book-a-week.

So, if you look at it the other way round, then
looks like I'm on my way to become a MS MVP :) :) :)

Wonderful to know that I have company! Oh no, not as MVPs but as book readers :)

Friday, November 16, 2007

Making Entity Framework work with a Web Application

Making Entity Framework (EFW) work with a web application was the toughest (relatively) of the lot (Win App, Console App etc).

To get it working for any type of app, these 2 steps are sufficient:
  1. Add the app.config of the EFW project to your app. If you already have a app.config, then add only the "connectionStrings" node of it.
  2. Copy the c/m/s (.csdl, .msl and .ssdl) files to the bin directory, where the executable of the app resides.

But if you have to get this working for a web app, then

  1. Add the "connectionStrings" node to your web app's web.config.
  2. Copy c/m/s files to App_Data folder
  3. Change the string in "connectionStrings" node From
    ".\EFWSampleDb.csdl.\EFWSampleDb.ssdl.\EFWSampleDb.msl"
    To
    "DataDirectoryEFWSampleDb.csdlDataDirectoryEFWSampleDb.ssdlDataDirectoryEFWSampleDb.msl"

Alternately, instead of "|DataDirectory|EFWSampleDb.csdl" you can also say "~\App_Data\EFWSampleDb.csdl". ("~" refers to the root directory of the web app). So, this essentially means that you can have the m/s/l files in any directory, and not necessarily in App_Data, and reference it in web.config.


Failing to do the above steps may error out saying:

"The specified metadata path is not valid. A valid path must be either an existing directory, an existing file with extension '.csdl', '.ssdl', or '.msl', or a URI that identifies an embedded resource."


OR

"The specified named connection is either not found in the configuration, not intended to be used with the EntityClient Provider, not valid."

Wednesday, October 24, 2007

C# 3.0 Features: Lambda Expressions

C# 3.0 Lambda expressions come very handy to developers. One important consideration (which is beautiful) is that all these features (LINQ, C# 3.0 features, Entity Framework etc) come with no change in CLR. That means your old CLR, which executes your .Net 2.0 apps can execute your new apps too. And that implies that the IL that is emitted hasn't changed. So, though you use Lambda expressions instead of anonymous methods, the IL generated is the same in both cases. (Wow!!! Now I can feel the beauty of the IL concept and design.)

Coming back to Lambda expressions, what are they basically? They are not just a syntactic substitute to anonymous methods. You can read more about Lambda expressions (and an interesting topic of how to pronounce them!!) in Eric White's blog. I will deal with two important things of Lambda expressions (in context of LINQ) which you may not find often on the web.
  1. Writing whole blocks of code in Lambda expressions. (Remember that Lambdas are expressions, hence writing more than one statement may sound little odd)
  2. Returning subtypes (or columns) of a type on which the LINQ query is fired.

Writing whole blocks
Lambda expressions definitely make writing anonymous methods easy. Using Lambda you can do all that you can with anonymous and even more. So, if you can write a proper function with different control statements and logic using anonymous, you can do the same with lambda. Most of the lambda examples you see would be something like this:

var existingAccount = repository.Accout.Where(a => a.AccountId == "1");

You can write quite an amount of logic here, something like this:

var existingAccount = repository.Accout.Where(a =>
{
if (a.AccountId == "1" && a.AccountName == "Pavan")
return true;
else
return false;
});

The above code snippet will return an Account object after processing all the logic, accordingly. So, as you can see, it's just like any other (anonymous) function.

Now, if you carefully observe the snippet above, we are returning a boolean value from within the lambda but what existingAccount contains is an Account object. How did this happen? Well, it's pretty simple. If you carefully inspect signature of "Where" method being called on Account, you can understand.


What Where expects is a Linq.Expressions.Expression parameter which, in turn, expects a delegate that takes an input parameter as InsuranceDBWrapper.Account and returns a boolean. And this delegate's return value decides whether to return the object (in our case Account) on which Where is being called. And that's exactly what our lambda does - to return a boolean telling whether to return the (Account) object or not. Note that you can pass the delegate directly also without any expression in between.

Returning Subtypes (or columns)
What if you don't want the whole type (or object) to be returned but just some columns or subtypes of it? You can as well do that, but not using Where. Where has 4 overloads of which two take expressions and the other two, directly delegates. But the sig for these delegates involves atmost two input parameters (first parameter is the type on which Where is applied and which is inferred automatically, second an int which gives the index of an item) and always returns a boolean (which tells whether to return the whole object or nothing). So, there is no means here to select and return specific columns. Since you return a boolean, it's either the complete object or nothing - that is returned.

What you need to use in this case is a Select:

var existingAccount = repository.Accout.Where(a => a.AccountId == "1").Select(b => new {b.AccountId, b.Name, b.IsLocked});

This returns an anonymous type with three properties (AccountId, Name, IsLocked).

Select is used to filter on columns and Where is used to filter on rows.

Lambdas can be used in Expression trees (which will be in a separate post :))

Workflow with id not found in persistance store

For couple of days now I've been doing extensive debugging of a (Windows) Workflow. And time and again I've been facing this error. So I thought I will elaborate more on this. There are three primary reasons why this might happen:

  1. Your workflow has actually terminated. It could have terminated or finished execution, but since you wouldn't try to load a finished workflow, in all probablities, it would have terminated (due to some unhandled exception). You can check this by going to your WorkflowInstance table in your persistence store and check the DbEndDateTime for your workflow instance. If it is null, then you can move to next points :-) else you have found the culprit. All you have gotta do is to debug into your workflow and fix your code.
  2. Workflow changes. If you make any changes to your workflow and then try to load previous instances of it, you will see this error. You will have to apply the changes done on the workflow to the old instances also.
  3. Try to connect to remote persistence store. If you are trying to load a workflow instance from a remote store, this error will come up. Make sure that your remote (store) server DTC is configured to allow this.
Hopefully, this will help people in saving time trying to find why the workflow doesn't load. Pls be aware that this error can come up due to many other reasons and not only the three mentioned above.

C# 3.0 Features: Var

"var" is one feature of C# 3.0 that has called for much debate. What is "var" and when can it be used, has already been dealt in many blogs and Microsoft documentation. So, I'll not be writing about it here. What I'll talk about is why var is not allowed to be passed around in functions i.e. why do you get this compile-time error:

the contextual keyword var may only appear within a local variable declaration

when you try to accept a parameter of type var. Considering that var can accept anonymous types, it is very convenient to tossing it around in function calls. But that isn't allowed. Let's see why:

Let's approach this using the Contradiction theory. Let's assume that this doesn't give any error and is allowed. Now, when the code is built the actual type of var has to be resolved. And since the var, in our case, hasn't been initialized (remember it's a function parameter), the compiler doesn't know to what type the var should be resolved. And that's why the compiler can't allow this. Let's also assume that the compiler is intelligent enough to infer its type from the invocation call of the method i.e.

..........
ExectueThis(5)
..........

private void ExecuteThis(var intVar)
{
}

Looking at "ExectueThis(5)", let's say, the compiler infers intVar is of Int32 type. Looks good to me if the compiler could do it. But what if ExecuteThis is called from somewhere else also and a string is being passed to it.

ExecuteThis("abc")


Probably we can say that don't allow the second call as from the first call we have already determined intVar to be Int32. But what if all this is in a class library, where you can't determine the sequence of function calls i.e we don't know whether first function call will be made first or the second one will be made first.

So, essentially, there is no way the compiler can tell, for sure, what type the var parameter is. And thus var can't be passed around in functions. I don't see a great use of var in general programming except if you are using LINQ. It helps you to avoid declaring custom types for each resultset that is returned from a LINQ query. var is more tailored for use with LINQ

Thursday, October 4, 2007

VS 2005 C# projects in Orcas Beta 2

Opening a VS 2005 C# project (.csproj) in Orcas Beta 2 may sometimes throw you this error:

"Make sure the application for the project type (.csproj) is installed."

I tried googling on this but did not find much information except that, this might happen if your project is under source control. My projects were under source control and hence I was elated as the post did carry a solution for the same (http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=8461&SiteID=1). But my elation was short-lived as the work-around didn't help me.

After breaking my head for sometime I came with a work-around that resolved the issue. Here are the steps:
  1. Delete the solution file and any associated source control bindings.
  2. Open one of the projects (open the .csproj file)
  3. Orcas will prompt for migration to new version. Finish it.
  4. Now add all the remaining projects to the newly created solution.
  5. Once you re-create your solution structure save it to the location from where you deleted the original one.
The solution can now be built.

Also, do not forget to change the target framework to 3.5 in your project properties unless you aren't using any of 3.5 features.