Notes from Daily Encounters with Technology RSS 2.0
 
# Saturday, January 14, 2012

NuGet is a valuable tool for managing references to external libraries in your projects. If you’re not using it yet, you owe it to yourself to try it out and see what you’re missing. Though, that’s not what this post is about. Not only are NuGet packages a great way to distribute publically available libraries, they can be used just as well for custom internal libraries with their own release management which are used in multiple projects. Since there’s a lot of information already available on this topic, instead of repeating it I’ll rather link to it from one place and add a few helpful hints and tricks along the way.

The first step is to create a NuGet package from your library. To do it you need NuGet.exe, it’s not enough to have NuGet Package Manager Visual Studio extension installed, neither is that necessary when this step is being done on your build server. Although it is possible to create a package directly from a Visual Studio project, I strongly suggest to put in a little extra effort from the beginning and use a convention based working directory instead. It gives you many more options which you’re going to miss very soon if you do it the easy way. Don’t forget to set the correct version in the manifest file during each build -  it is only done automatically for you when using a project file as the source. This short NAnt task should do the trick (CCNetLabel property contains the desired version since this is being built with CruiseControl.NET):

<xmlpoke file="MyLibrary.nuspec"
         xpath="package/metadata/version"
         value="${CCNetLabel}" />

Once *.nupkg files are being generated on every build of the library, it’s time to set up an internal feed to distribute them. While it is possible to host a proper feed in IIS, a poor man’s version in the form of a file share will work just as well. Just create a shared folder somewhere on your network (e.g. \\buildserver\NuGet) and copy every generated package file into it. Now you can instruct your developers to add this feed to their NuGet configuration and they can start referencing your libraries the same way they are already used to with libraries from the official NuGet gallery:

NuGet Package Manager Package Sources Settings

You could already stop at this point but I’m convinced that you should go one step further and take care of package restore to avoid putting the libraries in your source control system. There are only three easy steps to follow:

  • Open Package Manager Console Window (Tools > Library Package Manager > Package Manager Console menu item in Visual Studio with NuGet Package Manager installed).
  • Run the following commands:
Install-Package NuGetPowerTools
Enable-PackageRestore
  • Instead of the packages folder put the .nuget folder into source control (both are inside the solution folder).

Once this is done, NuGet will always make sure the correct versions of all the packages are present locally before the build starts. There’s even no need to have NuGet Package Manager installed for this to work. There’s only one more change required to make this work flawlessly with the internal feed that we have set up. Open up the NuGet.targets file in the generated .nuget folder and add this feed to the PackageSources property group:

<PackageSources>\\buildserver\NuGet -source https://go.microsoft.com/fwlink/?LinkID=230477</PackageSources>

Without this modification the package won’t be found if NuGet is not properly configured for the user the build is running under (the package sources configuration is stored in %APPDATA%\NuGet\NuGet.config). The second feed in my case is the official one which you should always add as well so that the public libraries can still be found.

Saturday, January 14, 2012 5:30:40 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | NAnt | NuGet | Software | VisualStudio
# Sunday, January 08, 2012

Web.config transformations are a great but often overlooked feature introduced with ASP.NET 4.0. They provide a simple way to define a different configuration for Debug and Release builds of your project by only specifying the differences (typically only connection strings and similar settings) in a separate transformation file while keeping the core of the configuration file common and consequentially making it easier to manage.

Unfortunately files aren’t transformed until the web deployment package is created, i.e. they aren’t part of the core build process. This makes the transformations more difficult to use in some scenarios such as having a different configuration file for automated testing as a part of the build process.

Since the transformation is done by the TransformXml MSBuild task in Microsoft.Web.Publishing.Tasks.dll assembly there is a way to make this work by modifying the project file manually, though. Here is a snippet that I added to my project file (line break in the AssemblyFile added for readability only):

<UsingTask TaskName="TransformXml" 
           AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\
                         v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild">
    <MakeDir Directories="obj\$(Configuration)" 
             Condition="!Exists('obj\$(Configuration)')" />
    <TransformXml Source="Web.Config" 
                  Transform="Web.$(Configuration).config" 
                  Destination="obj\$(Configuration)\Web.config" 
                  StackTrace="true" 
                  Condition="Exists('Web.$(Configuration).config')" />
