Linq: bug
От: ili Россия  
Дата: 02.02.10 11:54
Оценка:
проапдейтился и кой чего сломалось:

вот это:

var res = from rc in db.GetTable<ResourceCount>()
          join li in db.GetTable<LookupInterface>() on rc.Id equals li.Stock.Id
          where rc.StockType == StockName.ResourceCount
          select rc;

var list = res.ToList();


генерит вот это:

SELECT
    [rc].[StockType],
    [rc].[Amount],
    [rc].[IsActive],
    [rc].[AccountStockId] as [Id],
    [rc].[CategoryId] as [StockCategory_Id],
    [rc].[SuperAccountId] as [Owner_Id]
FROM
    [AccountStock] [rc]
        INNER JOIN [LookupInterface] [t1] ON [rc].[AccountStockId] = [t1].[LookupLink]
WHERE
    Convert(Int, (
        SELECT
            *
    )) = 48


а раньше было так:
WHERE
    Cast(rc.StockType as Int) = 48


P.S. на счет того что был cast а не convert я не уверен
P.P.S. rc.StockType — enum
Re: Linq: bug 2
От: ili Россия  
Дата: 02.02.10 12:12
Оценка:
Здравствуйте, ili, Вы писали:

ili>проапдейтился и кой чего сломалось:


и еще несколько схожая ситуёвина:

вот такой запрос валится

var zones = (from z in db.GetTable<PaidZoneVisit>()
         join o in db.GetTable<SuperAccount>() on z.Owner.Id equals o.Id 
         where z.Amount > 0 
            && o.Type == SuperAccountType.Client
         select z).ToList();


в ExpressionParser

