LinQ to Entities on ADO.Net vs LinQ to SQL

To make it short :

  • LinQ to SQL only works with SQL Server but it’s working great. It’s simple, supports all LinQ operations and optimizes the generated SQL queries.
  • LinQ to Entities on ADO.Net works with lots of database but it doesn’t behave like LinQ to SQL and doesn’t support some key LinQ features.

Now the long story :
For the last project I’ve been working on, we wanted to use LinQ and still be able to switch to one database to an other (MSSQL to MySQL for instance). So we decided we would use LinQ to entity. The generated object are roughly the same, the code to Create/Read/Update/Delete data is roughly the same. So we were quite happy.

Deffered loading
When you do a LinQ request, the data from the associated table isn’t fetched. There’s in fact no other way, as you would get your whole database if you always fetched all the associated objects of your current query.
Deferred loading consists in loading the data coming from an associated table when you request it (when you access your object property).
Eager loading consists in loading the data when you request it.

In LinQ to entities, deferred loading isn’t supported. You have to use eager loading with the .Include(“Property”) LinQ method.

1
var query = from u in Db.User.Include( "Group" ) select u;

But in fact, you can do some deferred loading very easily in LinQ to Entities :

1
2
3
4
5
6
7
8
var query = from u in Db.User select u;
 
foreach( var user in query ) {
    if ( ! user.GroupReference.IsLoaded )     
        user.GroupReference.Load();
 
    Console.WriteLine( "User={0}, Group={1}", user.Name, user.Group.Name );
}

Non supported LinQ key features
Well, now I only want to select the users 1, 2, 3 :

1
2
var users = new int[] { 1, 2, 3 };
var query = from u in Db.User.Include( "Group" ) where users.Contains( u.UserId ) select u;

Oups, that would work on LinQ to SQL, but on LinQ to Entities it doesn’t. LinQ to Entities doesn’t support the .Contains or .Any methods. (Note : these methods are supported since .Net 4.0, see below).

There’s in fact a solution but it requires your request to be typed in a method based LinQ Query :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
		static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(
			Expression<Func<TElement, TValue>> valueSelector,
			IEnumerable<TValue> values
		) {
			if ( null == valueSelector ) { throw new ArgumentNullException( "valueSelector" ); }
			if ( null == values ) { throw new ArgumentNullException( "values" ); }
			ParameterExpression p = valueSelector.Parameters.Single();
			// p => valueSelector(p) == values[0] || valueSelector(p) == ...
			if ( !values.Any() ) {
				return e => false;
			}
			var equals = values.Select( value => (Expression) Expression.Equal( valueSelector.Body, Expression.Constant( value, typeof( TValue ) ) ) );
			var body = equals.Aggregate<Expression>( ( accumulate, equal ) => Expression.Or( accumulate, equal ) );
			return Expression.Lambda<Func<TElement, bool>>( body, p );
		}

And then it looks like this :

1
2
var users = new int[] { 1, 2, 3 };
var query = Db.User.Where( BuildContainsExpression<User, int>( u=> u.UserId, users ) );

Now, let’s say you want to use the Include method in the method based query. Well you can’t. But someone added an extension method to do this :

1
2
3
4
5
	public static class ObjectQueryExtension {
		public static ObjectQuery<T> Include<T>( this ObjectQuery<T> mainQuery, Expression<Func<T, object>> subSelector ) {
			return mainQuery.Include( ( ( subSelector.Body as MemberExpression ).Member as System.Reflection.PropertyInfo ).Name );
		}
	}

You have to use it like that :

1
2
var users = new int[] { 1, 2, 3 };
var query = Db.User.Include( u => u.Group ).Where( BuildContainsExpression<User, int>( u=> u.UserId, users ) );

I hope this could help you start or switch to LinQ to entities in case you hesitated.

LEFT JOIN in LinQ to entities
You know how LEFT JOIN works in LinQ, you need a join and DefaultIfEmpty :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var query = 
from user in Db.User
join preferredSuperHero in Db.User_Parameter on 
	new { 
		UserId = user.UserId, 
		ParamName = "PreferredSuperHero" 
	} 
	equals new { 
		UserId  = preferredSuperHero.UderId, 
		ParamName = preferredSuperHero.Parameter.Name 
	}
	into joinedPreferredSuperHero