</Target>

As you can see the transformed configuration file is put inside the obj folder from where I copy it to the desired final location before running the tests. I find this a suitable spot for it unless you are precompiling views in your ASP.NET MVC project. A web.config file anywhere in obj folder brakes the build so you’ll have to put the file elsewhere or make sure you delete it before precompiling the views.

If you want to make this work on your build server without having Visual Studio installed on it, there is one more step remaining. The above mentioned assembly is not installed with .NET SDK meaning that you have to copy it there from your development machine. The file is located in the MSBuild extension folder, i.e. “C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\” by default.

Transformation files displayed under the original fileThis takes care of transforming web.config files during build. How about transforming app.config files and even other XML files in your projects? I guess it would be possible to use the same MSBuild task on them but no Visual Studio support for transforming those files would mean even more tempering with project files to make transformation files appear under the file they are used to transform.

This is where SlowCheetah – XML Transforms Visual Studio extension can help. After installing it you can define transformations for app.config the same way you are already doing it with web.config files. The transformation is part of the build process in this case, i.e. the transformed file is put in its usual spot in the build output folder (usually bin) instead of the original one. It couldn’t get any simpler.

As an added bonus the extension features support for previewing the results of the transformation: after right clicking the transformation file and selecting the Preview Transform command a diff window will open graphically showing the differences between the original and the transformed file. Of course this works with web.config transformations as well making the debugging of transformations much simpler. A good reason in itself to install this extension.

To avoid failed builds on your build server as well as with the other members of your team not having this extension installed it’s best that you copy the SlowCheetah MSBuild targets and the corresponding assembly containing the tasks to your solution directory and put it in source control. In this case you’ll again have to modify the project file to set the new path. Just search for the SlowCheetahTargets property definition and modify the path accordingly (line breaks added for readability):

<PropertyGroup>
    <SlowCheetahTargets Condition=" '$(SlowCheetahTargets)'=='' ">
        ..\_References\SlowCheetah\SlowCheetah.Transforms.targets
    </SlowCheetahTargets>
</PropertyGroup>

Are there any ways to make your life simpler by using configuration transformations in your projects?

Sunday, January 08, 2012 12:34:56 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | ASP.NET | Software | VisualStudio
# Monday, December 26, 2011

DateTime can be a tricky data type to deal with. Not only is there daylight saving time and different time zones to keep in mind but also the range and precision can vary in different systems. You are probably already aware of some differences between .NET framework’s DateTime structure in Transact-SQL’s datetime data type.

Most notable is certainly a different minimum value that can be expressed:

  • In .NET framework all values between January 1st 1 and December 31st 9999 are supported.
  • In Transact-SQL only values between January 1st 1753 and December 31st 9999 are supported.

This usually shouldn’t be a problem unless you are working with historic data. Setting proper minimum value in the user interface is not be a bad idea nevertheless.

You might not be aware of the difference in precision between these two data types, though. In some edge cases this can cause strange and unpredictable behavior. Let’s take a look at the following example (based on an issue that had me mystified for some time):

using (var context = new TestEntities())
{
    var task = context.Tasks.Single(t => t.Id == taskId);
    task.CompletedAt = DateTime.Now;
    timestamp = task.CompletedAt.Value;
    context.SaveChanges();
}

using (var context = new TestEntities())
{
    var task = context.Tasks.Single(t => t.Id == taskId);
    Assert.GreaterOrEqual(timestamp, task.CompletedAt);
}

The assertion in the above code will occasionally fail with a message similar to this one:

SampleTest has failed:
  Expected: greater than or equal to 2011-12-26 19:04:28.313
  But was:  2011-12-26 19:04:28.312

If you’re not familiar with entity framework, here’s what’s going on:

  • In the first code block a DateTime value is stored to the database.
  • In the second code block that same value is reloaded from the database.
  • The value from the database is compared with the one stored in a local variable the whole time.

The strange behavior is caused by the fact that milliseconds get rounded in the database: to increments of .000, .003, or .007 seconds, as it is stated in the documentation. The DateTime value can therefore be different when reloaded from the database, hence the occasional failed assertion. While the problem might be fairly obvious in the simplified example above, it can be much more difficult to pinpoint in a larger chunk of code where there could be other reasons for the values to differ. Even more so if you’re not even aware of the rounding.