ISqlExpression ParseSubQuery(ParseInfo expr, params QuerySource[] queries)
{
    ParsingTracer.WriteLine(expr);
    ParsingTracer.WriteLine(queries);
    ParsingTracer.IncIndentLevel();

    var parentQueries = queries.Select(q => new ParentQuery { Parent = q, Parameter = q.Lambda.Parameters.FirstOrDefault() }).ToList();


получаю NRE, т.к. q.Lambda == null
Re: Linq: bug
От: IT Россия linq2db.com
Дата: 02.02.10 14:23
Оценка:
Здравствуйте, ili, Вы писали:

ili>проапдейтился и кой чего сломалось:


ili>вот это:


ili>
ili>var res = from rc in db.GetTable<ResourceCount>()
ili>          join li in db.GetTable<LookupInterface>() on rc.Id equals li.Stock.Id
ili>          where rc.StockType == StockName.ResourceCount
ili>          select rc;

ili>var list = res.ToList();
ili>


ili>генерит вот это:


Не воспроизводится. Можно структуру объектов посмотреть. Особенно интересно что такое li.Stock.Id.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Linq: bug 2
От: IT Россия linq2db.com
Дата: 03.02.10 05:54
Оценка:
Здравствуйте, ili, Вы писали:

ili>и еще несколько схожая ситуёвина:


Этот тоже не воспроизводиться. Но я немного подкрутил работу с энумераторами, может быть поможет. Если нет, то желательно получить код классов или минимально упрощённый пример, на котором это проявляется.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Linq: bug 2
От: ili Россия  
Дата: 03.02.10 06:17
Оценка:
Здравствуйте, IT, Вы писали:

IT>Этот тоже не воспроизводиться. Но я немного подкрутил работу с энумераторами, может быть поможет. Если нет, то желательно получить код классов или минимально упрощённый пример, на котором это проявляется.


не спасли 300р отца русской демократии
ща тесты делать буду, которые воспроизводят.
Re[3]: Linq: bug 2
От: ili Россия  
Дата: 03.02.10 06:46
Оценка:
Здравствуйте, IT, Вы писали:

так, а чего поставить надо, чтобы UnitTests.Linq.dll загружалась нормально, а то nUnit говорит FileNotFoundException — не могу загрузить сборку UnitTests.Linq.dll или один зависимый от них компонент (про образ виртуальный я помню, но мен так, в общеобразовательном плане дополнительно интересно).
Re[3]: Собственно тесты
От: ili Россия  
Дата: 03.02.10 07:54
Оценка: 58 (1)
IT>Этот тоже не воспроизводиться. Но я немного подкрутил работу с энумераторами, может быть поможет. Если нет, то желательно получить код классов или минимально упрощённый пример, на котором это проявляется.

код ниже, а в краце, все упипается в то, что TestEntity и SuperAccount наследники IEnumerable<T>, как только убираешь это наследование, летает как трофейный мерседес.

[TestFixture]
public class Tests1
{
    public class Entity
    {
        public int Id { get; set; }
    }

    public enum TestEntityType : byte { Type1, Type2 }

    [MapField("LookupEntityId", "Id")]
    [MapField("LookupLink", "InnerEnity.Id")]
    public class LookupEntity : Entity
    {
        public Entity         InnerEnity      { get; set; }
        public TestEntityType InnerEntityType { get; set; }
    }

    [TableName("TestEntity")]
    [MapField("TestEntityBaseId", "Id")]
    [MapField("SuperAccountId",   "Owner.Id")]
    public class TestEntityBase : Entity
    {
        public TestEntityType EntityType { get; set; }
        public SuperAccount   Owner      { get; set; }
        public decimal        Amount     { get; set; }
    }

    public class TestEntity : TestEntityBase, IEnumerable<object>
    {
        #region IEnumerable<object> Members

        public IEnumerator<object> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    [TableName("TestEntity2")]
    public class TestEntity2 : TestEntityBase
    {
    }

    public enum SuperAccountType { Client, Organization }
    
    public class SuperAccount : Entity, IEnumerable<object>
    {
        public List<Entity>     InnerAccounts { get; set; }
        public SuperAccountType Type          { get; set; }


        #region IEnumerable<object> Members

        public IEnumerator<object> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    [Test]
    public void WrongQueryTest()
    {
        using (var db = new DbManager())
        {
            try
            {
                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;

                res.ToList();

            }
            finally
            {
                Console.WriteLine(db.LastQuery);
            }
        }
    }

    [Test]
    public void NRETest()
    {
        using (var db = new DbManager())
        {
            var zones = (from z in db.GetTable<TestEntity2>()
                         join o in db.GetTable<SuperAccount>() on z.Owner.Id equals o.Id
                         where z.Amount > 0
                            && o.Type == SuperAccountType.Client
                         select z).ToList();
        }
    }
}
Re[4]: Linq: bug 2
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 03.02.10 09:49
Оценка:
Здравствуйте, ili, Вы писали:

ili>так, а чего поставить надо, чтобы UnitTests.Linq.dll загружалась нормально


.NET драйвера всех используемых внешних СУБД — ODP для Оракля, DB2, Informix, MySql, FB, Sybase. Может еще какую забыл.
... << RSDN@Home 1.2.0 alpha 4 rev. 1424 on Windows 7 6.1.7600.0>>
AVK Blog
Re[5]: Linq: bug 2
От: ili Россия  
Дата: 03.02.10 10:06
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>.NET драйвера всех используемых внешних СУБД — ODP для Оракля, DB2, Informix, MySql, FB, Sybase. Может еще какую забыл.


спс, вот что-то подобное я и подозревал...
хорошобы добавить ссылки откуда качать, дабы гугл не перенапрягать, либо в текстик в редистре как для оракула, либо в вики, которая сейчас лежит, там даж раздел был про поддерживаемые провайдеры... его еще и дополнить можно
Re[4]: Собственно тесты
От: IT Россия linq2db.com
Дата: 03.02.10 18:54
Оценка:
Здравствуйте, ili, Вы писали:

ili>код ниже, а в краце, все упипается в то, что TestEntity и SuperAccount наследники IEnumerable<T>, как только убираешь это наследование, летает как трофейный мерседес.


Понятно. Тогда ничего удивительного, BLT не может выявить разницу межу скалярным полем и списочным, если это IEnumerable. Какие-нибудь идеи как это распознать?
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Собственно тесты
От: ili Россия  
Дата: 04.02.10 03:55
Оценка:
Здравствуйте, IT, Вы писали:

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


эээ... месяц назад этот код работал, у меня с ним релиз продукта есть точную ревизию не скажу, но последний апдейт (до того как этот код сломался) я делал где-то в декабре.

да и чего тут распозновать, везде скаляры.
где-то, что-то не так при разборе лямбд в where, когда тот же join on equals разбирается и строится четко.
эт ярко видно на WrongQueryTest, где генерится кривой код именно в WHERE.
В NRETest разбор WHERE вообще не проходит, по ходу из-за того, что там два условия...
на работу приду — проверю.

    [Test]
    public void WrongQueryTest()
    {
        using (var db = new DbManager())
        {
            try
            {
                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 но работает правильно - поля сгенерены;

                res.ToList();

            }
            finally
            {
                Console.WriteLine(db.LastQuery);
            }
        }
    }

    [Test]
    public void NRETest()
    {
        using (var db = new DbManager())
        {
            var zones = (from z in db.GetTable<TestEntity2>()
                         join o in db.GetTable<SuperAccount>() on z.Owner.Id equals o.Id //скаляр
                         where z.Amount > 0 //скаляр
                            && o.Type == SuperAccountType.Client //скаляр
                         select z /* до этого даже не доходит */).ToList();
        }
    }
Re[6]: Собственно тесты
От: IT Россия linq2db.com
Дата: 04.02.10 04:00
Оценка:
Здравствуйте, ili, Вы писали:

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


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


ili>эээ... месяц назад этот код работал, у меня с ним релиз продукта есть точную ревизию не скажу, но последний апдейт (до того как этот код сломался) я делал где-то в декабре.


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

ili>да и чего тут распозновать, везде скаляры.


Логика то простая. Раз объект наследуется от IEnumerable<T>, значит это списочный объект. Нужна какая-то дополнительная проверка.
... << RSDN@Home 1.2.0 alpha 4 rev. 1425>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Собственно тесты
От: IT Россия linq2db.com
Дата: 04.02.10 04:55
Оценка:
Здравствуйте, ili, Вы писали:

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


В общем, я долго думал и ничего кроме IgnoreIEnumerable атрибута не придумал. Вещать на все классы, которые испльзуются как скаляры. Обе баги вроде полечились.
... << RSDN@Home 1.2.0 alpha 4 rev. 1425>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: Собственно тесты
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.02.10 05:08
Оценка:
Здравствуйте, IT, Вы писали:

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


В подзапросах, кстати, IEnumerable не работает. Правда, заработал IList, что уже неплохо.
... << RSDN@Home 1.2.0 alpha 4 rev. 1424 on Windows 7 6.1.7600.0>>
AVK Blog
Re[7]: Собственно тесты
От: ili Россия  
Дата: 04.02.10 06:06
Оценка:
Здравствуйте, IT, Вы писали:

IT>Логика то простая. Раз объект наследуется от IEnumerable<T>, значит это списочный объект. Нужна какая-то дополнительная проверка.


эээ... поясни для тех кто в танке и не в тренде:

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 но работает правильно - поля сгенерены;


где здесь IEnumerable<T> кроме select rc?
я ввиду, тойже, малоопытасти не знаю как правильно выразить join но :

... 
    .Where(rc => rc.EntityType == TestEntityType.Type1)
    .Select(rc => rc);


везде скаляры...
я так, интуитивно думаю, что валиться на такой лямбде rc => rc.EntityType == TestEntityType.Type1
ну так сверять то надо не вход лямбды, а операнды, а в операндах четкие скаляры...

да и L2O работает без приседаний:

        [Test]
        public void Linq2ObjectTest()
        {
            var tel = new List<TestEntity>();
            var lel = new List<LookupEntity>();

            tel.Add(new TestEntity() { EntityType = TestEntityType.Type1, Id = 1 });
            tel.Add(new TestEntity() { EntityType = TestEntityType.Type1, Id = 2 });
            tel.Add(new TestEntity() { EntityType = TestEntityType.Type1, Id = 3 });

            lel.Add(new LookupEntity() { InnerEnity = tel[0] });
            lel.Add(new LookupEntity() { InnerEnity = tel[1] });

            var res = from rc in tel
                      join li in lel on rc.Id equals li.InnerEnity.Id
                      where rc.EntityType == TestEntityType.Type1
                      select rc;

            var rel = res.ToList();

            Assert.AreEqual(2, rel.Count);
            Assert.That(object.ReferenceEquals(tel[0], rel[0]));
            Assert.That(object.ReferenceEquals(tel[1], rel[1]));
        }
Re[8]: Собственно тесты
От: IT Россия linq2db.com
Дата: 04.02.10 06:17
Оценка:
Здравствуйте, ili, Вы писали:

ili>эээ... поясни для тех кто в танке и не в тренде:


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


Выделенное.

ili>да и L2O работает без приседаний:


В данном случае может и работает. Будем считать, что BLT в такой ситуации не работает бай дизайн.
Если нам не помогут, то мы тоже никого не пощадим.
Re[9]: Собственно тесты
От: ili Россия  
Дата: 04.02.10 07:15
Оценка:
Здравствуйте, IT, Вы писали:

IT>В данном случае может и работает. Будем считать, что BLT в такой ситуации не работает бай дизайн.


хозяин — барин... но с моей, профанской точки зрения простого пользователя, BLT неправильно в этом случае парсит выражение — если работает в L2O то и в BLT должно, типа догмат юзера да и абсолютно неожиданый результат получается...
Re[7]: Собственно тесты
От: ili Россия  
Дата: 04.02.10 07:17
Оценка:
Здравствуйте, IT, Вы писали:

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


спс, только есть такой вопрос — а с применеием этого аттрибута, какие запросы могут сломаться?
Re[7]: Собственно тесты
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.02.10 10:54
Оценка:
Здравствуйте, IT, Вы писали:

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


Может, надо было добавить в AssociationAtribute отдельное свойство, позволяющее явно задать тип связи?
... << RSDN@Home 1.2.0 alpha 4 rev. 1424 on Windows 7 6.1.7600.0>>
AVK Blog
Re[10]: Собственно тесты
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.02.10 10:54
Оценка:
Здравствуйте, ili, Вы писали:

ili>хозяин — барин... но с моей, профанской точки зрения простого пользователя, BLT неправильно в этом случае парсит выражение — если работает в L2O то и в BLT должно, типа догмат юзера


L2S и линк в BLT все таки не одно и то же, BLT обладает рядом дополнительных возможностей и особенностей. И иногда таки да, это особенности и возможности приводят к ощутимой разнице в поведении. Это нормально для продуктов подобной сложности.
... << RSDN@Home 1.2.0 alpha 4 rev. 1424 on Windows 7 6.1.7600.0>>
AVK Blog
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...
Пока на собственное сообщение не было ответов, его можно удалить.