linq2db status

AndrewVK AndrewVK
В выходные мы успешно мигрировали RSDN@Home с BLToolkit на linq2db. Было поправлено несколько не очень серьезных, но неприятных ошибок. В итоге полет нормальный, так что всем рекомендую как минимум новые проекты начинать на linq2db, и, по возможности мигрировать старые.
Основные исправления заключаются в смене неймспейсов и переименовании части атрибутов для разметки маппинга.
Изменений в запросах не понадобилось.
На очереди rsdn.ru
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
AK107
AK107
09.04.2013 06:10
Здравствуйте, AndrewVK, Вы писали:

AVK>В выходные мы успешно мигрировали RSDN@Home с BLToolkit на linq2db. Было поправлено несколько не очень серьезных, но неприятных ошибок. В итоге полет нормальный, так что всем рекомендую как минимум новые проекты начинать на linq2db, и, по возможности мигрировать старые.

AVK>Основные исправления заключаются в смене неймспейсов и переименовании части атрибутов для разметки маппинга.
AVK>Изменений в запросах не понадобилось.

если не сложно, скажите, чем принципиально отличается сабж? чего лишаемся/приобретаем переходя с BLToolkit на linq2db?
AndrewVK
AndrewVK
09.04.2013 08:04
Здравствуйте, AK107, Вы писали:

AK>если не сложно, скажите, чем принципиально отличается сабж?


Публичное АПИ и внутренности сильно чище и немного быстрее БЛТ. Плюс развиваться по ряду причин будет linq2db быстрее.

AK> чего лишаемся/приобретаем переходя с BLToolkit на linq2db?


Лишаемся прежде всего всяких старых методов типа ExecuteList и всяких наворотов в плане метапрограммирования.
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
AK107
AK107
10.04.2013 06:37
Здравствуйте, AndrewVK, Вы писали:

AVK>Лишаемся прежде всего всяких старых методов типа ExecuteList и всяких наворотов в плане метапрограммирования.


а DataAccessor'ы остаются?
если да, то по идее можно реализовать посредством него
    public abstract class MyDataAccessor : DataAccessor
    {
        [SqlQuery("SELECT * FROM table")]
        public abstract List<Entity> SelectSomeListofObjects(int count);
    }
AndrewVK
AndrewVK
10.04.2013 09:13
Здравствуйте, AK107, Вы писали:

AK>а DataAccessor'ы остаются?


Нет.
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
AK107
AK107
10.04.2013 11:06
Здравствуйте, AndrewVK, Вы писали:

AK>>а DataAccessor'ы остаются?


AVK>Нет.


а это уже плохо. никогла не знаешь когда понадобится хранимая процедура (по опыту они были всегда), не говоря уже о хинтах в запросах.
Jack128
Jack128
10.04.2013 11:32
Здравствуйте, AK107, Вы писали:

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


AK>>>а DataAccessor'ы остаются?


AVK>>Нет.


AK>а это уже плохо. никогла не знаешь когда понадобится хранимая процедура (по опыту они были всегда), не говоря уже о хинтах в запросах.


вроде вот так можно чистый sql выполнить:

var names = db.Query<string>("select first_name from persons").ToList();


ну и вообще https://github.com/linq2db/linq2db/blob/master/Source/Data/DataConnectionExtensions.cs
AK107
AK107
11.04.2013 08:16
Здравствуйте, Jack128, Вы писали:

J>ну и вообще https://github.com/linq2db/linq2db/blob/master/Source/Data/DataConnectionExtensions.cs


не могу найти QueryProc<T> для хранимок возвращающих скалярные типы, вижу только для получения последовательностей объектов (IDataReader-ориентированные).

можно добавить такую функцию?
AndrewVK
AndrewVK
10.04.2013 11:33
Здравствуйте, AK107, Вы писали:

AK>а это уже плохо.


Это не плохо и не хорошо, это такая идеология.

AK> никогла не знаешь когда понадобится хранимая процедура


Поддержка хранимок есть, только без акцессоров.
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
IT
IT
10.04.2013 04:14
Здравствуйте, AK107, Вы писали:

AK>а это уже плохо. никогла не знаешь когда понадобится хранимая процедура (по опыту они были всегда), не говоря уже о хинтах в запросах.


Вызов хранимых процедур автоматически генерируется T4 шаблонами.
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
AK107
AK107
10.04.2013 05:15
Здравствуйте, IT, Вы писали:

IT>Вызов хранимых процедур автоматически генерируется T4 шаблонами.


пока не добрался.

еще вопрос: как быть без NonUpdatableAttribute учитыая, что остался DataConnection.Insert?
и еще: parameterPrefix у dataProviders больше не используется?

з.ы. в остальном небольшой проект перевел в течении 1.5 часов. пока полет нормальный.
-Dm-
-Dm-
12.04.2013 04:34
Здравствуйте, AndrewVK, Вы писали:

AVK>Публичное АПИ и внутренности сильно чище и немного быстрее БЛТ. Плюс развиваться по ряду причин будет linq2db быстрее.


Иными словами 'bltoolkit все', эх надо было на Hibernate ставку делать
IT
IT
12.04.2013 01:44
Здравствуйте, -Dm-, Вы писали:

D>Иными словами 'bltoolkit все', эх надо было на Hibernate ставку делать


Тогда уж на EF.

Есть такая штука как груз обратной совместимости. Некоторые вещи просто нельзя сделать без поломки существующего кода. Нужен не просто рефакторинг кода, а изменение дизайна. L2DB как раз и есть такое изменение. Что касается поддержки и развития BLT, то если кто-то не заметил, то все фиксы и новые фичи, которые можно сделать в обоих библиотеках сегодня делаются и там и там. Так будет продолжаться пока это будет иметь смысл.
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
AndrewVK
AndrewVK
12.04.2013 04:29
Здравствуйте, -Dm-, Вы писали:

D>Иными словами 'bltoolkit все'


Нет.
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
gravatar
Аноним
09.04.2013 07:32
Здравствуйте, AndrewVK, Вы писали:
[...]
Ждём подробностей.
AndrewVK
AndrewVK
09.04.2013 08:04
Здравствуйте, <Аноним>, Вы писали:

А>Ждём подробностей.


Каких? Я вроде все основные моменты помянул? Если интересуют конкретные изменения, которые пришлось сделать в RSDN@Home, то его репозиторий публичный.
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
denis8158
denis8158
10.04.2013 05:22
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, <Аноним>, Вы писали:


А>>Ждём подробностей.


AVK>Каких? Я вроде все основные моменты помянул? Если интересуют конкретные изменения, которые пришлось сделать в RSDN@Home, то его репозиторий публичный.


Здравствуйте.

Подскажите, пожалуйста, ссылку на репозиторий rsdn'а.
AndrewVK
AndrewVK
10.04.2013 09:13
Здравствуйте, denis8158, Вы писали:

AVK>>Каких? Я вроде все основные моменты помянул? Если интересуют конкретные изменения, которые пришлось сделать в RSDN@Home, то его репозиторий публичный.


D>Подскажите, пожалуйста, ссылку на репозиторий rsdn'а.


https://bitbucket.org/andrewvk/janus
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
Дьяченко Александр
Здравствуйте, AndrewVK!

После перевода появились проблемы:

1) Некорректный HintPath:
diff -r 3b30e89cc9bf Janus.Jet/Janus.Jet.csproj
--- a/Janus.Jet/Janus.Jet.csproj    Sat Apr 06 23:42:27 2013 +0400
+++ b/Janus.Jet/Janus.Jet.csproj    Thu Apr 11 00:13:32 2013 +0800
@@ -102,7 +102,7 @@
       <Private>True</Private>
     </Reference>
     <Reference Include="linq2db">
-      <HintPath>..\Janus-Model\bin\Debug\linq2db.dll</HintPath>
+      <HintPath>..\Dependencies\linq2db\linq2db.dll</HintPath>
     </Reference>
     <Reference Include="R.SAT-Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>


Из за этого кстати на tc.rsdn.ru RSDN@Home не собирается...


2) На Sql Server не работает:

Exception с сообщением "Переполнение SqlDateTime. Должно находиться в пределах от 1/1/1753 12:00:00 AM и 12/31/9999 11:59:59 PM.".

