title: Linq Sum() precision
body: <p>In my project I have been using <code>Linq's Sum()</code> a lot. It's powered by NHibernate on MySQL. In my <code>Session Factory</code> I have explicitly asked NHibernate to deal with exactly 8 decimal places when it comes to <code>decimals</code>:</p>
  
  <pre><code>public class DecimalsConvention : IPropertyConvention
  {
      public void Apply(IPropertyInstance instance)
      {
          if (instance.Type.GetUnderlyingSystemType() == typeof(decimal))
          {
              instance.Scale(8);
              instance.Precision(20);
          }
      }
  }
  </code></pre>
  
  <p>However, I found out that <code>.Sum()</code> rounds up the numbers in 5 decimal places: </p>
  
  <p><code>var opasSum = opasForThisIp.Sum(x =&gt; x.Amount);  // Amount is a decimal</code></p>
  
  <p>In the above statement <code>opaSum</code> equals to <strong>2.46914</strong> while it should be <strong>2.46913578</strong> (calculated directly on MySQL). <code>opasForThisIp</code> is of type <code>IQueryable&lt;OutgoingPaymentAssembly&gt;</code>.</p>
  
  <p>I need all the Linq calculations to handle 8 decimal places when it comes to <code>decimals</code>. </p>
  
  <p>Any ideas of how to fix this?</p>
  
  <p><strong>Edit 1</strong>: I have found <code>var opasSum = Enumerable.Sum(opasForThisIp, opa =&gt; opa.Amount);</code> to produce the correct result, however the question remains, why <code>.Sum()</code> rounds up the result and how can we fix it?</p>
  
  <p><strong>Edit 2</strong>: The produced SQL seems to be problematic:</p>
  
  <pre><code>select cast(sum(outgoingpa0_.Amount) as DECIMAL(19,5)) as col_0_0_ 
  from `OutgoingPaymentAssembly` outgoingpa0_ 
  where outgoingpa0_.IncomingPayment_id=?p0 
  and (outgoingpa0_.OutgoingPaymentTransaction_id is not null);
  ?p0 = 24 [Type: UInt64 (0)]
  </code></pre>
  
  <p><strong>Edit 3</strong>: <code>var opasSum = opasForThisIp.ToList().Sum(x =&gt; x.Amount);</code> also produces the correct result.</p>
  
  <p><strong>Edit 4</strong>: Converting the <code>IQueryable&lt;OutgoingPaymentAssembly&gt;</code> to an <code>IList&lt;OutgoingPaymentAssembly&gt;</code> made the original query: <code>var opasSum = opasForThisIp.Sum(x =&gt; x.Amount);</code> to work.</p>