from preferredSuperHero in joinedPreferredSuperHero.DefaultIfEmpty()
orderby user.Name
select new { User = user, PreferredSuperHero = preferredSuperHero };

Except… DefaultIfEmpty doesn’t works with LinQ-to-entities. You generally can find other solutions, but it will add some difficulties. (Note : this method is supported since .Net 4.0, see below).

Check what is supported
In this page, you can check if the methods you might require are available. The two non supported methods I talked about are supported with the .Net 4.0 (currently only available in bĂȘta). So most of the problem related to the missing methods will be solved.

About switching from one base to an other
Switching from one base to the other can be pretty easy if you have the right conversion tool. If not, you have to do all the work yourself. If you wish to switch to MySQL for instance, you can use the MySQL conversion tool. It converts the table structure, the keys, the foreign keys, the indexes and the data from MSSQL to MySQL.

After that, the generated code is exactly the same but I’m not sure you can use one EDMX model file for multiple databases. It might work by using an external SSDL (instead of an resource embedded file) that you select in the connection String for each database. But I haven’t tested it yet.

My little conclusion
LinQ to entities works pretty well. The non automatic deferred loading is really not a problem, especially since it totally kills performances (it fetches data row by row instead of loading everything from a single request). My biggest problem was the lacking support of some LinQ methods, you can solve most of them easily (it just makes an ugly code).

With the .Net 3.5, I think the multi-database feature offered by LinQ to Entities on ADO.Net worth this little extra effort to make it work. But if you don’t care about this (because you only build a little short-life program), you should stick to LiNQ to (MS)SQL as everything works instantly on it.

With the .Net 4.0, LinQ to entities becomes even more interesting. And that’s a reason to start using it with the .Net 3.5 framework.

Sources :

Inside Sharepoint

I recently took the time to take a look inside the Microsoft.Sharepoint.dll using reflector. I’m not sure I have the right to do that. And I’m pretty sure I don’t have the right to publish any code extracted from it, so I won’t show any.

Using SPSite(s) and SPWeb(s)
If you do some timing on the SPWeb creation call (SPSite.OpenWeb), you will find out that it’s freaking fast (less then 1 ms on my server). The reason is that the most heavy object, the SPRequest class, is shared among SPWebs of a SPSite. The Dispose call only “Invalidate” the SPWeb, and if this SPWeb is the owner of the SPRequest (which is SPContext.Current.Web object in most of the cases), it releases it.

Personnaly, I like to have something like that when I use a particular SPWeb along my code in a WebPart :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private SPWeb _rootWeb;
public SPWeb RootWeb {
    get {
        if ( _rootWeb == null ) {
            _rootWeb = SPContext.Current.Site.RootWeb;
            if ( _rootWeb != SPContext.Current.Web )
                _toDispose.Add( _rootWeb );  
        }
        return _rootWeb;
    }
}
 
private List<IDisposable> _toDispose = new List<IDisposable>();
protected override void OnUnLoad() {
    foreach( var disp in _toDispose )
        disp.Dispose();
}

But the code above won’t make you gain a 1 ms compared to this code (which is shorter and potentially safer, you don’t need to dispose everything) :

1
2
3
4
5
6
7
8
var rootWeb = SPContext.Current.Site;
try {
    // Your code
}
finally {
     if ( rootWeb != SPContext.Current.Web )
         rootWeb.Dispose();
}

If you had to access some more indirect objects, you certainly should keep the code showed earlier. For instance to use a SuperToken Web :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private SPSite _stSite;
SPSite STSite {
    get {
        if ( _stSite == null ) {
            _stSite = new SPSite( SPContext.Current.Site.Url, SPContext.Current.Site.SystemAccount.UserToken );
            if ( _stSite != SPContext.Current.Site )
                _toDispose.Add( _stSite );
        }
        return _stSite;
    }
}
 
private SPWeb _stWeb;
SPWeb STWeb {
    get {
        if ( _stWeb == null ) {
            _stWeb = STSite.OpenWeb( SPContext.Current.Web.Url );
            if ( _stWeb != SPContext.Current.Web )
                _toDispose.Add( _stWeb );
        }
        return _stWeb;
    }
}
 
