Здравствуйте, 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.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, 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>>
Здравствуйте, 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.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, ili, Вы писали:
IT>>В общем, я долго думал и ничего кроме IgnoreIEnumerable атрибута не придумал. Вещать на все классы, которые испльзуются как скаляры. Обе баги вроде полечились.
ili>спс, только есть такой вопрос — а с применеием этого аттрибута, какие запросы могут сломаться?
Никакие не должны. Он просто убирает из рассмотрения те IEnumerables, которые к делу не относятся.
ЗЫ. Но, думаю, что можно будет обойтись и без него, только подкрутить кое-что малость.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, AndrewVK, Вы писали:
IT>>Я недавно менял в одном месте List<T> на IEnumerable<T>, т.к. последнее правильнее. По-этому и сломалось.
AVK>В подзапросах, кстати, IEnumerable не работает. Правда, заработал IList, что уже неплохо.
В смысле в ассоциациях? Непорядок.
Если нам не помогут, то мы тоже никого не пощадим.
А зачем анализировать на предмет IEnumerable, если это не ассоциация? И, в любом случае, IgnoreEnumerable должно прикладываться не только к классу, но и свойству.
... << RSDN@Home 1.2.0 alpha 4 rev. 1424 on Windows 7 6.1.7600.0>>
Здравствуйте, 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]
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, 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.