В методе XmlBuilder.BuildMessage на запросе:
db
    .Message(
        mid,
        m =>
            new
            {
                m.UserID,
                m.UserClass,
                UserNick = m.UserNick.ToUserDisplayName(m.UserClass),
                m.Date,
                m.IsRead,
                m.IsMarked,
                m.ArticleId,
                m.Name,
                m.Subject,
                m.Message,
                m.User.Origin,
                Rating = m.Rating(),
                Smiles = m.SmileCount(),
                Agrees = m.AgreeCount(),
                Disagrees = m.DisagreeCount(),
                PenaltyType = m.Violation != null ? m.Violation.PenaltyType : 0,
                Reason = m.Violation != null ? m.Violation.Reason : null,
                ViolationDate = m.Violation != null ? m.Violation.Create : DateTime.MinValue
            });


Несмотря на то, что генерируемый SQL не содержит выделенной части, linq2db все равно создает параметр для констнты DateTime.MinValue, что в свою очередь приводит к ошибке при попытке передать в параметре это значение.

Генерируеммый SQL:
SELECT TOP (1)
    [m].[uid] as [uid1],
    [m].[uclass],
    [m].[UserNick],
    [m].[dte],
    [m].[IsRead],
    [m].[IsMarked],
    [m].[article_id],
    [m].[Name],
    [m].[Subject],
    [m].[Message],
    [t1].[Origin],
    (
        SELECT
            Sum(Convert(SmallInt, [c].[rate]) * [c].[rby])
        FROM
            [rating] [c]
        WHERE
            [m].[mid] = [c].[mid] AND [c].[rate] > 0
    ) as [c2],
    (
        SELECT
            Count(*)
        FROM
            [rating] [c3]
        WHERE
            [m].[mid] = [c3].[mid] AND [c3].[rate] = -2
    ) as [c4],
    (
        SELECT
            Count(*)
        FROM
            [rating] [c5]
        WHERE
            [m].[mid] = [c5].[mid] AND [c5].[rate] = -4
    ) as [c6],
    (
        SELECT
            Count(*)
        FROM
            [rating] [c7]
        WHERE
            [m].[mid] = [c7].[mid] AND [c7].[rate] = 0
    ) as [c8],
    CASE
        WHEN [t2].[MessageID] IS NOT NULL OR [t2].[Reason] IS NOT NULL OR [t2].[PenaltyType] IS NOT NULL OR [t2].[Create] IS NOT NULL
            THEN [t2].[PenaltyType]
        ELSE 0
    END as [c9],
    CASE
        WHEN [t2].[MessageID] IS NOT NULL OR [t2].[Reason] IS NOT NULL OR [t2].[PenaltyType] IS NOT NULL OR [t2].[Create] IS NOT NULL
            THEN [t2].[Reason]
        ELSE NULL
    END as [c10],
    CASE
        WHEN [t2].[MessageID] IS NOT NULL OR [t2].[Reason] IS NOT NULL OR [t2].[PenaltyType] IS NOT NULL OR [t2].[Create] IS NOT NULL
            THEN [t2].[Create]
        ELSE @p1
    END as [c11]
FROM
    [messages] [m]
        LEFT JOIN [users] [t1] ON [m].[uid] = [t1].[uid]
        LEFT JOIN [violations] [t2] ON [m].[mid] = [t2].[MessageID]
WHERE
    [m].[mid] = @mid


Выходов 2:
1) Отказываемся от поддержки Sql Server 2008

diff -r 3b30e89cc9bf Janus.Mssql/MssqlDriver.cs
--- a/Janus.Mssql/MssqlDriver.cs    Sat Apr 06 23:42:27 2013 +0400
+++ b/Janus.Mssql/MssqlDriver.cs    Thu Apr 11 00:23:14 2013 +0800
@@ -67,7 +67,7 @@
         /// </summary>
         public IDataProvider CreateDataProvider()
         {
-            return new SqlServerDataProvider("mssql", LinqToDB.DataProvider.SqlServer.SqlServerVersion.v2005);
+            return new SqlServerDataProvider("mssql", LinqToDB.DataProvider.SqlServer.SqlServerVersion.v2008);
         }
 
         /// <summary>


Тогда linq2db использует тип datatime2 (которого нет в Sql Server 2005) в который DateTime.MinValue запихивается и все начинает работать .

2) Допиливаем linq2db что бы для неиспользованных констант параметры не генерировались.
... << RSDN@Home 1.2.0 alpha 5 rev. 71>>
AndrewVK
AndrewVK
10.04.2013 04:50
Здравствуйте, Дьяченко Александр, Вы писали:

ДА>1) Некорректный HintPath:


Бывает. Студия слишком много себе позволяет при поиске референсов. Но к сабжу отношения не имеет.