private List<IDisposable> _toDispose = new List<IDisposable>();
protected override void OnUnLoad() {
    foreach( var disp in _toDispose )
        disp.Dispose();
}

Here, opening these new SPSite and SPWeb takes 200 ms on my server. Making sure this only happen once per webpart (or better, per page) can really boost your performances.

The SPRequest object
Well… I was very disapointed, the SPRequest object references an SPRequestInternalClass from the Microsoft.Sharepoint.Library assembly which only uses interrop COM+ methods. So, it’s basically wrapping COM+ methods. The SPRequest does a lot of exception handling and it keeps track of where (with the stacktrace) it has been created and the size of the “unmanaged stack”.

Optimization
I like how they did their code. It’s pretty optimized (they even use a bunch of gotos). But sometimes there is some weird things and I don’t know if it’s the compiler’s or the developer’s fault. If you look at the code, they have an SPRequestManager.SPRequestsPerThreadWarning property, which gets (in the Registry, at “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings\LocalSPRequestWarnCount”) the max number of opened SPRequest objects opened before logging it (or 8 if this entry doesn’t exist), that takes twice the amount of code it would normaly require.

The limit of disassembling
The most frustrating part is there are tons of really important methods that are obfuscated (and that .Net reflector doesn’t disassemble, it could at least give the IL code in comments). I just have :

1
2
3
private static void xxx() {
    // This item is obfuscated and can not be translated.
}

For instance, I really would have liked to see how works the SPList.Update() method, but it’s also obfuscated.