Knowing this might save you a couple of hours once.

Monday, December 26, 2011 7:28:18 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | SQL
# Monday, December 19, 2011

In a previous post I addressed the issue of using HTTP module based authentication in WCF. The presented solution worked in most cases but failed completely with Windows authentication. In this post I’ll describe the necessary changes to make this work as well.

Let’s first see what goes wrong with the existing solution and why. To configure WCF for Windows authentication, the following changes are required in web.config:

<system.serviceModel>
    <!-- ... -->
    <bindings>
        <basicHttpBinding>
            <binding name="HttpWindowsBinding" 
                     maxReceivedMessageSize="2147483647">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Windows" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <services>
        <service name="WcfAuthentication.Service">
            <endpoint address="windows"
                      binding="basicHttpBinding"
                      bindingConfiguration="HttpWindowsBinding"
                      contract="WcfAuthentication.IService" />
        </service>
    </services>
</system.serviceModel>

Of course the settings have to be matched in IIS: Windows authentication should be enabled for the application while anonymous authentication should be disabled, as well as all the other types of authentication.

After setting all this up any calls to our service will throw a MessageSecurityException: "The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'." If you try searching the web for solutions, you’ll notice the same error pops up in many different situations not related to our case. So what’s going on here?

The problem is being caused by the following method in HttpAuthenticationModule:

void context_AuthenticateRequest(object sender, EventArgs e)
{
    HttpContext.Current.User = ProcessAuthentication();
}

Setting the user in the current HttpContext to a custom IPrincipal implementation confuses WCF which expects a WindowsPrincipal as configured. The only way to make it work is to pass through the original user information in this case:

void context_AuthenticateRequest(object sender, EventArgs e)
{
    if (!(HttpContext.Current.User is WindowsPrincipal) && 
        HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.EndsWith(".svc"))
        HttpContext.Current.User = ProcessAuthentication();
}

The extension based filtering is there so that the authentication will still work for the rest of our web application. This change alone is not enough, of course. We still to need the authentication somewhere for the WCF case. HttpContextAuthorizationPolicy is the right spot for it. Evaluate method should be modified as follows:

public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
    HttpContext context = HttpContext.Current;

    if (context != null)
    {
        if (context.User is WindowsPrincipal)
        {
            IPrincipal principal = HttpAuthenticationModule.ProcessAuthentication();
            evaluationContext.Properties["Principal"] = principal;
            evaluationContext.Properties["Identities"] = new List<IIdentity> { principal.Identity };
        }
        else
        {
            evaluationContext.Properties["Principal"] = context.User;
            evaluationContext.Properties["Identities"] = new List<IIdentity> { context.User.Identity };
        }
    }

    return true;
}

Keep in mind that calling a static method in HttpAuthenticationModule to authenticate the user is just a shortcut to make this sample work and is not suggested practice. In production code you’ll want to have your authentication logic implemented somewhere in the business layer and call it from both HttpAuthenticationModule and HttpContextAuthorizationPolicy.

Monday, December 19, 2011 9:12:16 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | ASP.NET | WCF
# Monday, December 12, 2011

WCF has great built-in support for most types of authentication so there aren’t many good reasons to use HTTP module based authentication with it. Having an existing ASP.NET application already using such authentication certainly is one of them. Finding resources on how to do it might be a challenge though. I managed to stumble upon an article by Microsoft patterns & practices team which helped a lot. In a way this post is its abridged and more practical version.

From here on I assume you already have an IHttpModule in your application (ProcessAuthentication() being the method implementing the actual authentication of the user):

public class HttpAuthenticationModule : IHttpModule
{
    public void Dispose()
    { }

    public void Init(HttpApplication context)
    {
        context.AuthenticateRequest += context_AuthenticateRequest;
    }

    void context_AuthenticateRequest(object sender, EventArgs e)
    {
        HttpContext.Current.User = ProcessAuthentication();
    }

    private static IPrincipal ProcessAuthentication()
    {
        // implement your authentication here
        IIdentity identity = new GenericIdentity("Authenticated User");
        return new GenericPrincipal(identity), null);
    }
}

