views:

26

answers:

1

I'm coding a business layer for an ASP.NET application. I've created database methods in my BLL as static. I've created public static Func variables to be compiled and used in several different methods, like this:

namespace BLL
public class User
{
    public static Func<Context, variable, result> selectUser;

    private static void CompileQuery()
    {
        if(selectUser == null)
        {
            selectUser = CompiledQuery.Compile......
        }
    }

    public static UserClass Select(int id)
    {
        CompileQuery();

        //uses selectUser
    }

    public static SomethingElse DoSomethingElse()
    {
        CompileQuery();

        //also uses selectUser
    }
}

It'll be used in ASP.NET layer like this:

using BLL;
private void AddUser()
{
    UserClass user = User.Select(id);
}

My question is, since static variables are not thread-safe, is this a bad design decision? I'm thinking of either implementing a locking mechanism, which makes me think if it'd slow down the application, or using instantiated class approach which makes me wonder if query compiling would be beneficial. I'd appreciate any advice on this.

+3  A: 

It should at least be read-only - and initialized on type load, like this:

public static readonly Func<Context, variable, result> selectUser = 
     CompileQuery(); // Or inline this...

private static Func<Context, variable, result> CompileQuery()
{
    return CompiledQuery.Compile(...);
}

I'd probably make it a property myself, but otherwise it should be okay. Delegates themselves are immutable and threadsafe, so that shouldn't be a problem.

Doing it on type initialization means you don't need to worry about locking: the CLR guarantees that a type initializer is executed once and only once.

Jon Skeet
Does the CLR not guarantee that with static constructors? I always assumed a static constructor could only be called once per application domain.
Nathan Ridley
@Nathan: Yes, a static constructor is part of the type initializer - except that a class with a static constructor has stricter timing guarantees. We certainly *could* use a static constructor here.
Jon Skeet