You should explore it too
In the Microsoft.Office.Server.Search assembly, you will also find some pretty interesting things. If you look how works the standard search webparts, well you will be pretty disapointed. The advanced search uses an internal (in the C# meaning) shared object.

Before doing your own webpart, you should take a look at the overriden methods of some sharepoint webparts. It can show you, for instance, how to create your own toolparts. In my last project, I used a stupid text property instead of using a DropDownList in a ToolPart, I was very disappointed with myself when I discovered this.

Mono Tools for Visual Studio : I have tested it !

Yes, I have tested MonoVS with the version 0.2.2641 (on both client and server). I installed OpenSuse 11.1 and added the MonoVS software repository, and everything worked ! I would have prefer to get it from SVN in order to use it in my Debian hosts but the mono development team seems to have removed it from their SVN repository.

So, the Mono Remote Debugger for Visual Studio works, but there still some bugs. Deployment is super fast and it copies all the required DLL.

Remote debugging can be used (launching it is really fast too), but has some bugs, here are the ones I could find :
- On the classical mouse hover debugging popup, the expandable element “Non-public members” is always empty if available. If not available, every private member is displayed like any other public member variable.
- In my first tests, the “watch” window wouldn’t allow any variable to be expanded.
- If you have a variable not yet declared (but available) in the watch window and try to expand it, debugging just stops without any warning
- Sometimes, when I stop debugging I get a message saying something went wrong and the debugger might be unstable
- Once, after making a pause and then a stop, it totally crashed Visual Studio (but it only happened once).

And this is not really a bug, but unhandled exception are displayed in the dirty popup. This isn’t pretty.

If do “Run remotely in Mono”, it will display the Console output in the server’s console. If you do “Debug remotely in Mono”, the Console output is redirect the Debug output window.

This tool is still in private beta (I guess anyone has a good chance to be accepted like I was), but it can already help a lot of people. Even if you just use the Remote Running (which includes deploying the assembly), it still worth using this tool.

Sharepoint – Updating webparts

I’ve talked about this before. When you create versions of webparts, you have two main solutions to update existing webparts :

  • Create a binding redirect within the web.config file.
  • Update each and every webpart instance of the collection site (or just the site).

The first one is really the best solution : It’s simple and very fast. But, it applies to the whole Web Application. Sometimes, the client might want to only update the site collection or even the website. In this case, we need to apply the second solution : update each webpart.

Updating each webpart requires you to create a solution that will go through all the pages of your website and replace each instance of a webpart by an other instance.

I can’t give the complete code (as it’s still not mine), but only some little hints that can help you solve this problem.

You have to analyse each an every file of your websites :

1
2
3
4
5
6
7
8
9
		private static void AnalyseFolder( List<SPFile> list, SPFolder folder ) {
			foreach ( SPFile file in folder.Files ) {
				var fileName = file.Name.ToLower();
				if ( fileName.EndsWith( ".aspx" ) || fileName.EndsWith( ".master" ) )
					list.Add( file );
			}
			foreach ( SPFolder subFolder in folder.SubFolders )
				AnalyseFolder( list, subFolder );
		}

You could restrict youself to the “pages” folder, but you would miss some pages like the layouts.

Then for each file of the class :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
		private void TreatPage( SPWeb web, SPFile file ) {
			try {
				if ( file.Name.EndsWith( ".master" ) ) {
					Logger.LogVerbose( "\"{0}\" is a masterpage...", file.Url );
					return;
				}
				SPWeb managerWeb = null;
				try {
					if ( file.Item == null ) {
						Logger.LogNotice( "\"{0}\" isn't part of a document library...", file.Url );
						return;
					}
 
					// Sometimes the code above works but this will still throw an exception
					file.Item.ToString();
				} catch ( SPException ex ) {
					Logger.LogNotice( "\"{0}\" isn't part of a document library...", file.Url );
					return;
				}
				try {
					using ( var manager = file.GetLimitedWebPartManager( PersonalizationScope.Shared ) ) {
 
						managerWeb = manager.Web;
 
						// we reload the same file but in the SPLimitedWebpartManager's web context
						file = managerWeb.GetFile( file.Item.UniqueId );
 
						var collection = manager.WebParts;
 
						var toDelete = new List<WebPart>();
 
						var previousWebparts = new List<WebPart>();
						foreach ( WebPart wp in collection )
							previousWebparts.Add( wp );
 
						Boolean madeChanges = false;
 
						var toDispose = new List<WebPart>();
 
						foreach ( WebPart wp in previousWebparts ) {
							Boolean deleteWebPart;
 
							var newWebPart = GetNewWebPart( wp, out deleteWebPart );
							if ( newWebPart != null || deleteWebPart ) {
 
								if ( !madeChanges ) {
									CheckOutPage( file );
									madeChanges = true;
								}
 
								Logger.LogVerbose( "Replacing webpart \"{0}\" by \"{1}\"...", wp.GetType().FullName, newWebPart != null ? newWebPart.GetType().FullName : "- none -" );
								if ( newWebPart != null )
									manager.AddWebPart( newWebPart, wp.Zone != null ? wp.Zone.ID : "0", wp.ZoneIndex );
 
								// it's either replaced or deleted : it will need to be removed from the page
								toDelete.Add( wp );
 
								if ( newWebPart != null )
									toDispose.Add( newWebPart );
							}
						}
 
						// If we made some changes to the file, we have to save it
						if ( madeChanges ) {
							foreach ( var wp in toDelete )
								manager.DeleteWebPart( wp );
 
							file.Update();
 
							CheckInPage( file, "Webpart update" );
						}
 
 
						// All the webparts found will need to be disposed
						toDispose.AddRange( previousWebparts );
 
						// We dispose everyone
						foreach ( var wp in toDispose )
							wp.Dispose();
					}
				} finally {
					if ( managerWeb != null && managerWeb != web )
						MemoryManagement.MightDispose( web );
				}
			} catch ( Exception ex ) {
				Logger.LogException( ex, "UpdateWebpartsInPage.TreatPage( SPFile.Url=\"{0}\" )", file.Url );
			}

Access your Google Latitude position from a .Net app

When I saw that Google Latitude now enables you to access your data by a JSON feed, I decided to make it communicate with a little GPS tracking project of mine.

I’m really found of all these ways we now have to make anything communicate with anything. You can build interfaces from any system to any other system really easily.

This code enables you to automatically get your GPS position (or the position of a friend) from your JSON Latitude feed. To be able to do that, you have to enable your KML/JSON feed.
It requires .Net 3.5′s System.Web.Extensions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Script.Serialization;
using System.Net;
using System.IO;
 
namespace LatitudeReader {
	class Program {
		static void Main() {
 
			Console.WriteLine( "What is your user id ?" );
 
			var userId = Console.ReadLine();
 
			if ( userId == String.Empty )
				userId = "5616045291659744796";
 
			// Url of the JSON Latitude feed
			var url = String.Format( "http://www.google.com/latitude/apps/badge/api?user={0}&type=json", userId );
 
			// We download the file
			var ms = new MemoryStream();
			Download( url, ms );
 
			// JSON in text format
			var textContent = UTF8Encoding.UTF8.GetString( ms.ToArray() );
 
			// We convert the JSON text file to an object
			// It returns 
			var jss = new JavaScriptSerializer();
			var jsonContent = jss.DeserializeObject( textContent ) as Dictionary<String, Object>;
 
			// We get the data
			var features = ( jsonContent[ "features" ] as object[] )[ 0 ] as Dictionary<string, object>;
			var geometry = features[ "geometry" ] as Dictionary<string, object>;
			var coordinates = geometry[ "coordinates" ] as object[];
			var lon = coordinates[ 0 ] as decimal?;
			var lat = coordinates[ 1 ] as decimal?;
 
			// And then the timestamp
			var properties = features[ "properties" ] as Dictionary<string, object>;
			var date = ConvertFromUnixTimestamp( (double) (int) properties[ "timeStamp" ] );
 
			// We convert the UTC date to local time
			date = date.ToLocalTime();
 
			Console.WriteLine( "{0} : {1} x {2}", date, lat, lon );
		}
 
		public static DateTime ConvertFromUnixTimestamp( double timestamp ) {
			DateTime origin = new DateTime( 1970, 1, 1, 0, 0, 0, 0 );
			return origin.AddSeconds( timestamp );
		}
 
		private const int BUFFER_SIZE = 1024;
 
		private static void Download( string url, Stream writeStream ) {
			var request = (HttpWebRequest) WebRequest.Create( url );
			var response = request.GetResponse();
 
			var readStream = response.GetResponseStream();
 
			var data = new Byte[ BUFFER_SIZE ];
 
			int n;
			do {
				n = readStream.Read( data, 0, BUFFER_SIZE );
				writeStream.Write( data, 0, n );
			} while ( n > 0 );
 
			writeStream.Flush();
			readStream.Close();
		}
	}
}

The only references you need are : System and System.Web.Extensions

NetEventServer

I talked some time ago about a library I made to take advantage of the kernel network events. I now release it and explain how to use it. It can help people to do some little network softwares without knowing where to start from.

I built it for network servers made to communicate with remotely connected embedded chips. I wanted to be able to always stay in touch with a huge number of chips without any real cost. So, my very personal goal was to built a server network layer for massive M2M applications.
I also made a little web server with it supporting Keep-Alive and partial file download (wit the “Range” header) and an other little library to send serialized objects.

I made this little network library to accomplish two main goals :

  • Simplify network server development
  • Be able to support a lot of connections

It is actually able to support a lot of connections : On a little Linux server using Mono (with 512 MB memory with swap deactivated), I easily managed to listen to 60 000 simultaneous connections without consuming more than 40% of the server’s memory.

And it allows to create network servers in only few line of code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Collections.Generic;
using System.Text;
using SoftIngenia.NetEventServer;
 
namespace TestServer {
 
	/// <summary>
	/// My little server
	/// </summary>
	class MyServer {
 
		public static String BytesToString( Byte[] data ) {
			var sb = new StringBuilder();
			sb.Append( String.Format( "[ {0} ] {{ ", data.Length ) );
			for ( int i = 0; i < data.Length; ++i )
				sb.Append( String.Format( " 0x{0:X02}", data[ i ] ) );
			sb.Append( " }" );
			return sb.ToString();
		}
 
		/// <summary>
		/// My server view of the client
		/// </summary>
		class MyClient {
			public MyClient( uint id ) {
				Id = id;
			}
 
			public uint Id { get; private set; }
 
			public int NbMessagesReceived { get; set; }
 
			public void Treat( byte[] data ) {
				Console.WriteLine( "{0}.Treat( {1} );", this, BytesToString( data ) );
				NbMessagesReceived++;
			}
 
			public override string ToString() {
				return String.Format( "Client{{Id={0}}}", Id );
			}
		}
 
		private readonly TcpEventServer _server;
		private readonly Dictionary<uint, MyClient> _clients = new Dictionary<uint, MyClient>();
 
		public MyServer( int portNumber ) {
			_server = new TcpEventServer( portNumber );
			_server.ClientConnected += server_ClientConnected;
			_server.ClientDisconnected += server_ClientDisconnected;
			_server.BinaryDataReceivedFromClient += server_BinaryDataReceivedFromClient;
		}
 
		public void StartListening() {
			_server.StartListening();
		}
 
		void server_BinaryDataReceivedFromClient( uint clientId, byte[] data ) {
			_clients[ clientId ].Treat( data );
		}
 
		void server_ClientDisconnected( uint clientId ) {
			Console.WriteLine( "Client {0} disconnected !", clientId );
			_clients.Remove( clientId );
		}
 
		void server_ClientConnected( uint clientId ) {
			Console.WriteLine( "Client {0} connected from {1} !", clientId, _server.RemoteEndPoint( clientId ) );
			_clients.Add( clientId, new MyClient( clientId ) );
		}
 
 
	}
 
	class Program {
		static void Main() {
			var myserver = new MyServer( 3000 );
			myserver.StartListening();
 
			Console.WriteLine( "Listening..." );
			Console.ReadLine();
		}
	}
}

This app launched gives you something like that :

1
2
3
4
5
Listening...
Client 1 connected from 127.0.0.1:53792 !
Client{Id=1}.Treat( [ 5 ] { 0x68 0x65 0x6C 0x6C 0x6F } ); // "hello"
Client{Id=1}.Treat( [ 2 ] { 0x0D 0x0A } ); // '<CR>' '<LF>'
Client 1 disconnected !

The library also enables you to receive data as text. You just have to subscribe to the “ReceivedLine” event. There’s no performance cost if you don’t subscribe to the event.

For network server, you still need to do some frame recognition. I usually instantiate a FrameParsing class into every client on the server side.

You can download the NetEventServer library with its XML and PDB files.

Posted in English. Tags: , , , . No Comments »

C# 4.0

I tested it in VS2010. Which is beautiful by the way, I like the WPF rendering. And I’m happy they didn’t disable the possibility to generate .Net 2.0 assemblies. I wanted to test the new historical debugger functionnality, which enable you to see the state of variable in the past time, but I didn’t take the Team System Edition (and I’m too lazy to download it again).

named and optionnal arguments
I’m so happy Microsoft has created optional and named arguments for method calls. It avoids a lot of stupid method overload. And I just can’t way to be using it in my code.

This is also a good news for people using Interop methods, like the one for Word 2007. I’ve seen a code using them, it looks like that :

1
2
3
object nullObj = null;
object name = "doc.docx";
officeClass.SaveAsWord2007Document( ref name, ref nullObj, ref nullObj, ref nullObj, ref nullObj, ref nullObj, ref nullObj, ref nullObj, ref nullObj, ref nullObj, ref nullObj, ref nullObj, ref nullObj );

With C# 4.0, it could be translated to something like that :

1
officeClass.SaveAsWord2007Document( "doc.docx" );

The C# 4.0 will convert it to exactly the same IL code internally (creating a refNullObj).

But it’s still just a little COM+ specific feature, you can’t use in Mono/Linux for instance. So I don’t think we can consider it as a real language feature.

DLR
I tested DLR with the “dynamic” type, I think it should only be used when we have no other choice (when we want to communicate with some scripting languages for instance). One reason is that it breaks the VS auto-completion, it’s like you were typing your code in notepad. The other reason is that, from my test, dynamic calls are 3 times slower to execute than compiled calls :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
static void Main() {
	int nb = 100000000;
 
	Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;
 
	TimeSpan without, with;
 
	{ // Without dynamics
		Console.WriteLine( "Without dynamics..." );
 
		var c = new Clacla();
 
		var start = DateTime.Now;
		for ( int i = 0; i < nb; ++i ) {
			c.DoSomething();
		}
		without = DateTime.Now - start;
		Console.WriteLine( "Elapsed time : {0}", without );
	}
 
	{ // With dynamics
		Console.WriteLine( "With dynamics..." );
 
		dynamic d = new Clacla();
 
		var start = DateTime.Now;
		for ( int i = 0; i < nb; ++i ) {
			d.DoSomething();
		}
 
		with = DateTime.Now - start;
		Console.WriteLine( "Elapsed time : {0}", with );
	}
 
	Console.WriteLine( "Dynamics call are {0} times slower.", Math.Round( (double) with.Ticks / without.Ticks, 2 ) );
 
	Console.ReadLine();
}

The Clacla class is a totally useless class :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Clacla {
	private string _s;
	private int _x, _y;
	private dynamic _d;
 
	public Clacla( int x = 1, int y = 2, string s = "", dynamic d = null ) {
		_x = x;
		_y = y;
		_s = s;
		_d = d;
	}
 
	public int DoSomething() {
		return (int) Math.Pow( X, 2 ) + Y;
	}
 
	public int X { get { return _x; } }
 
	public int Y { get { return _y; } }
 
	public string S { get { return _s; } }
 
	public dynamic D { get { return _d; } }
 
	public override string ToString() {
		return String.Format( "X={0}, Y={1}, S={2}, D={3}", _x, _y, _s, _d );
	}
}

The result is :

1
2
3
4
5
Without dynamics...
Elapsed time : 00:00:14.7285156
With dynamics...
Elapsed time : 00:00:39.8613281
Dynamics call are 2,71 times slower.

Covariance / Contravariance

It will simplify things for sure but I’m a little disappointed by the remaining restrictions.

The best explanation I could find on it so far is here.

C# + IL
I think Microsoft really had a great idea when they created their “Intermediate Language” to split the language from the managed library. Because if Sun had done the same thing you would be able to use enums (which is just an “int” internally) in an “old” 1.4 JRE.
With C# 4.0, you can still code for “old” .Net 2.0 environnements.

Sharepoint : The 0×80020009 (DISP_E_EXCEPTION) error

If you’re faced with that error, you should know that it doesn’t mean anything except you have a problem. Lots of people have written posts about it, but most of their explanations are wrong. It just means that sharepoint didn’t like what you did somewhere in your masterpage, your page, your webpart, your user control or anything else.

For me, it was because I used the SPWeb.GetListFromUrl method to test if the user actually had access to a list. If it didn’t, I was just catching the exception thrown.

The problem is, sharepoint never behaves like it should. As soon as Sharepoint has thrown the Exception, I couldn’t save any parameters of the webpart.

By the way, I corrected my webpart by checking available lists in the SPWeb.Lists property.

Lighttpd + Mono ASP.Net : The right configuration

As I already told before, I love the Mono project. It enables to run the powerful Microsoft .Net Framework on UNIX/Linux/BSD systems.

I recently wanted to test a very cool feature of ASP.Net on a mono server. So I did a little

1
apt-get install lighttpd mono-fastcgi-server2 -y

The feature I wanted to try was a web scripting method ( with the “[WebMethod]” attribute) exporting some JSON directly from your method return value.

Here is the web scripting method declaration :

1
2
3
4
5
6
7
8
9
10
 
[ScriptService]
public partial class _Default:Page {
 
	[WebMethod]
	[ScriptMethod( ResponseFormat = ResponseFormat.Json, UseHttpGet = false )]
	public static String TestMethod() {
		return DateTime.Now.ToString();
	}
}

And here is the javascript / JQuery code that gets the data :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div id="toto"></div>
 
<script type="text/javascript">
    function doIt() {
        $(document).ready(function() {
            $.ajax({
                type: "POST",
                url: "/Default.aspx/TestMethod",
                contentType: "application/json; charset=utf-8",
                data: "{}",
                dataType: "json",
                success: AjaxSucceeded,
                error: AjaxFailed
            });
        });
        function AjaxSucceeded(result) {
            document.getElementById("toto").innerHTML = result.d;
        }
        function AjaxFailed(result) {
           document.getElementById("toto").innerHTML = "Error : "+result.status + ' ' + result.statusText;
        }
        setTimeout("doIt()", 1000);
    }
    doIt();
 
</script>

In my /etc/lighttpd/conf-enabled/10-fastcgi.conf file, I had this :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server.modules   += ( "mod_fastcgi" )
fastcgi.server    = (
        "" => ((
                "socket" => mono_shared_dir + "fastcgi-mono-server",
                "bin-path" => mono_fastcgi_server,
                "bin-environment" => (
                        "PATH" => "/bin:/usr/bin:" + mono_dir + "bin",
                        "LD_LIBRARY_PATH" => mono_dir + "lib:",
                        "MONO_SHARED_DIR" => mono_shared_dir,
                        "MONO_FCGI_LOGLEVELS" => "Standard",
                        "MONO_FCGI_LOGFILE" => "/var/log/lighttpd/mono.log",
                        "MONO_FCGI_ROOT" => mono_fcgi_root,
                        "MONO_FCGI_APPLICATIONS" => mono_fcgi_applications
                ),
                "max-procs" => 1,
                "check-local" => "disable"
        ))
)

Everytime I launched a call from javascript, I got (with JS) I got a “405 Method not allowed”. Well, that was pretty disturbing. Mostly because a google search on this didn’t give me anything.
My first thought was that mono didn’t react the same way the .Net framework does. But this isn’t it. It came from my crappy lighttpd config file. It didn’t search for the Default.aspx file but for the Default.aspx/TesMethod.
What you need to do is set :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fastcgi.server    = (
        ".aspx" => ((
            # Everything you have in your file (like my file above)
        )
 
fastcgi.map-extensions = (
        ".asmx"   => ".aspx",
        ".ashx"   => ".aspx",
        ".asax"   => ".aspx",
        ".ascx"   => ".aspx",
        ".soap"   => ".aspx",
        ".rem"    => ".aspx",
        ".axd"    => ".aspx",
        ".cs"     => ".aspx",
        ".config" => ".aspx",
        ".dll"    => ".aspx"
)

And that will even improve your performances because any other file will be handled directly by lighttpd.

One quick note : There’s something weird with VS2008 WebDev.WebServer.Exe, the WebMethod request takes at least 1.0s to complete. On the same host with XSP, it’s around 15 ms. And on the Celeron 2.6Ghz linux server with lighttpd it’s around 12 ms. And on a IIS 7 server (bundled with Windows 7), it takes 12 ms. So why is the Visual Studio’s WebDev.WebServer so slow ?

By the way, why should we use a Linux + lighttpd + Mono server when we can use a Windows + IIS + ASP.Net server ? The reason is mainly that for the same usage, Linux consumes less resources and it’s easier to customize to suit your needs.

An other question you might have : Why use JQuery + JSON when you can use everything in the Microsoft AJAX Framework ? The main reason is that I really have the feeling to lose control with Microsoft AJAX Framework, I don’t like the huge automatically generated code. And it doesn’t make really fast web interfaces. With JQuery, everything goes faster and it’s way more simpler to understand (and debug).

Related :
- Using JQuery with ASP.Net

Sharepoint : What should I Dispose ?

When you begin with Sharepoint like it did (and still do), you will ask your self : “What object should I dispose ?”. It’s quite important because Sharepoint leaks approximatively 1 Mb per IDisposable object not disposed. If it’s a menu, it could quickly make you loose 10 Mb per loaded page.

The best and complete answer is in the MSDN. But it’s a pretty long answer.

The short answer is :
In your webpart, you should dispose every SPWeb and SPSite you use except :

  • SPContect.Current.Site
  • SPContext.Current.Web
  • SPContext.Current.Site.RootWeb

In your features, you should dispose every SPWeb and SPSite you use except the ones given in your “properties” variable.

The reason is that Sharepoint gives these objects to every component it will launch, if you dispose one of these objects, the next component loaded by sharepoint has a good chance to crash. And it’s not always easy to debug as it’s the NEXT component which will crash also it’s the previous one that messed up one of the sharepoint context variables.

If your not sure that you will Dispose an object you should, you shoud check. The following code Disposes the SPWeb passed as argument and every parent except the last one.

1
2
3
4
5
6
7
8
9
10
11
12
public static SPWeb SPWebParentWebGenerationDp( SPWeb web, int generation ) {
	for ( int i = 0; i < generation; ++i ) {
		SPWeb toDispose = web;
 
		if ( web != null )
			web = web.ParentWeb;
 
		if ( toDispose != null && toDispose != SPContext.Current.Web )
			toDispose.Dispose();
	}
	return web;
}