Wednesday, 31 October 2007

Where can I get the Visual Studio 2008 Runtime installer?

You can get the Visual Studio 2008 runtime installer from X:\WCU\dotNetFramework\dotNetFx35setup.exe where X: is the virtual drive path of your Visual Studio 2008 Setup. Note that for Vista-based installs you must run it in Admin mode for the setup to work correctly - otherwise the setup will fail.

Friday, 26 October 2007

Picture of the day!

Don't say we didn't warn you!


Creating a root Virtual Path usng Cassini

If you ever wondered how to create a root Virtual path using the new ASP.NET2.0 Web Development Server (Casini)? It’s easy!

At the moment our application is having problems mapping images correctly because it will not accept http://localhost:8080/WebUI/default.aspx
Even if I create an IIS virtual directory http://localhost/WebUI/default.aspx it will still not be good enough.
(I know I know it is this stupid third party CMS and I have no control over its relative mappings)

I need something like the following:

http://localhost:8080/default.aspx

Create an external tool from “Tools” > “External Tools…”
Add a new external tool and call it “WebServer on port 8080 (or whatever port you want)
In the command point to casini which is located at C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\WebDev.WebServer.EXE
Have the argument as the following so that you assign the port and the path is directly in the Project Directory as follow:/port:8080 /path:$(ProjectDir)
Click ok
Then run the tool by going “Tools” > “Web Server on Port 8080”
Cassini will now run in the task bar with http://localhost:8080/
In the Properties Page of your web project, select “Start Options” and select “Use custom server” radio button
Type the Base URL as http://localhost:8080/
OK

Wednesday, 24 October 2007

LINQ and the DataContext Attach() method

I just found out today that it is possible (rather than passing a DataContext object around by reference or refetching the objects), to "re-attach" objects to another data context. You can then perform updates on the object and related collection. See this article for more details:
http://blogs.msdn.com/dinesh.kulkarni/archive/2007/10/08/attach-if-you-have-something-detached.aspx

Tuesday, 23 October 2007

C# code format for Blogs

This is just a simple formatting tool that you can use online to format your code using "pre" tags

http://www.manoli.net/csharpformat/

My code samples in previous posts use this tool for formatting. Also supports XML, HTML, VB, SQL and Powershell scripts (aka Monad).

C# Coalesce

The ?? coalesce operator checks whether the value on the left hand side of the expression is null, if so it returns the value on the right hand side. If the value on the left hand side is not null, then the left hand side value is returned:

string message = "Hi Devs";
string result = message ?? "It was null!";

// Outcome: result == "Hi Devs"


string message = null;
string result = message ?? "It was null!";

// Outcome: result == "Message was null"


Note that this is a short-circuited operator. For example:

a = b ?? c;
translates to:
a = ( b == null ? c : b);
Which means the expression c is only evaluated if b is null. There is no equivalent in VB (short of performing an iif())

LINQ - Best Practices with Anonymous Types

Anonymous types allow you to return data from multiple LINQ objects which are strongly typed, determined at runtime. However, anonymous types only have local scope. I believe that best practice with LINQ objects is to NOT cast the anonymous type to an object and consume it (because designers e.g. datagrid cannot determine the properties of the type).

Instead of casting to objects and consuming, you should really create a wrapper class which defines the standard contract that can be returned from your data access layer.

Example:



   1:  using System;

   2:  using System.Collections.Generic;

   3:  using System.Text;

   4:  using System.Linq;

   5:  using System.Configuration;

   6:  using LendLease.InvestmentManagement.AssetMaintenance.Entities;

   7:   

   8:  namespace LendLease.InvestmentManagement.AssetMaintenance.Services

   9:  {

  10:      public class CityName

  11:      {

  12:          public string DisplayValue {get; set;}

  13:      }

  14:      class AddressService : IAddressService 

  15:      {

  16:   

  17:          static AddressService()

  18:          {

  19:          }

  20:   

  21:          public IList<CityName> GetAllCities()

  22:          {

  23:              InvestmentManagementDbDataContext context =

  24:                   new InvestmentManagementDbDataContext();

  25:   

  26:              var query = (from ps in context.Addresses

  27:                          select new CityName { DisplayValue = ps.City }).Distinct();

  28:              return query.ToList();

  29:          }

  30:      }

  31:  }





For more info, see http://weblogs.asp.net/scottgu/archive/2007/05/15/new-orcas-language-feature-anonymous-types.aspx?CommentPosted=true
and http://blogs.msdn.com/miah/archive/2007/09/07/outsmarting-the-limitations-of-anonymous-types.aspx for some more comments on this.

Changes to System.Data.Linq.ChangeSet and System.Data.Linq.Table from VS 2008 Beta 2 to RTM

Just installed VS 2008 release candidate, and there were some compile issues related to the System.Data.Linq.ChangeSet class. One of the changes that affected me in the upgrade was the move to move "Database mindset" language. I found this move from "ModifiedEntity" to "Updates" unusual because it is terminology brought from the database field. There is also a change to System.Data.Linq.Table where the "Add" method is now "InsertOnSubmit". The "Remove" method is now "DeleteOnSubmit". Seems like a throwback to me!

Another issue is that my LINQ dbml files had conversion issues, showing the error:
"There is no Unicode byte order mark. Cannot switch to Unicode." The fix was just to remove the encoding attibute in the XML document description:

<?xml version="1.0" encoding="utf-16"?>



public bool Run(ChangeSet changedObjects)
{
List<trackedobject> tracked = new List<trackedobject>();
foreach (object o in changedObjects.AddedEntities)
tracked.Add(new TrackedObject { Current = o, IsNew = true });
foreach (object o in changedObjects.ModifiedEntities)
tracked.Add(new TrackedObject { Current = o, IsChanged = true });
foreach (object o in changedObjects.RemovedEntities)
tracked.Add(new TrackedObject { Current = o, IsDeleted = true });
return Run(tracked);
}

needs to change to:


public bool Run(ChangeSet changedObjects)
{
List<TrackedObject> tracked = new List<TrackedObject>();

foreach (object o in changedObjects.Inserts)
tracked.Add(new TrackedObject { Current = o, IsNew = true });
foreach (object o in changedObjects.Updates)
tracked.Add(new TrackedObject { Current = o, IsChanged = true });
foreach (object o in changedObjects.Deletes)
tracked.Add(new TrackedObject { Current = o, IsDeleted = true });

return Run(tracked);
}