Hi,

I've encountered a strange exception:

I'm trying to do a rather innocent sum:

decimal total = myEntity.Lines.Sum(l => l.Amount.GetValueOrDefault());

This throws an exception:

L'exception System.InvalidCastException s'est produite
  Message="Unable to cast null value to System.Decimal; use System.Decimal? instead."
  Source="Xtensive.Core"
  StackTrace:
       à Xtensive.Core.Tuples.Tuple.GetValueOrDefault[T](Int32 fieldIndex)
       à lambda_method(ExecutionScope , Object[] , Tuple , ItemMaterializationContext )
       à System.DelegateBindExtensions.<>c__DisplayClassa`4.<Bind>b__9(T2 arg2, T3 arg3)
       à Xtensive.Storage.Linq.Materialization.MaterializationHelper.<>c__DisplayClass4`1.<Materialize>b__3(Tuple tuple)
       à System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
       à System.EnumerableExtensions.<Batch>d__27`1.MoveNext()
       à System.EnumerableExtensions.<ApplyBeforeAndAfter>d__2f`1.MoveNext()
       à Xtensive.Storage.TransactionalExtensions.<ToTransactional>d__0`1.MoveNext()
       à System.Linq.Enumerable.<SelectManyIterator>d__14`2.MoveNext()
       à System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
       à lambda_method(ExecutionScope , Object[] , IEnumerable`1 , Dictionary`2 , ParameterContext )
       à System.DelegateBindExtensions.<>c__DisplayClass13`5.<Bind>b__12(T2 arg2, T3 arg3, T4 arg4)
       à Xtensive.Storage.Linq.TranslatedQuery`1.Execute(ParameterContext parameterContext)
       à Xtensive.Storage.Linq.QueryProvider.Execute[TResult](Expression expression)
       à System.Linq.Queryable.Sum[TSource](IQueryable`1 source, Expression`1 selector)

I've tried to create a small sample but naturally the sample runs just fine... ;)

Any thought on this problem?


Updated at 04.05.2010 7:36:49

Hello,

Here is the file version of Xtensive.Storage : 1.0.4870.60138 (latest 4.2 release)

For the model, I will try to build a model reproducing the bug, but I've not been successful for now.

Regards,


Updated at 04.05.2010 7:58:26

Ok, I found the problem: it happens when doing the sum of an empty Entiset<t> on a Nullable type column

Model:

[Serializable]
  [HierarchyRoot]
  public class MyEntity : Entity
  {
    [Field, Key]
    public int Id { get; private set; }

    [Field, Association(PairTo = "Owner")]
    public EntitySet<Line> Lines { get; private set; }
  }

  [HierarchyRoot]
  public class Line : Entity
  {
    [Field, Key]
    public int Id { get; private set; }

    [Field]
    public MyEntity Owner { get; set; }

    [Field]
    public decimal? Amount { get; set; }
  }

Test code:

using (Session.Open(domain))
      {
        using (var transactionScope = Transaction.Open())
        {
          var myEntity = new MyEntity();
          transactionScope.Complete();
        }
      }

      using (Session.Open(domain))
      {
        using (var transactionScope = Transaction.Open())
        {
          MyEntity myEntity = Query.All<MyEntity>().FirstOrDefault();
          Console.WriteLine("Sum = " + myEntity.Lines.Sum(l => l.Amount.GetValueOrDefault()));
          transactionScope.Complete();
        }
      }

Updated at 04.05.2010 8:23:59

Yes this helps : but I disagree with your solution.

First problem: myEntity.Lines.Sum(l => l.Amount.GetValueOrDefault()) is of type decimal. So I can't use the ?? operator (decimal can not contains null)

Second problem: This is inconsistent with the behavior of standard LinqToObject Sum()

Sample:

class Test
    {
      public decimal? Amount { get; set; }
    }

I create an empty list of objects and sum it (like previous sample but without DO)

List<Test> emptyList = new List<Test>();
      decimal sum2 = emptyList.Sum(l => l.Amount.GetValueOrDefault());
      Console.WriteLine("Sum (decimal) = " + sum2);

The result is 0.

For me this is a (minor) bug, and you should correct this particular case to get a true complete LINQ implementation. Do you agree?

This thread was imported from our support forum. The original discussion may contain more detailed answer.

asked May 03 '10 at 16:07

olorin's gravatar image

olorin
358848792

Hello,

Could you please post a subset of your domain model which includes types, taking part in the query?

Also, the file version of DataObjects.Net will assemblies be helpful.

(May 03 '10 at 16:07) Dmitri Maximov Dmitri%20Maximov's gravatar image

One Answer:

Hello,

It seems that the query might be executed against an empty set and as a result NULL value is returned from SQL, which in turn can't be casted to decimal value.

decimal total = myEntity.Lines.Sum(l => l.Amount.GetValueOrDefault());

In order to cope with the problem you should rewrite it in the following way:

decimal total = myEntity.Lines.Sum(l => l.Amount) ?? 0.0;

answered May 04 '10 at 08:06

Dmitri%20Maximov's gravatar image

Dmitri Maximov
22111211

We wrote our posts simultaneously =) So yes, the problem was in the empty set and the solution is to rewrite the query. Does it help?

(May 04 '10 at 08:06) Dmitri Maximov Dmitri%20Maximov's gravatar image

Well, yes. We are going to fix this misbehavior but the investigation might require some additional time. If the fix is minor, it will appear in one of the nearest nightly builds.

(May 04 '10 at 08:06) Dmitri Maximov Dmitri%20Maximov's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

powered by OSQA