The module should also already be registered in web.config:

<system.web>
    <!-- ... -->
    <httpModules>
        <add name="HttpAuthenticationModule" 
             type="WcfAuthentication.HttpAuthenticationModule"/>
    </httpModules>
</system.web>

The goal is of course getting access to the authenticated user (i.e. IPrincipal instance) in WCF service through ServiceSecurityContext. The following test method is a great way for testing that:
public string GetUser()
{
    if (ServiceSecurityContext.Current != null)
        return ServiceSecurityContext.Current.PrimaryIdentity.Name;
    else
        return null;
}

IAuthorizationPolicy is the interface to implement custom authorization in WCF with. In our case the authenticated user can be accessed through current HttpContext:

public class HttpContextAuthorizationPolicy : IAuthorizationPolicy
{
    public bool Evaluate(EvaluationContext evaluationContext, ref object state)
    {
        HttpContext context = HttpContext.Current;

        if (context != null)
        {
            evaluationContext.Properties["Principal"] = context.User;
            evaluationContext.Properties["Identities"] = new List<IIdentity>() { context.User.Identity };
        }

        return true;
    }

    public System.IdentityModel.Claims.ClaimSet Issuer
    {
        get { return ClaimSet.System; }
    }

    public string Id
    {
        get { return "HttpContextAuthorizationPolicy"; }
    }
}

Of course the class should be registered in web.config so that our service will use it:

<system.serviceModel>
    <!-- ... -->
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <!-- ... -->
                <serviceAuthorization>
                    <authorizationPolicies>
                        <add policyType="
                             WcfAuthentication.HttpContextAuthorizationPolicy, 
                             WcfAuthentication, Version=1.0.0.0, 
                             Culture=neutral, PublicKeyToken=null"/>
                    </authorizationPolicies>
                </serviceAuthorization>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

There is still one thing missing. If you try out the above code, you will realize that HttpContext.Current is always null even if authorization in our HTTP module was successful. To get access to it you need to enable ASP.NET compatibility:

<system.serviceModel>
    <!-- ... -->
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" 
                               aspNetCompatibilityEnabled="true"/>
</system.serviceModel>

To make your WCF service work in this mode you need decorate it with AspNetCompatibilityRequirementsAttribute:

[AspNetCompatibilityRequirements(RequirementsMode = 
    AspNetCompatibilityRequirementsMode.Allowed)]
public class Service : IService
{
    // ...
}

Finally, we’re done. If you’ve implemented all of the above correctly, our test method GetUser() should return the user who was authenticated in the HTTP module. Unless you’re trying to use Windows authentication which still doesn’t work in this setup. That’s already a subject for another post, though.

Monday, December 12, 2011 9:29:48 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | ASP.NET | WCF
# Thursday, December 01, 2011

DefaultModelBinder is an essential piece of ASP.NET MVC framework which makes writing strongly typed actions really simple. In spite of its strengths (or maybe because of them) it can still introduce hard to solve problems in your code. Take a look at the following example, a simplification of the problem I was confronted with today:

public class DocumentVersion
{
    public int Id { get; set; }
    public int Version { get; set; }
    public string Name { get; set; }
}

public class DocumentController : Controller
{
    public ActionResult New()
    {
        return View();
    }

    public ActionResult Save(DocumentVersion version)
    {
        if (ModelState.IsValid)
        {
            // save data
            return View("Confirm");
        }
        return View("New");
    }
}

Assuming all DocumentVersion properties are submitted and valid Save action should return Confirm view, right? Wrong! Try it out and you’ll get a validation error on Version property. Taking a closer look it turns out ModelState["Version"].Errors[0].Exception contains an InvalidOperationException: "The parameter conversion from type 'System.String' to type 'MvcApplication1.Models.DocumentVersion' failed because no type converter can convert between these types." Of course there’s no String to DocumentVersion converter. Though, Version property is an int. Why does it want to convert it to a DocumentVersion?

I soon started running out of ideas and fortunately enough I quickly decided to enable .NET Framework source stepping. A few moments later I reached the following piece of code in DefaultModelBinder and suddenly it became obvious what was happening:

if (!String.IsNullOrEmpty(bindingContext.ModelName)
        && !bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) {
    // We couldn't find any entry that began with the prefix. If this is the top-level element, fall back
    // to the empty prefix.
    if (bindingContext.FallbackToEmptyPrefix) { 
        bindingContext = new ModelBindingContext() {
            ModelMetadata = bindingContext.ModelMetadata, 
            ModelState = bindingContext.ModelState, 
            PropertyFilter = bindingContext.PropertyFilter,
            ValueProvider = bindingContext.ValueProvider 
        };
        performedFallback = true;
    }
    else { 
        return null;
    } 
} 

// Simple model = int, string, etc.; determined by calling TypeConverter.CanConvertFrom(typeof(string)) 
// or by seeing if a value in the request exactly matches the name of the model we're binding.
// Complex type = everything else.
if (!performedFallback) {
    bool performRequestValidation = ShouldPerformRequestValidation(controllerContext, bindingContext); 
    ValueProviderResult vpResult = 
        bindingContext.UnvalidatedValueProvider
                      .GetValue(bindingContext.ModelName, skipValidation: !performRequestValidation);
    if (vpResult != null) { 
        return BindSimpleModel(controllerContext, bindingContext, vpResult); 
    }
} 

Notice the call to bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName) at the top and read the comment above the bottom block of the code. It turns out that in my sample ModelName Was "version" just like one of the DocumentVersion properties therefore DefaultModelBinder decided to use simple model binding which failed because of a missing converter as it was also clearly stated in the exception. You might be wondering where ModelName came from. It’s the name of the action method parameter. Fixing the code was simple now – rename the parameter and the code starts working as expected:

public ActionResult Save(DocumentVersion documentVersion)
{
    if (ModelState.IsValid)
    {
        // save data
        return View("Confirm");
    }
    return View("New");
}

Lesson of the day? Be aware of conventions and make sure parameter names don’t match any of the property names if you are using complex models.

Thursday, December 01, 2011 9:42:37 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | ASP.NET MVC
# Sunday, October 02, 2011

This year’s Bleeding Edge conference was taking place this week in the beautiful surroundings of Gozd Martuljek. The second day was dedicated to community driven redelivery of Build. As the last session of the day I had a talk on the aspects of reusing existing .NET framework code in Metro applications for Windows 8. I’ve based the contents of the talk on the following Build sessions:

The slides from my talk are available on SlideShare. Here are the sources for the sample Windows runtime component I've created during the talk.


Sunday, October 02, 2011 8:34:40 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | Metro | Downloads | Presentations | Sources
# Sunday, July 24, 2011

Reflection is a great tool for calling methods on objects when their types are not known at compile time. Unfortunately the Type.GetMethod method doesn’t work with generic methods therefore we seem to be stuck with finding the right method by iterating through all the methods returned by Type.GetMethods:

public static MethodInfo GetMethodWithLinq(this Type staticType, string methodName, params Type[] paramTypes)
{
    var methods = from method in staticType.GetMethods()
                  where method.Name == methodName
                        && method.GetParameters()
                                  .Select(parameter => parameter.ParameterType)
                                  .Select(type => type.IsGenericType ? type.GetGenericTypeDefinition() : type)
                                  .SequenceEqual(paramTypes)
                  select method;
    try
    {
        return methods.SingleOrDefault();
    }
    catch (InvalidOperationException)
    {
        throw new AmbiguousMatchException();
    }
}

Searching for alternatives I stumbled upon a solution using expression trees posted by Neil Whitaker on StackOverflow:

private static MethodInfo GetMethodWithExpressions(Type innerType)
{
    var method = typeof(Program).GetMethod("GetSingleOrDefaultMethod", 
                                           BindingFlags.Static | BindingFlags.NonPublic, 
                                           null, Type.EmptyTypes, null)
                                .MakeGenericMethod(innerType);
    return method.Invoke(null, new object[] { }) as MethodInfo;
}

private static MethodInfo GetSingleOrDefaultMethod<TSource>()
{
    Expression<Func<TSource, bool>> fakePredicate = i => true;
    Expression<Func<IQueryable<TSource>, TSource>> lambda = l => l.SingleOrDefault(fakePredicate);

    return (lambda.Body as MethodCallExpression).Method;
}