ДА>2) На Sql Server не работает:


ДА>Exception с сообщением "Переполнение SqlDateTime. Должно находиться в пределах от 1/1/1753 12:00:00 AM и 12/31/9999 11:59:59 PM.".


Это понятно почему. Поправлял для sqlite, сломал для mssql.

ДА>Выходов 2:

ДА>1) Отказываемся от поддержки Sql Server 2008
ДА>2) Допиливаем linq2db что бы для неиспользованных констант параметры не генерировались.

Все несколько проще. Переписываем вообще без этой константы:
ViolationDate = m.Violation != null ? (DateTime?)m.Violation.Create : null


Вообще можно просто откатить правки и обновить linq2db до после этого коммита — https://github.com/linq2db/linq2db/commit/1308fe9c85139f32a3e30d9cd0d605d6da693048. Драйвер sqlite не сообщает о том, что колонка может быть null, если эта колонка получается в результате outer join, в результате дефолтный ридер, который не проверяет содержимое на null, валится на InvalidCastException.
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
Дьяченко Александр
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Дьяченко Александр, Вы писали:


ДА>>1) Некорректный HintPath:

AVK>Бывает. Студия слишком много себе позволяет при поиске референсов. Но к сабжу отношения не имеет.

Согласен, но поправить все равно нужно...

ДА>>2) На Sql Server не работает:

ДА>>Exception с сообщением "Переполнение SqlDateTime. Должно находиться в пределах от 1/1/1753 12:00:00 AM и 12/31/9999 11:59:59 PM.".
AVK>Это понятно почему. Поправлял для sqlite, сломал для mssql.

AVK>Вообще можно просто откатить правки и обновить linq2db до после этого коммита — https://github.com/linq2db/linq2db/commit/1308fe9c85139f32a3e30d9cd0d605d6da693048. Драйвер sqlite не сообщает о том, что колонка может быть null, если эта колонка получается в результате outer join, в результате дефолтный ридер, который не проверяет содержимое на null, валится на InvalidCastException.


Можно, но ситуация с неиспользуемыми параметрами, тоже не очень...
... << RSDN@Home 1.2.0 alpha 5 rev. 71>>
IT
IT
10.04.2013 06:15
Здравствуйте, Дьяченко Александр, Вы писали:

ДА>Можно, но ситуация с неиспользуемыми параметрами, тоже не очень...


Почему же не используемый? Очень даже используемый:

CASE
    WHEN [t2].[MessageID] IS NOT NULL OR [t2].[Reason] IS NOT NULL OR [t2].[PenaltyType] IS NOT NULL OR [t2].[Create] IS NOT NULL
        THEN [t2].[Create]
    ELSE @p1
END as [c11]
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
Дьяченко Александр
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, Дьяченко Александр, Вы писали:


ДА>>Можно, но ситуация с неиспользуемыми параметрами, тоже не очень...


IT>Почему же не используемый? Очень даже используемый:


IT>
IT>CASE
IT>    WHEN [t2].[MessageID] IS NOT NULL OR [t2].[Reason] IS NOT NULL OR [t2].[PenaltyType] IS NOT NULL OR [t2].[Create] IS NOT NULL
IT>        THEN [t2].[Create]
IT>    ELSE @p1
IT>END as [c11]
IT>


Ночь... смотрел не внимательно...
IT
IT
10.04.2013 06:17
Здравствуйте, Дьяченко Александр, Вы писали:

ДА>2) Допиливаем linq2db что бы для неиспользованных констант параметры не генерировались.


Костанту можно попробовать убрать так:

ViolationDate = (m.Violation != null ? m.Violation.Create : null) ?? DateTime.MinValue
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
gravatar
Аноним
11.04.2013 10:17
А что с конфигурацией DataProviders через App.config файл? Почему классы в LinqToDB.Configuration стали internal? Как подключаться к БД теперь?
IT
IT
11.04.2013 02:40
Здравствуйте, Аноним, Вы писали:

А>А что с конфигурацией DataProviders через App.config файл? Почему классы в LinqToDB.Configuration стали internal? Как подключаться к БД теперь?


