Hello, i am getting NotSupportedException when trying to compare result of ternary conditional operator with already materialized entity. Here is how to reproduce it:

[HierarchyRoot]
public class First : Entity
{
    public First(Guid id) : base(id)
    {
    }

    [Field]
    [Key]
    public Guid Id { get; private set; }

    [Field]
    public Second Second { get; set; }
}

[HierarchyRoot]
public class Second : Entity
{
    public Second(Guid id) : base(id)
    {
    }

    [Field]
    [Key]
    public Guid Id { get; private set; }
}

class Program
{
    static void Main(string[] args)
    {
        var dc = new DomainConfiguration("sqlserver", "Data Source=.; Initial Catalog=DO41-Tests;Connection Timeout=300;Integrated Security = true;Max pool size=2");

        dc.Types.Register(typeof(Program).Assembly);

        dc.UpgradeMode = DomainUpgradeMode.Recreate;

        using (var domain = Domain.Build(dc))
        using (var session = domain.OpenSession(SessionType.Default))
        using (session.Activate())
        using (var tr = session.OpenTransaction())
        {
            var second1 = new Second(Guid.NewGuid());
            var second2 = new Second(Guid.NewGuid());

            session.Query.All<First>().Select(z => new
            {
                Id = z.Id,
                Sum = z.Second != null ? z.Second : second1,
            })
            .Where(z => z.Sum == second2)
            .ToArray();
        }
    }
}

and exception


Unhandled Exception: Xtensive.Orm.QueryTranslationException: Unable to translate 'Query.All().Select(z => new @<id, sum="">(
  z.Id,
  (z.Second != null)
    ? z.Second
    : @.second1
)).Where(z => (z.Sum == @.second2))' expression. See inner exception for details. ---> System.NotSupportedException: Both left and right part of binary expression '(IIF((Convert(Field Id, [2 ... 1]) != null), Entity Second, value(Sample.Program+<>cDisplayClas
s0_0).second1) == value(Sample.Program+<>cDisplayClass0_0).second2)' are NULL or not EntityExpression(EntityFieldExpression).
   at Xtensive.Orm.Linq.Translator.VisitBinaryRecursive(BinaryExpression binaryExpression, BinaryExpression originalBinaryExpression)
   at Xtensive.Orm.Linq.Translator.VisitBinary(BinaryExpression binaryExpression)
   at Xtensive.Linq.ExpressionVisitor1.Visit(Expression e)
   at Xtensive.Orm.Linq.Translator.Visit(Expression e)
   at Xtensive.Orm.Linq.Translator.VisitLambda(LambdaExpression le)
   at Xtensive.Orm.Linq.Translator.VisitWhere(Expression expression, LambdaExpression le)
   at Xtensive.Orm.Linq.Translator.VisitQueryableMethod(MethodCallExpression mc, QueryableMethodKind methodKind)
   at Xtensive.Linq.QueryableVisitor.VisitMethodCall(MethodCallExpression mc)
   at Xtensive.Orm.Linq.Translator.VisitMethodCall(MethodCallExpression mc)
   at Xtensive.Linq.ExpressionVisitor1.Visit(Expression e)
   at Xtensive.Orm.Linq.Translator.Visit(Expression e)
   at Xtensive.Orm.Linq.Translator.TranslateTResult
   at Xtensive.Orm.Linq.QueryProvider.TranslateTResult
   --- End of inner exception stack trace ---
   at Xtensive.Orm.Linq.QueryProvider.TranslateTResult
   at Xtensive.Orm.Linq.QueryProvider.TranslateTResult
   at Xtensive.Orm.Linq.QueryProvider.ExecuteTResult
   at Xtensive.Orm.Linq.Queryable1.GetEnumerator()
   at System.Linq.Buffer1..ctor(IEnumerable1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source)
   at Sample.Program.Main(String[] args) in F:\Projects\CleanDO\Sample\Program.cs:line 69

asked Feb 18 at 08:54

meatblob's gravatar image

meatblob
5


One Answer:

Hello meatblob

Such closures are not supported. I'm not sure that it is possible to translate into pure SQL query. The only way it will work with such closures is executing select on client side like

session.Query.All<first>().AsEnumerable().Select(z => new
            {
                Id = z.Id,
                Sum = z.Second != null ? z.Second : second1,
            })
            .Where(z => z.Sum == second2)
            .ToArray();

but it is horrible idea because it is reading of whole tables. Don't do that.

Another thing you can do is rewrite your query to avoid closure of entire entity like

session.Query.All<first>().Select(z => new
          {
            Id = z.Id,
            SumId = z.Second != null ? z.Second.Id : second1.Id,
          })
          .Select(t=> new {t.Id, Sum = session.Query.All<second>().First(s=> s.Id==t.SumId)})
          .Where(z => z.Sum == second1)
          .ToArray()

answered Feb 20 at 08:26

Alexey%20Kulakov's gravatar image

Alexey Kulakov
66215

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