Re[8]: Собственно тесты
От: IT Россия linq2db.com
Дата: 04.02.10 15:14
Оценка:
Здравствуйте, AndrewVK, Вы писали:

IT>>В общем, я долго думал и ничего кроме IgnoreIEnumerable атрибута не придумал.

AVK>Может, надо было добавить в AssociationAtribute отдельное свойство, позволяющее явно задать тип связи?

Там проблема не с ассоциациями, а с анализом принадлежности поля к источнику. Возьмём вот такой пример:

from p in db.Parent select db.Child.FirstOrDefault().ChildID

То, что здесь ChildID скаляр ещё ничего не значит. Выражение разбирать нужно дальше и смотреть из какого источниа этот ChildID к нам приехал. Здесь:

var res = from rc in db.GetTable<TestEntity>()
          join li in db.GetTable<LookupEntity>() on rc.Id equals li.InnerEnity.Id //скаляр
          where rc.EntityType == TestEntityType.Type1 //скаляр
          select rc; // IEnumerable но работает правильно - поля сгенерены;

li.InnerEnity.Id тоже по идее скаляр, но при анализе источника мы выходим на InnerEnity, которое по идее вложенный объект, на который даже что-то мапится, но при этом этот InnerEnity реализует IEnumerable для каких-то своих корыстных целей. Парсер BLT принимает решение, что это что-то связанное с IEnumerable и дальше сваливается на парсинг подзапроса.

Можно, конечно провести более глубокий анализ, но во-первых, это не добавит простоты коду, который и так уже зашкаливает все разумные пределы, во-вторых, случай уж больно экзотический.

Можно, конечно, добавить ещё одно имперической условие — анализировать на предмет подзапроса только выражения у которых базовое выражение НЕ типа ExpressionType.MemberAccess. По идее работать должно. Я не припомню у стандартных наследников IEnumerable членов-многочленов типа Property1.Property2.
Если нам не помогут, то мы тоже никого не пощадим.
Re[9]: Собственно тесты
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.02.10 15:24
Оценка:
Здравствуйте, IT, Вы писали:

IT>li.InnerEnity.Id тоже по идее скаляр, но при анализе источника мы выходим на InnerEnity, которое по идее вложенный объект, на который даже что-то мапится, но при этом этот InnerEnity реализует IEnumerable для каких-то своих корыстных целей.


Так вот если в InnerEntity будет явно прописана ассоциация с указанием, что она х к 1, то анализировать на предмет множеств уже нафик не нужно, следует интерпретировать строго как скаляр.

IT>Можно, конечно, добавить ещё одно имперической условие


эмпирическое

IT>- анализировать на предмет подзапроса только выражения у которых базовое выражение НЕ типа ExpressionType.MemberAccess.


Тогда отвалятся честные ассоциации-множества, которые ввиде все того же MemberAccess.
... << RSDN@Home 1.2.0 alpha 4 rev. 1424 on Windows 7 6.1.7600.0>>
AVK Blog
Re[10]: Собственно тесты
От: IT Россия linq2db.com
Дата: 04.02.10 15:42
Оценка:
Здравствуйте, AndrewVK, Вы писали:

IT>>li.InnerEnity.Id тоже по идее скаляр, но при анализе источника мы выходим на InnerEnity, которое по идее вложенный объект, на который даже что-то мапится, но при этом этот InnerEnity реализует IEnumerable для каких-то своих корыстных целей.


AVK>Так вот если в InnerEntity будет явно прописана ассоциация с указанием, что она х к 1, то анализировать на предмет множеств уже нафик не нужно, следует интерпретировать строго как скаляр.


Это не ассоциация, это тип, который используется как часть объекта, на который мапится часть записи. Упрощённо:

class A : IEnumerable
{
    public int Field2;
}

[MapField("Field2", "Field2.Field2")]
class B
{
    public int Field1;
    public A   Field2;
}

Т.е. у нас поле Field2 является одновременно и скаляром и последовательностью.

IT>>Можно, конечно, добавить ещё одно имперической условие


AVK>эмпирическое


А мне уже пофиг. И те и другие уже порядком заколебали.

IT>>- анализировать на предмет подзапроса только выражения у которых базовое выражение НЕ типа ExpressionType.MemberAccess.


AVK>Тогда отвалятся честные ассоциации-множества, которые ввиде все того же MemberAccess.


Не должны. Анализ нужно продолжать до самого источника, просто не принимать решение раньше времени. Т.е. в случае db.Table.FirstOrDefault().Field1.Field2 мы должны не останавливаться на Field1, если это член и IEnumerable, а только игнорировать тот факт, что это IEnumerable.
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: Собственно тесты
От: IT Россия linq2db.com
Дата: 04.02.10 16:39
Оценка:
Здравствуйте, ili, Вы писали:

IT>>В общем, я долго думал и ничего кроме IgnoreIEnumerable атрибута не придумал. Вещать на все классы, которые испльзуются как скаляры. Обе баги вроде полечились.


ili>спс, только есть такой вопрос — а с применеием этого аттрибута, какие запросы могут сломаться?


Никакие не должны. Он просто убирает из рассмотрения те IEnumerables, которые к делу не относятся.

ЗЫ. Но, думаю, что можно будет обойтись и без него, только подкрутить кое-что малость.
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: Собственно тесты
От: IT Россия linq2db.com
Дата: 04.02.10 17:09
Оценка:
Здравствуйте, AndrewVK, Вы писали:

IT>>Я недавно менял в одном месте List<T> на IEnumerable<T>, т.к. последнее правильнее. По-этому и сломалось.


AVK>В подзапросах, кстати, IEnumerable не работает. Правда, заработал IList, что уже неплохо.


В смысле в ассоциациях? Непорядок.
Если нам не помогут, то мы тоже никого не пощадим.
Re[9]: Собственно тесты
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.02.10 17:32
Оценка:
Здравствуйте, IT, Вы писали:

IT>В смысле в ассоциациях?


В них.

IT> Непорядок.


Точно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1424 on Windows 7 6.1.7600.0>>
AVK Blog
Re[11]: Собственно тесты
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.02.10 17:32
Оценка:
Здравствуйте, IT, Вы писали:

IT>Это не ассоциация


А зачем анализировать на предмет IEnumerable, если это не ассоциация? И, в любом случае, IgnoreEnumerable должно прикладываться не только к классу, но и свойству.
... << RSDN@Home 1.2.0 alpha 4 rev. 1424 on Windows 7 6.1.7600.0>>
AVK Blog
Re[12]: Собственно тесты
От: IT Россия linq2db.com
Дата: 04.02.10 17:53
Оценка:
Здравствуйте, AndrewVK, Вы писали:

IT>>Это не ассоциация


AVK>А зачем анализировать на предмет IEnumerable, если это не ассоциация? И, в любом случае, IgnoreEnumerable должно прикладываться не только к классу, но и свойству.


Откуда я знаю что это не ассоциация? Чтобы это определить нужно дойти до самого низа цепочки, возможно посмотреть что это за параметр, определить по нему источник, затем покопаться в этом источнике на предмет разбора его полей вроде 'new { t = myTable }', разобрать эти поля, потом вернуться обратно. При этом даже если я обнаружу, что это не ассоциация, то это не значит, что мне не нужно обрабатывать IEnumerable как подзапрос. Пример я приводил выше:

from p in db.Parent select db.Child.FirstOrDefault().ChildID

Здесь нет ассоциации, но есть подзапрос:

SELECT
    (
        SELECT TOP (1)
            [t1].[ChildID]
        FROM
            [Child] [t1]
    ) as [c1]
FROM
    [Parent] [p]
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: Собственно тесты
От: ili Россия  
Дата: 21.02.11 12:33
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, ili, Вы писали:


IT>>>Понятно. Тогда ничего удивительного, BLT не может выявить разницу межу скалярным полем и списочным, если это IEnumerable. Какие-нибудь идеи как это распознать?


IT>В общем, я долго думал и ничего кроме IgnoreIEnumerable атрибута не придумал. Вещать на все классы, которые испльзуются как скаляры. Обе баги вроде полечились.


Не прошло и года, как проблема вернулась:

        public class Entity
        {
            public Int32 Id { get; set; }
        }

        [IgnoreIEnumerable]
        public class EnumerableMaster : Entity, IEnumerable<Entity>
        {
            public String Name { get; set; }


            public IEnumerator<Entity> GetEnumerator()
            {
                yield return new Entity { Id = 1 };
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }

        [MapField("MasterId", "Master.MasterId")]
        public class DetailWithEnumerableMaster : Entity
        {
            public EnumerableMaster Master { get; set; }
        }


        [Test]
        public void ParentEnumerableBug()
        {
            using (var db = GetDbManager())
            {
                var visitsFiltered = from detail in db.GetTable<DetailWithEnumerableMaster>()
                                     join master in db.GetTable<EnumerableMaster>() on detail.Master.Id equals master.Id
                                     where master.Name == "fdkjbnla"
                                     select detail;
                var res = visitsFiltered.ToList();
            }
        }


BLToolkit.Data.Linq.LinqException : 'detail.Master.Id' cannot be converted to SQL.

Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.