Sure, it is more difficult to comprehend and a lot less flexible, requiring a helper method building the expression tree for every method to be returned as MethodInfo. It got me wondering though, which of the two solutions actually performs better. Let’s try them out:

static void Main(string[] args)
{
    MethodInfo method;
    Type innerType = typeof(string);

    int count = 10000;
    Stopwatch stopwatch = new Stopwatch();

    stopwatch.Restart();
    for (int i = 0; i < count; i++)
    {
        method = typeof(Queryable).GetMethodWithLinq("SingleOrDefault", typeof(IQueryable<>), typeof(Expression<>))
                                  .MakeGenericMethod(innerType);
    }
    stopwatch.Stop();
    Console.WriteLine(String.Format("Method 1: {0}", stopwatch.ElapsedMilliseconds));

    stopwatch.Restart();
    for (int i = 0; i < count; i++)
    {
        method = GetMethodWithExpressions(innerType);
    }
    stopwatch.Stop();
    Console.WriteLine(String.Format("Method 2: {0}", stopwatch.ElapsedMilliseconds));

    Console.ReadLine();
}

And the results?

Method 1: 224
Method 2: 396

Not only is the Type.GetMethods based approach simpler, it also consistently performs a lot better. We’ll just stick with it until support for generic methods is added to Type.GetMethod.

Sunday, July 24, 2011 10:31:43 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | C#
# Sunday, June 12, 2011

XmlSerializer is often a great choice for persisting objects or transmitting them over the wire, either by using default object serialization tailored only with attributes or by implementing the IXmlSerializable interface yourself. If you’re not careful though, this might come at a significant performance cost.

You’re probably already aware that in order to increase performance of XML serialization, assemblies are dynamically generated each time XmlSerializer is instantiated for the first time for a specific type. Since it happens only once in the application lifetime, it usually doesn’t pose much of a problem.

What you might not know, is that this is not necessary a once in a lifetime process. If you’re using the wrong constructor, it can happen every time you instantiate XmlSerializer. To be fair, this is mentioned in the documentation, but if you’re like me, you might not read it until you encounter performance issues in your project. So unless you’re calling XmlSerializer(Type) or XmlSerializer(Type, String), the dynamically generated assemblies are not reused. When you think about it, it also makes perfect sense. All other constructors modify the behavior of the serializer, thus causing small differences in the generated serializers and hindering their reuse.

Fortunately there is a way to avoid this performance hit. Since XmlSerializer is one of the few thread safe classes in the framework you really only need a single instance of each serializer even in a multithreaded application. The only thing left for you to do, is to devise a way to always retrieve the same instance. If you know in advance which serializers you’ll need, you can simply store them in static fields. If you don’t, you’ll need to store them in a dictionary, keyed by the arguments used in the constructor.

Your best choice for the data structure is ConcurrentDictionary introduced in .NET 4 which takes care of synchronizing for multithreading. This makes the implementation really simple:

private static ConcurrentDictionary<Type, XmlSerializer> serializers = 
    new ConcurrentDictionary<Type, XmlSerializer>();

private XmlSerializer GetSerializer(Type type)
{
    return serializers.GetOrAdd(type, t => 
        { return new XmlSerializer(t, new XmlRootAttribute("Value")); });
}

If you’re wondering what kind of performance hit I’m talking about, try running the following sample:

static void Main(string[] args)
{
    StringWriter writer = new StringWriter();
    XmlTextWriter xmlWriter = new XmlTextWriter(writer);
    xmlWriter.WriteStartDocument();
    xmlWriter.WriteStartElement("Root");
    Stopwatch stopwatch = new Stopwatch();
    int iterations = 100;

    stopwatch.Restart();
    for (int i = 0; i < iterations; i++)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(string));
        serializer.Serialize(xmlWriter, "Test");
    }
    stopwatch.Stop();
    Console.WriteLine(
        "{0} serializations with XmlSerializer(string):                   {1,5} ms",
        iterations, stopwatch.ElapsedMilliseconds);

    stopwatch.Restart();
    for (int i = 0; i < iterations; i++)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(string), new XmlRootAttribute("Type"));
        serializer.Serialize(xmlWriter, "Test");
    }
    stopwatch.Stop();
    Console.WriteLine(
        "{0} serializations with XmlSerializer(string, XmlRootAttribute): {1,5} ms",
        iterations, stopwatch.ElapsedMilliseconds);

    XmlSerializer staticSerializer = new XmlSerializer(typeof(string), new XmlRootAttribute("Type"));
    stopwatch.Restart();
    for (int i = 0; i < iterations; i++)
    {
        staticSerializer.Serialize(xmlWriter, "Test");
    }
    stopwatch.Stop();
    Console.WriteLine(
        "{0} serializations with a static serializer:                     {1,5} ms",
        iterations, stopwatch.ElapsedMilliseconds);

    Console.ReadKey();
}