Можно установить nuget linq2db.SqlServer, там есть инструкция.
gravatar
Аноним
11.04.2013 02:11
Уже несколько часов не могу понять, как настроить подключение к БД.
Пытаюсь создать DataContext, он не видит строк подключения из Web.config. СУБД — MSSQL 2012. Что я делаю не так?
[KeyNotFoundException: The given key was not present in the dictionary.]
   System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key) +3444847
   LinqToDB.Data.DataConnection.GetDataProvider(String dataProviderName) +22
   LinqToDB.DataContext..ctor(String configurationString) +21
AndrewVK
AndrewVK
11.04.2013 02:21
Здравствуйте, <Аноним>, Вы писали:

А>Пытаюсь создать DataContext, он не видит строк подключения из Web.config. СУБД — MSSQL 2012. Что я делаю не так?

А>
А>[KeyNotFoundException: The given key was not present in the dictionary.]
А>   System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key) +3444847
А>   LinqToDB.Data.DataConnection.GetDataProvider(String dataProviderName) +22
А>   LinqToDB.DataContext..ctor(String configurationString) +21
А>


А что в configurationString?
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
gravatar
Аноним
11.04.2013 02:33
Здравствуйте, AndrewVK, Вы писали:

AVK>А что в configurationString?

Имя ConnectionString'а.
AndrewVK
AndrewVK
11.04.2013 02:36
Здравствуйте, <Аноним>, Вы писали:

AVK>>А что в configurationString?

А>Имя ConnectionString'а.

А в конфигурации что под этим именем находится?
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
gravatar
Аноним
11.04.2013 03:04
Здравствуйте, AndrewVK, Вы писали:

AVK> А в конфигурации что под этим именем находится?


<connectionStrings>
  <add name="mainDB" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=mydb;Integrated Security=True;Connection Timeout=600" providerName="System.Data.SqlClient" />
</connectionStrings>
AndrewVK
AndrewVK
11.04.2013 03:16
Здравствуйте, <Аноним>, Вы писали:

providerName="SqlServer"
... << RSDN@Home 1.2.0 alpha 5 rev. 71 on Windows 8 6.2.9200.0>>
gravatar
Аноним
11.04.2013 03:32
Здравствуйте, AndrewVK, Вы писали:

AVK>
AVK>providerName="SqlServer"
AVK>


Выдает ту же самую ошибку. В дебаггере DataConnection._configurations пуст.
AK107
AK107
12.04.2013 01:16
Здравствуйте, AndrewVK, Вы писали:

AVK>Изменений в запросах не понадобилось.


я накидал unit test для тех проблем что обнаружил. буду признателен если поправите

тестовый проект
IT
IT
14.04.2013 02:54
Здравствуйте, AK107, Вы писали:

AK>тестовый проект


linq2db.Oracl ещё не добавлен в NuGet.
AK107
AK107
14.04.2013 08:40
Здравствуйте, IT, Вы писали:

AK>>тестовый проект


IT>linq2db.Oracl ещё не добавлен в NuGet.


скомпилил из исходников

BTW,
этот тест:
[Test]
        public void TestUpdateTake()
        {
            var entities = from x in db.GetTable<Entity>()
                           where x.Time < Sql.CurrentTimestamp
                           orderby x.Time descending
                           select x;
            
            entities.Take(10)
                    .Update(x => new Entity { Time = Sql.CurrentTimestamp });
        }

не проходит и в BLToolkit. давно жду и надеюсь, что поправите (пока приходится юзать хранимку )
gravatar
Аноним
12.11.2013 09:33
Здравствуйте, AndrewVK, Вы писали:

AVK>В выходные мы успешно мигрировали RSDN@Home с BLToolkit на linq2db. Было поправлено несколько не очень серьезных, но неприятных ошибок. В итоге полет нормальный, так что всем рекомендую как минимум новые проекты начинать на linq2db, и, по возможности мигрировать старые.

AVK>Основные исправления заключаются в смене неймспейсов и переименовании части атрибутов для разметки маппинга.
AVK>Изменений в запросах не понадобилось.
AVK>На очереди rsdn.ru

Подскажите, как работает .LoadWith().
Такой код не вытаскивает
using (var db = new testDB())
            {
                var q = db.T1.LoadWith(t => t.T2).Select(t => t);

                foreach (var t1 in q)
                {
                    foreach (var t2 in t1.T2)
                        Console.WriteLine(t1.Name + " -- " + t2.Name);
                }
            }
IT
IT
14.11.2013 03:13
Здравствуйте, Аноним, Вы писали:

А>Подскажите, как работает .LoadWith().


Пока не работает.