DO 5.0.17

namespace Sample
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using NUnit.Framework;
    using Xtensive.Orm;
    using Xtensive.Orm.Configuration;

    internal class Program
    {
        private static void Main(string[] args)
        {
            var dc = new DomainConfiguration("sqlserver",
                "Data Source=.; Initial Catalog=DO40-Tests; Integrated Security=True;");

            dc.Types.Register(typeof(TestEntity));
            dc.Types.Register(typeof(TestEntity2));
            dc.Types.Register(typeof(ListEntity));

            dc.UpgradeMode = DomainUpgradeMode.Recreate;

            Expression<Func<TestEntity, TestEntity2>> exp = e => e.List.FirstOrDefault().Link; 
            Expression<Func<TestEntity, TestEntity2>> exp2 = e => e.LinkOnList.Link;

            dc.LinqExtensions.Register(typeof(TestEntity).GetProperty(nameof(TestEntity.VirtualList)), exp);
            dc.LinqExtensions.Register(typeof(TestEntity).GetProperty(nameof(TestEntity.VirtualLink)), exp2);

            using (var d = Domain.Build(dc))
            {
                using (var s = d.OpenSession())
                using (s.Activate())
                using (var t = s.OpenTransaction())
                {
                    var item = new TestEntity(s) { String = "test" };
                    var item2 = new TestEntity2(s) { String = "test" };
                    var list = new ListEntity(s) { String = "test", Owner = item, Link = item2 };
                    item.LinkOnList = list;

                    new TestEntity(s) { String = "test2" };

                    t.Complete();
                }

                using (var s = d.OpenSession())
                using (s.Activate())
                using (var t = s.OpenTransaction())
                {
                    var ids = new List<Guid> { Guid.NewGuid() };

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.Link != null && e.Link.Id != Guid.NewGuid())
                        .OrderBy(e => e.Link)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.VirtualLink != null && e.VirtualLink.Id != Guid.NewGuid())
                        .OrderBy(e => e.VirtualLink)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.VirtualList != null && e.VirtualList.Id != Guid.NewGuid())
                        .OrderBy(e => e.VirtualList)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.Link != null && !ids.Contains(e.Link.Id))
                        .OrderBy(e => e.Link)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.VirtualLink != null && !ids.Contains(e.VirtualLink.Id))
                        .OrderBy(e => e.VirtualLink)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.VirtualList != null && !ids.Contains(e.VirtualList.Id))
                        .OrderBy(e => e.VirtualList)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.Link.Id != Guid.NewGuid())
                        .OrderBy(e => e.Link)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.VirtualLink.Id != Guid.NewGuid())
                        .OrderBy(e => e.VirtualLink)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => e.VirtualList.Id != Guid.NewGuid())
                        .OrderBy(e => e.VirtualList)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => !ids.Contains(e.Link.Id))
                        .OrderBy(e => e.Link)
                        .ToArray();

                    // OK
                    Query.All<TestEntity>()
                        .Where(e => !ids.Contains(e.VirtualLink.Id))
                        .OrderBy(e => e.VirtualLink)
                        .ToArray();

                    // FAIL
                    // Generate INNER JOIN on [Program.TestEntity2], when 'List' empty, VirtualList = null and row excluded from select
                    Assert.AreEqual(2, Query.All<TestEntity>()
                        .Select(e => new { e.VirtualList.String, e.VirtualList.Id })
                        .Count());

                    // FAIL
                    // Unable to translate
                    Query.All<TestEntity>()
                        .Where(e => !ids.Contains(e.VirtualList.Id))
                        .OrderBy(e => e.VirtualList)
                        .ToArray();

                    t.Complete();
                }
            }
        }

        [HierarchyRoot]
        public class TestEntity : Entity
        {
            /// <summary>Initializes a new instance of this class.</summary>
            /// <param name="session">The session.</param>
            public TestEntity(Session session) : base(session)
            {
            }

            [Key]
            [Field(Nullable = false)]
            public Guid Id { get; private set; }

            [Field]
            public string String { get; set; }

            [Field]
            public ListEntity LinkOnList { get; set; }

            [Field]
            [Association(PairTo = "Owner")]
            public EntitySet<ListEntity> List { get; set; }

            [Field]
            public TestEntity2 Link { get; set; }

            public TestEntity2 VirtualList { get; set; }

            public TestEntity2 VirtualLink { get; set; }
        }

        [HierarchyRoot]
        public class ListEntity : Entity
        {
            /// <summary>Initializes a new instance of this class.</summary>
            /// <param name="session">The session.</param>
            public ListEntity(Session session) : base(session)
            {
            }

            [Key]
            [Field(Nullable = false)]
            public Guid Id { get; private set; }

            [Field]
            public string String { get; set; }

            [Field(Nullable = false)]
            public TestEntity Owner { get; set; }

            [Field(Nullable = false)]
            public TestEntity2 Link { get; set; }
        }

        [HierarchyRoot]
        public class TestEntity2 : Entity
        {
            /// <summary>Initializes a new instance of this class.</summary>
            /// <param name="session">The session.</param>
            public TestEntity2(Session session) : base(session)
            {
            }

            [Key]
            [Field(Nullable = false)]
            public Guid Id { get; private set; }

            [Field(Nullable = false)]
            public string String { get; set; }
        }
    }
}

asked Sep 12 at 07:53

Gushchin%20Anton's gravatar image

Gushchin Anton
76913

Be the first one to answer this question!
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