In my case the output was as follows:

100 serializations with XmlSerializer(string):                       2 ms
100 serializations with XmlSerializer(string, XmlRootAttribute): 17460 ms
100 serializations with a static serializer:                         2 ms

Quite a difference, isn’t it?

Sunday, June 12, 2011 4:55:48 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET
# Wednesday, June 08, 2011

One of the features introduced in Entity Framework 4 was support for foreign key properties in entity types. No matter what your opinion is about having foreign keys exposed by an ORM, there are some cases where it might be more practical or even more performant to use foreign key properties instead of navigation properties (e.g. when you are creating a new object with a reference for which you know the primary key value but don’t have a corresponding object in your ObjectContext). That’s the reason why it’s usually recommended to include foreign key columns in your model even though it will pollute your entity types with properties you might not need at all.

Update Wizard

But what if you decided not to include them in your model when you originally created it, but want to add them at a later time? Although the checkbox is enabled in the model Update Wizard which opens up when you want to Update Model from Database, its value only effects newly created entity types, but leaves existing entity types unchanged. Unless you feel comfortable deleting existing entity types and recreating them from database, you’ll have to add the properties by hand. Once you know how to do it, it’s just a matter of following a few simple steps. I’ll describe them on a simple example from Northwind database. I’ve only included three entity types: Category, Product and Supplier. We want to add CategoryID and SupplierID properties to the Product entity type.

Model without Foreign Key Properties

First add a new scalar property to the entity type:

  1. Right click on the Product entity type.
  2. Click on the Add > Scalar Property from the context menu.
  3. Click on the newly created Property and set its properties: Name to CategoryID, Nullable to True and Type to Int32.

CategoryID Properties Window

Next you need to map the database column to your new property:

  1. Open Mapping Details for Product entity type.
  2. Select the CategoryID : Int32 as Value / Property for the CategoryID : int column.

Product Mapping Details Window

Now it’s time to set up the referential constraint:

  1. Select the FK_Products_Categories association in the Model Browser.
  2. Open the Referential Constraint editor from its properties window.
  3. Select Category as Principal and CategoryID as Dependent Property.

Referential Constraint Editor

Only one step left, deleting the mapping of foreign key to the navigation property which is not allowed when you have a foreign key property in your entity type:

  1. Select the Category property of the Product entity type.
  2. Click on the Delete mappings link displayed in the Mapping Details window.

Category Mapping Details

You have to repeat the above steps for the SupplierID property and you have created a functionally identical model to the one automatically generated for you if you had selected to include foreign keys in the model before adding the tables to it.

Model with Foreign Key Properties

The above process is not only useful when you change your mind about the foreign key properties at a later time. You can also intentionally decide to add the foreign key properties only when you actually need them and avoid having redundant properties at the cost of the consistency of the model.

Wednesday, June 08, 2011 9:43:08 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | EF4
Page 1 of 6 in the Development category Next Page
Sponsored Ads

About Me
Twitter
@MladenPrajdic @andrejt use the middle mouse button then 2 days ago
Great #DotNetRocks show: Troy Hunt Secures http://t.co/oxClbXLe http://t.co/MiMasNuZ PDF is worth checking out as well http://t.co/z4BHAzqh 3 days ago
Hazards of Converting Binary Data To A String http://t.co/lb8kRSsU via @haacked 5 days ago
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

All Content © 2012, Damir Arh, M. Sc. Send mail to the author(s) - Privacy Policy - Sign In
Based on DasBlog theme 'Business' created by Christoph De Baene (delarou)
Social Network Icon Pack by Komodo Media, Rogie King is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.