Actually, there are 2 tests/bugs here. First for subj, second for new session modes.

namespace Project2
{
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Transactions;

    using NUnit.Framework;

    using Xtensive.Core;
    using Xtensive.Linq;
    using Xtensive.Orm.Configuration;

    using System;

    using Xtensive.Orm;

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

        [Field]
        public int Age { get; set; }

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

        public string RegionName { get { return exprComp(Region); } }

        private static readonly Expression<Func<Region, string>> expr = r => r.Name;

        private static readonly Func<Region, string> exprComp = expr.Compile();

        /// <summary>
        /// The custom linq compiler container.
        /// </summary>
        [CompilerContainer(typeof(Expression))]
        public static class CustomLinqCompilerContainer
        {
            /// <summary>
            /// The current.
            /// </summary>
            /// <param name="assignmentExpression">
            /// The assignment expression.
            /// </param>
            /// <returns>
            /// </returns>
            [Compiler(typeof(Person), "RegionName", TargetKind.PropertyGet)]
            public static Expression Current(Expression assignmentExpression)
            {
                return expr.BindParameters(assignmentExpression);
            }
        }
    }

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

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

    public interface ITest : IEntity
    {
        string RegionName { get; }
    }

    /// <summary>
    /// The virtual fields test.
    /// </summary>
    [TestFixture]
    public class VirtualFieldsTest
    {
        private Domain domain;

        [TestFixtureSetUp]
        public virtual void Setup()
        {
            var cfg = new DomainConfiguration("sqlserver", "Data Source=.; Initial Catalog=DO40-Tests; Integrated Security=True;Connection Timeout=300")
            {
                UpgradeMode = DomainUpgradeMode.Recreate,
                ValidationMode = ValidationMode.OnDemand,
                NamingConvention = new NamingConvention { NamingRules = NamingRules.UnderscoreDots }
            };

            cfg.Sessions.Add(new SessionConfiguration("Default")
            {
                BatchSize = 25,
                DefaultIsolationLevel = IsolationLevel.ReadCommitted,
                CacheSize = 1000,
                Options = SessionOptions.Default | SessionOptions.AutoTransactionOpenMode | SessionOptions.AutoActivation
            });

            cfg.Types.Register(Assembly.GetExecutingAssembly());

            domain = Domain.Build(cfg);
        }

        /// <summary>
        /// Проверка виртуальных полей
        /// </summary>
        [Test]
        [Transactional(ActivateSession = true)]
        public void VirtualFieldSelect1()
        {
        }

        /// <summary>
        /// Проверка виртуальных полей
        /// </summary>
        [Test]
        public void VirtualFieldSelect2()
        {
            using (var s = domain.OpenSession())
            {
                var r = new Region { Name = "13123123121" };
                var p = new Person { Age = 1, Region = r };

                var queryable = Query.All<Person>();

                var qwe = from person in queryable
                          where person.RegionName != null
                          select person;
                Assert.DoesNotThrow(() => qwe.ToArray());

                var q = queryable as IQueryable<ITest>;
                var qq = from test in q
                         where test.RegionName != null
                         select test;
                Assert.DoesNotThrow(() => qq.ToArray());
            }
        }
    }
}

asked Feb 22 '11 at 04:33

xumix's gravatar image

xumix
425757682

edited Feb 25 '11 at 08:58

What exceptions are thrown here?

(Feb 23 '11 at 07:24) Alex Yakunin Alex%20Yakunin's gravatar image
1

You can just copy/paste this code and run it to see the exceptions.

(Feb 24 '11 at 03:23) xumix xumix's gravatar image

Any progress?

(Mar 03 '11 at 03:12) xumix xumix's gravatar image

Not yet, the work has just been started. Sorry for the delay.

(Mar 03 '11 at 05:11) Dmitri Maximov Dmitri%20Maximov's gravatar image

3 Answers:

Fixed in revision 7579, the binaries are available on the website.

answered Jun 06 '11 at 07:33

Dmitri%20Maximov's gravatar image

Dmitri Maximov
22111211

Hello xumix,

It seems that there is a tiny problem in the sample, you define CustomLinqCompilerContainer for Person type only, but try fetching instances of more generic ITest interface instead, where the container is also supposed to be applied.

You should move in opposite direction: define CustomLinqCompilerContainer for ITest interface, for example, this sample one fits well:

[Compiler(typeof(ITest), "RegionName", TargetKind.PropertyGet)]
public static Expression ITestRegionName(Expression assignmentExpression)
{
  Expression<Func<ITest, string>> le = it => it is Person ? (it as Person).Region.Name : null;
  return le.BindParameters(assignmentExpression);
}

answered Mar 04 '11 at 06:37

Dmitri%20Maximov's gravatar image

Dmitri Maximov
22111211

edited Mar 04 '11 at 06:37

Well, this is not the way, how one should use Interfaces. They are interfaces exactly because you can create different implementations in every class. So Expression[Func[ITest, string]] expression can be different in different entities.

(Mar 04 '11 at 07:19) xumix xumix's gravatar image

Moreover, this sample does not work even in the first query, where no interface is used.

(Mar 04 '11 at 07:21) xumix xumix's gravatar image

Sorry, forgot to mention that we altered the Person class, here is how it looks like:

...
private static readonly Expression<Func<Person, string>> expr = p => p.Region.Name;
private static readonly Func<Person, string> exprComp = expr.Compile();

Secondly, the query is analyzed and preprocessed in the static context, at this step there is no any entities (with different implementations) because materialization is not started yet. The only thing that is clear is that the query root is ITest and if a CustomLinqCompilerContainer registered for this type, it should be applied.

(Mar 04 '11 at 07:39) Dmitri Maximov Dmitri%20Maximov's gravatar image

Ok, how do you imagine this expression for 10 ITest implementor types? Looks like this is not the right way to implement this feature.

(Mar 04 '11 at 08:07) xumix xumix's gravatar image
1

I agree. Will think about the possible alternatives.

(Mar 04 '11 at 08:22) Dmitri Maximov Dmitri%20Maximov's gravatar image

Nice, thank you!

(Mar 04 '11 at 09:26) xumix xumix's gravatar image

Any progress?

(Apr 20 '11 at 09:54) xumix xumix's gravatar image

Unfortunately, nothing has changed yet. I suppose that we could focus on this later, right after 4.5 release.

(Apr 20 '11 at 10:34) Dmitri Maximov Dmitri%20Maximov's gravatar image

Hello xumix,

The binaries with an early fix are published, nightly build #7571

(May 31 '11 at 11:32) Dmitri Maximov Dmitri%20Maximov's gravatar image

Hello xumix,

Thanks for your voting down and congratulations for 'Critic' badge! =)

Concerning the second question (session activation fail). Applying [Transactional(ActivateSession = true)] is senseless on types other than ISessionBound implementors.

answered Mar 05 '11 at 07:28

Alexis%20Kochetov's gravatar image

Alexis Kochetov
1414

Thanks for your voting down and congratulations for 'Critic' badge! =)

Thank you too:)

Concerning [Transactional(ActivateSession = true)] - isn't it supposed to be applied on methods and not types?

(Mar 05 '11 at 08:24) xumix xumix's gravatar image

It is supposed to be used with methods, but with methods of ISessionBound implementors.

Will describe this in detail in the Manual soon.

Could you share your scenario of Transactional attribute application on arbitrary type?

(Mar 05 '11 at 08:30) 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