Thursday, July 25, 2013

SetSite failed for package [Microsoft.VisualStudio.Editor.Implementation.EditorPackage]



After the 07/10/2013 Microsoft update, VS 2012 doesn't want to work. It throws exceptions that can be visible under:
C:\Users\[user]\AppData\Roaming\Microsoft\VisualStudio\11.0\ActivityLog.xml

In order to fix the issue one needs to clear the VS cache under:
%LOCALAPPDATA%\Microsoft\VisualStudio\11.0\ComponentModelCache

Decimal and Double once again

Yesterday I had a discussion with my co-worker about primitive types, I suggested that he should use decimal instead of double otherwise results of his computation may be misleading/incorrect. It is a booking applications and showing a correct prize (fee, cost) is crucial. His argument was that: "Double is a floating point type and decimal is not, that's why precision kept in double is bigger and it is safer to use it". Majority of information mentioned in a sentence above is not true! Decimal is also a floating point type, but with a base 10 not 2 like double has. First have a look at floating point canonical equation taken from wikipedia:


It explains what exponent and mantissa is. Because double and decimal have a fixed size in computer memory in C# language, designers had to decide how many bits should be spent on matissa and how many for exponent. And as for C# language it is illustrated below:
A double represents a number of the form +/- (1 + F / 252 ) x 2E-1023, where F is a 52 bit unsigned integer and E is an 11 bit unsigned integer; that makes 63 bits and the remaining bit is the sign, zero for positive, one for negative.

A decimal represents a number in the form +/- V / 10X where V is a 96 bit unsigned integer and X is an integer between 0 and 28.

It all means that decimal is much safer in doing a correct computations than double.

Wednesday, July 17, 2013

NHibernate cascade save and how many queries are produced

The simplest configuration for a cascade save in nhibernate looks following.
public class CUrlMap : ClassMap<CUrl>
{
    public CUrlMap()
    {
        Table("CommonUrl");
        Id(x => x.Id);
        Map(x => x.CommonUrl);

        HasMany(x => x.CMarketUrls)
            .Inverse()
            .Cascade.All()
            .KeyColumns.Add("CommonUrlId");
    }
}

public class CMarketUrlMap : ClassMap<CMarketUrl>
{
    public CMarketUrlMap()
    {
        Table("CommonMarketUrl");
        Id(x => x.Id);
        Map(x => x.MarketUrl);
        Map(x => x.MarketId);

        References(x => x.CUrl).Column("CommonUrlId");
    }
}

One CUrl has many CMarketUrls. The goal is to create/update/delete everything in lowest possible number of steps. Unfortunately it is not really beautiful from a code and SQL point of view.
The simple code to save CUrl
using (var trans = _repository.BeginTransaction())
{
    _repository.SaveOrUpdate(curl);
    trans.Commit();
}

The first thing is that CommonUrlId column (a foreign key) in SQL must allowed nulls. It is because what Nhibernate does during creation of CUrl is it first creates it and then it creates all CMarketUrl that it keeps in a collection (CMarketUrls). It means that total number of queries is:
  • 1 x insert to CUrl
  • K x insert to CMarketUrls (where K is number of CMarketUrl that are kept in CMarketUrls)

But we are not done yet, the code listed above will save everything but it will not assign Id from a freshly created CUrl to also freshly created CUrlMaps. Programmer needs to map this Id manually during creation. It complicates code, and now it looks:
using (var trans = _repository.BeginTransaction())
{
    _repository.SaveOrUpdate(curl);
                    
    foreach (var cMarketUrl in curl.CMarketUrls)
    {
        cMarketUrl.CUrl = curl;
        _repository.SaveOrUpdate(cMarketUrl);
    }
    trans.Commit();
}

What nhibernate will do is after creation of new records it will update CMarketUrls and set to them newly created Id for CUrl.

It all means that each time when we create a new CUrl with some CMarketUrls the total number of queries is following:
  • 1 x insert to CUrl
  • K x insert to CMarketUrls (where K is number of CMarketUrl that are kept in CMarketUrls)
  • 1 x batch update (in this one batch all CMarketUrls are updated, CUrl is set to them)

As always there is plenty of place to improve nhibernate.