Re[18]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 19:40
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

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


G>>Пфф, QFragmet не типизирован. Нет никаких гарантий, что этот фрагмент будет присоединен к выборке из Customer. Более того, нет гарантии что алиас для таблицы Customer будет именно "c". Про проверки при компиляции вообще молчу.

AP>Ты вообще читаешь? Третий раз повторяю, есть автоматическая проверка всех запросов.

Да повторять можешь сколько влезет, но на твоем фрагменте SQL выругается на алиас "c". Попробуй скопировать его в Management Studio и проверь.

В этом собственно и проблема текстовых запросов — они должны быть литералами в коде, чтобы их можно было проверить, а это сильно ограничивает возможности программы или множит количество запросов, что усложняет сопровождение.
Re[19]: Entity Framework за! и против!
От: Alexander Polyakov  
Дата: 24.06.14 19:53
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

G>Да повторять можешь сколько влезет, но на твоем фрагменте SQL выругается на алиас "c". Попробуй скопировать его в Management Studio и проверь.

G>В этом собственно и проблема текстовых запросов — они должны быть литералами в коде, чтобы их можно было проверить, а это сильно ограничивает возможности программы или множит количество запросов, что усложняет сопровождение.
Ты, кажется, не понимаешь. Если я в GoldCutomer заменю c на c2, то автоматическая проверка мне покажет, где надо еще поправить.
Re[2]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 20:02
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

AP>По поводу Dapper-а и LINQ. Вот разработчик stackoverflow детально описывает real world код.

AP>700ms только на то, чтобы сформировать строку запроса (до отправки в СУБД).... 700ms ... 700ms ...
Там такой код для генерации Linq запроса, что сходу руками на SQL его невозможно написать.

Кстати работу с тегами в итоге переписали на отдельный движок, ибо SQL становится плохо от такого количества джоинов.

AP>Процитирую Sam Saffron:

AP>

AP> I now have SQL I can comfortably work with in SQL Management Studio. In SQL Management Studio, I am superman. I can mold the query into the shape I want it and I can profile it.
AP>http://discuss.samsaffron.com/t/a-day-in-the-life-of-a-slow-page-at-stack-overflow/21

Ага, это как раз после написания эффективного запроса с помощью Linq2SQL.

Ты сам доказываешь то, с чем пытаешься спорить
Re[20]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 20:16
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

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


G>>Да повторять можешь сколько влезет, но на твоем фрагменте SQL выругается на алиас "c". Попробуй скопировать его в Management Studio и проверь.

G>>В этом собственно и проблема текстовых запросов — они должны быть литералами в коде, чтобы их можно было проверить, а это сильно ограничивает возможности программы или множит количество запросов, что усложняет сопровождение.
AP>Ты, кажется, не понимаешь. Если я в GoldCutomer заменю c на c2, то автоматическая проверка мне покажет, где надо еще поправить.

Да, не понимаю, покажи компилируемый пример с реальной проверкой. Тем более GoldCutomer может быть совсем в другой сборке и вообще не знать о том какой там исходный запрос.
Re[3]: Entity Framework за! и против!
От: Alexander Polyakov  
Дата: 24.06.14 20:21
Оценка: -2
Здравствуйте, gandjustas, Вы писали:

G>Ага, это как раз после написания эффективного запроса с помощью Linq2SQL.

Они перешли на Dapper. Linq2SQL жутко тормозил.
Re[4]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 20:29
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

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


G>>Ага, это как раз после написания эффективного запроса с помощью Linq2SQL.

AP>Они перешли на Dapper. Linq2SQL жутко тормозил.

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

Глупо думать что
1) У тебя будет такая нагрузка что оверхед Linq2SQL или EF будет хоть как-то заметен.
2) Ты сможешь сразу написать все запросы наиболее эффективным образом под каждый сценарий, не сдохнув на поддержке этого дела.
Re[5]: Entity Framework за! и против!
От: Alexander Polyakov  
Дата: 24.06.14 21:01
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

G>Угу только сначала написали все на Linq2SQL и больше года на нем прожили при нагрузках, которым не видать большинству веб-проектов.

G>Глупо думать что
G>1) У тебя будет такая нагрузка что оверхед Linq2SQL или EF будет хоть как-то заметен.
G>2) Ты сможешь сразу написать все запросы наиболее эффективным образом под каждый сценарий, не сдохнув на поддержке этого дела.
О чем ты ....
700 миллисекунд на простейшей страничке с вкладками и одним текстовым полем http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created
Re[6]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 21:10
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

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


G>>Угу только сначала написали все на Linq2SQL и больше года на нем прожили при нагрузках, которым не видать большинству веб-проектов.

G>>Глупо думать что
G>>1) У тебя будет такая нагрузка что оверхед Linq2SQL или EF будет хоть как-то заметен.
G>>2) Ты сможешь сразу написать все запросы наиболее эффективным образом под каждый сценарий, не сдохнув на поддержке этого дела.
AP>О чем ты ....
AP>700 миллисекунд на простейшей страничке с вкладками и одним текстовым полем http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created

Еще раз: такой запрос как " на простейшей страничке с вкладками и одним текстовым полем " ты в жизни руками на SQL не напишешь. А если напишешь — замучаешься поддерживать и никакой Dapper не поможет.

Кстати в EF вроде как сделали компиляцию запросов на порядок более быстрой.
Re[6]: Entity Framework за! и против!
От: fddima  
Дата: 24.06.14 21:52
Оценка: +1
Здравствуйте, Alexander Polyakov, Вы писали:

AP>О чем ты ....

AP>700 миллисекунд на простейшей страничке с вкладками и одним текстовым полем http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created
Ты упускаешь другое.
Скажем в БД с row-level security — требуется одно.
В SO — требуется совершенно иное. Фактически реально сложных запрсов у них и нет.
Dapper и им подробные — это ошибка природы. Это для тех, кто не понимает, что строки нужно эскейпить, и как правильно это делать. Отстрелить себе яйца с помощью dapper-а — очень легко.
LINQ — же предлагает очень высокоуровненую абстракцию. Со всеми возможными вариантами, я вот делал недавно load testing — я получил, что сервис который генерирует (через linq2db) запросы — тратит <20% процессора (не факт что на LINQ, — вообще). При этом сиквел выжрает — 80% процессора (и то только в том случае если вся база лежит в памяти — а иначе жуткий пенальти по IO который не виден вообще на фоне 700ms).
Так и получаем, что БД — способна обслужить дикое число запросов. Но не стоит забывать что это запросы к реальной БД, к реальному серверу, пусть даже и distributed по новому слову техники. Чем сложнее запрос — тем менее заметны затраты на LINQ.
Ну а если мерить простые запросы (привет dapper) — то и linq2db+реальная БД заточенная на реальную нагрузку на i7-4770 + 32GB RAM позволяет сделать почти 1000 запросов в секунду (по ~10GB БД). При чём итоговая цифра исключительно зависит от того где находятся данные в БД. Если это холодный старт БД и хранилище — HDD — то 3 запроса в секунду. Ну я так, что бы осознали разницу, что дело не в LINQ. А реально дело в RAM и IO.
Да — на фоне — моя тачка показывает теоретический максимум в 20K запросов в секунду. И это кстати на нифига не шустром ASP.NET WebApi. (Правда это с owin-self-hosting — на честном IIS — показатели становятся в 15K). Впрочем это чисто научный интерес — не суть на реал, но даёт ещё одну точку отправки.
Да. Это всё к тому, что — я х.з. что там были у SO проблемы — скорее всего — вылечили какую-то проблему, но не искоренили её. Как уже gandjustas сказал — там были большие бока с тегами. Информация общедоступна если что.
На фоне моих тестов и моих потребностей — я вижу что LINQ в общем — будет тратить <5% от времени обработки запроса. Что тут ещё говорить. При том что я ставлю высокую планку на время обработки запроса — где-то в 30ms.
А самое главное — LINQ-компиляция запросов — отлично масштабируется. Поставить больше "фронтовых" серверов может быть гораздо дешевле (ну а иметь как минимум 2 нужно всё равно иметь, из-за fault tolerance). А вот обеспечить нормальную и правильную логику работы приложения в кластере (при этом по возможности не нагружая медленную БД) — это уже другого характера вопрос.
Поэтмоу для меня — LINQ — отличный инструмент. В нём не всё как мне хочется — но, то что глупо писать хранимки под динамические (или полу-динамические) запросы — это факт. Более того — и у LINQ и у SQL — есть больше шансов выполнить запрос именно так как надо (применив актуальную статистику), нежели когда используем зранимку. Ну а хранимка with recompile будет стоить тоже дорого.
Подитожить я не могу — может gandjustas сможет это сделать более кратко. Заранее, спасибо!
Re[7]: Entity Framework за! и против!
От: fddima  
Дата: 24.06.14 21:56
Оценка:
Здравствуйте, fddima, Вы писали:

F> Ну а если мерить простые запросы (привет dapper) — то и linq2db+реальная БД заточенная на реальную нагрузку на i7-4770 + 32GB RAM позволяет сделать почти 1000 запросов в секунду (по ~10GB БД). При чём итоговая цифра исключительно зависит от того где находятся данные в БД. Если это холодный старт БД и хранилище — HDD — то 3 запроса в секунду. Ну я так, что бы осознали разницу, что дело не в LINQ. А реально дело в RAM и IO.

Я извиняюсь — я имел ввиду что не простые запросы. У меня сиквел справляется с почти 1000 запросов в секунду с неочень простыми запросами (они аггрегирующие и затрагивают много данных). Безусловно с простыми запросами навроде select * from something where id = ... справляется крайне быстро, ну от 7000+ (запросов в секунду), и возможно больше.
И то — ессно я не мерял чисто сиквел.
Re[2]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 22:33
Оценка: 6 (2)
Здравствуйте, Alexander Polyakov, Вы писали:

AP>По поводу Dapper-а и LINQ. Вот разработчик stackoverflow детально описывает real world код.

AP>700ms только на то, чтобы сформировать строку запроса (до отправки в СУБД).... 700ms ... 700ms ...

AP>Еще ссылки:

AP>http://discuss.samsaffron.com/t/how-i-learned-to-stop-worrying-and-write-my-own-orm/22
AP>http://discuss.samsaffron.com/t/a-day-in-the-life-of-a-slow-page-at-stack-overflow/21

AP>Вот реальные причины почему сделали Dapper.


AP>Процитирую Sam Saffron:

AP>

AP> I now have SQL I can comfortably work with in SQL Management Studio. In SQL Management Studio, I am superman. I can mold the query into the shape I want it and I can profile it.
AP>http://discuss.samsaffron.com/t/a-day-in-the-life-of-a-slow-page-at-stack-overflow/21


Ты немного удивишься и расстроишься...
Я вот взял Entity Framework последней версии, код из статьи, сгенерировал классы и вот что получилось:
Для начала классы:
  Скрытый текст
    public enum Filter
    {
        Active,
        Suggested,
        Merge
    }

    public enum Tab
    {
        Newest,
        Master,
        Synonym,
        Votes,
        Creator,
        Renames
    }

    public class DB : DbContext
    {
        public DbSet<TagSynonym> TagSynonyms { get; set; }
        public DbSet<Tag> Tags { get; set; }
        public DbSet<UserTagTotal> UserTagTotals { get; set; }
        public DbSet<User> Users { get; set; }
    }

    public class User
    {
        public int Id { get; set; }
        public string DisplayName { get; set; }
    }

    public class Tag
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public int Count { get; set; }
    }

    public class TagSynonym
    {
        public DateTime? ApprovalDate { get; set; }

        [Key]
        [Column(Order = 2)] 

        public string TargetTagName { get; set; }

        public DateTime CreationDate { get; set; }

        public string AutoRenameCount { get; set; }

        [Key]
        [Column(Order = 1)] 

        public string SourceTagName { get; set; }

        public int Score { get; set; }
        public int OwnerUserId { get; set; }
    }

    public class UserTagTotal
    {
        [Key]
        [Column(Order = 1)]
        public int TagId { get; set; }

        [Key]
        [Column(Order = 2)]
        public int UserId { get; set; }

        public int TotalAnswerScore { get; set; }
    }


Сам код выборки из поста, слега адаптированный:
  Скрытый текст
static void TestEf(DB db, Filter filter, Tab tab, bool isAnonymous, bool isModerarator, int currentUserId, string search)
    {
        var baseQuery = db.TagSynonyms as IQueryable<TagSynonym>;

        if (filter == Filter.Active)
        {
            baseQuery = baseQuery.Where(t => t.ApprovalDate != null);
        }
        else if (filter == Filter.Suggested)
        {
            baseQuery = baseQuery.Where(t => t.ApprovalDate == null);
            if (!isAnonymous && !isModerarator)
            {
                // exclude ones I can not vote on
                baseQuery = from ts in db.TagSynonyms
                            join tags in db.Tags on ts.TargetTagName equals tags.Name
                            join stats in db.UserTagTotals on
                                new { Id = tags.Id, UserId = currentUserId }
                                equals
                                new { Id = stats.TagId, UserId = stats.UserId }
                            where ts.ApprovalDate == null && stats.TotalAnswerScore > 100
                            select ts;
            }
        }

        switch (tab)
        {
            case Tab.Newest:
                baseQuery = baseQuery.OrderByDescending(s => s.CreationDate);
                break;
            case Tab.Master:
                baseQuery = baseQuery.OrderBy(t => t.TargetTagName).ThenBy(t => t.AutoRenameCount);
                break;
            case Tab.Synonym:
                baseQuery = baseQuery.OrderBy(t => t.SourceTagName).ThenBy(t => t.AutoRenameCount);
                break;
            case Tab.Votes:
                baseQuery = baseQuery.OrderByDescending(t => t.Score).ThenBy(t => t.TargetTagName).ThenBy(t => t.AutoRenameCount);
                break;
            case Tab.Creator:
                baseQuery = (
                                from s in baseQuery
                                join users1 in db.Users on s.OwnerUserId equals users1.Id into users1temp
                                from users in users1temp.DefaultIfEmpty()
                                orderby users == null ? "" : users.DisplayName
                                select s
                            );
                break;
            case Tab.Renames:
                baseQuery = baseQuery.OrderByDescending(t => t.AutoRenameCount).ThenBy(t => t.TargetTagName);
                break;

            default:
                break;
        }

        if (search != null)
        {
            baseQuery = baseQuery.Where(t => t.SourceTagName.Contains(search) || t.TargetTagName.Contains(search));
        }


        var query = from synonym in baseQuery
                    join sourceTagsTemp in db.Tags on synonym.SourceTagName equals sourceTagsTemp.Name into sourceTagsTemp1
                    join targetTagsTemp in db.Tags on synonym.TargetTagName equals targetTagsTemp.Name into targetTagsTemp1
                    from sourceTag in sourceTagsTemp1.DefaultIfEmpty()
                    from targetTag in targetTagsTemp1.DefaultIfEmpty()
                    where filter != Filter.Merge || (synonym.ApprovalDate != null && sourceTag != null && sourceTag.Count > 0)
                    select new { SourceTag = sourceTag, TargetTag = targetTag, TagSynonym = synonym };
        query.Load();
    }
}


И небольшой тестовый метод, который случайным образом прогоняет выборку для разных значений параметров:
  Скрытый текст
Честно переоткрывает контекст и соединение
static TimeSpan RandomTest()
{
    using (var db = new DB())
    {
        var rnd = new Random();

        var filterValues = (Filter[]) Enum.GetValues(typeof (Filter));
        var filter = filterValues[rnd.Next(filterValues.Length)];

        var tabValues = (Tab[]) Enum.GetValues(typeof (Tab));
        var tab = tabValues[rnd.Next(filterValues.Length)];

        var sw = Stopwatch.StartNew();
        TestEf(db, filter, tab, rnd.Next(2) == 0, rnd.Next(2) == 0, rnd.Next(1000),
            rnd.Next(2) == 0 ? "aaaa" : "");
        sw.Stop();
        return sw.Elapsed;
    }
}


Функция Main:

static void Main(string[] args)
{
    Console.WriteLine("Warming up");

    for (int i = 0; i < 1000; i++)
    {
        RandomTest();
    }

    Console.WriteLine("Testing");
    var results = new List<TimeSpan>();
    for (int i = 0; i < 1000; i++)
    {
        results.Add(RandomTest());
    }

    Console.WriteLine("Average {0}ms per query", results.Average(ts => ts.TotalMilliseconds));
}



Результат (вдохни поглубже):
Average 2,9131428ms per query


Еще раз по-русски — 2,8 миллисекунд на запрос. Это не только компиляция, это еще открыть соединение (взять из пула, но тоже чего-то стоит) и сбегать в базу (она пустая, но время раундтрипа считается).

Если ты не в курсе, то еще в EF5 прикрутили кеширование скомпилированных Linq запросов, поэтому время амотризированное время компиляции Linq выражений равно нулю.

Если не веришь, то создай консольное приложение в VS2013, установи EF последней версии и скопируй весь код к себе.
Re[3]: Entity Framework за! и против!
От: fddima  
Дата: 24.06.14 22:42
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Еще раз по-русски — 2,8 миллисекунд на запрос. Это не только компиляция, это еще открыть соединение (взять из пула, но тоже чего-то стоит) и сбегать в базу (она пустая, но время раундтрипа считается).

G>Если ты не в курсе, то еще в EF5 прикрутили кеширование скомпилированных Linq запросов, поэтому время амотризированное время компиляции Linq выражений равно нулю.
Ох как. Ну в BLT/linq2db такое то давно уже было. Я имел небольшой опыт с EF, скорее всего с 5-ым. Не могу сказать, что супер плохо — но удовольствия тоже не доставил.

PS: Миграции — бред. Не нужны они. Ими заниматься на первом этапе — дольше. На последующих — нужны всё равно нормальные скрипты. Ну и ессно, мы не ведем речь о приложениях которые сами собой там что-то могут преобразовать — им такого позволения "свыше" не дают. Поэтому — механизм интересный (известный опять же задолго до EF) — но муторный.
Re[4]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 22:55
Оценка: 3 (1)
Здравствуйте, fddima, Вы писали:

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


G>>Еще раз по-русски — 2,8 миллисекунд на запрос. Это не только компиляция, это еще открыть соединение (взять из пула, но тоже чего-то стоит) и сбегать в базу (она пустая, но время раундтрипа считается).

G>>Если ты не в курсе, то еще в EF5 прикрутили кеширование скомпилированных Linq запросов, поэтому время амотризированное время компиляции Linq выражений равно нулю.
F> Ох как. Ну в BLT/linq2db такое то давно уже было. Я имел небольшой опыт с EF, скорее всего с 5-ым. Не могу сказать, что супер плохо — но удовольствия тоже не доставил.
Где было?

F> PS: Миграции — бред. Не нужны они. Ими заниматься на первом этапе — дольше.

Да ладно? я вот в примере не создавал базу, ef сам сгенерил. Если я реальный проект буду делать, то включу автомагические миграции и первый месяц вообще не буду думать о том как базу на продакшене обновлять.

F>На последующих — нужны всё равно нормальные скрипты.

Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.


F>Ну и ессно, мы не ведем речь о приложениях которые сами собой там что-то могут преобразовать — им такого позволения "свыше" не дают.

Откуда это "свыше" ? Какие-то религиозные убеждения.

F>Поэтому — механизм интересный (известный опять же задолго до EF) — но муторный.

Наоборот, снимает нереальное количество геморроя при разработке и деплое.

Вообще удивительно что 90% комментаторов тупо не доверяют EF, но никаких объективных факторов привести не могут.
Причем не только тут, вот на хабре сегодня же: http://habrahabr.ru/post/227351/#comment_7713649
Re[5]: Entity Framework за! и против!
От: IT Россия linq2db.com
Дата: 24.06.14 23:08
Оценка:
Здравствуйте, gandjustas, Вы писали:

F>>На последующих — нужны всё равно нормальные скрипты.

G>Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.

Что с данными во время миграции?
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Entity Framework за! и против!
От: fddima  
Дата: 24.06.14 23:17
Оценка:
Здравствуйте, gandjustas, Вы писали:

F>> Ох как. Ну в BLT/linq2db такое то давно уже было. Я имел небольшой опыт с EF, скорее всего с 5-ым. Не могу сказать, что супер плохо — но удовольствия тоже не доставил.

G>Где было?
Ты сейчас про что? Кеширование запросов было и есть в BLToolkit/linq2db. Есть подобие автоматического, есть и ручное. Насчет ручного — я точно не ошибаюсь — а там дальше — нужно IT призывать. Благо ж форумчанин наш.

G>Да ладно? я вот в примере не создавал базу, ef сам сгенерил. Если я реальный проект буду делать, то включу автомагические миграции и первый месяц вообще не буду думать о том как базу на продакшене обновлять.

А что потом? С таблицами миллионниками не справлялись даже database project от МС (они тупо их рекрейтили, что ессно недопустимо). Я весьма не против такого механизма, но — он должен быть жостко контролируемым. То, из того что я видел в EF — было из рук вон плохо. Что касается сложных конверсий — то это вообще издевательство — заставлять разработчика хренячить скрипты где-то там в приложении (а автоматически модель просто не сможет измениться, т.к. таки да — реструктуризация) — то я так и не понял. Ничего миграции нового, кроме как выполнить реструктуризационные скрипты — не предлагают. Ну и ессно не могут. А примитивыне вещи навроде добавили колонку — с этим благо справляются не только миграции, но и всякие внешние тулзы, которые работают только с БД. Так что х.з. х.з. х.з.

F>>На последующих — нужны всё равно нормальные скрипты.

G>Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.
Руками писать так и не надо. Руками нужно писать скрипты создания таблиц и только. И они нужны для последователей. Никому нафиг не нужны эти миграции через 10 лет. Если ты не работал в проекте которому более 20 лет — то наверное не поймёшь важность и исторических решений, и вообще на саппорт смотришь иначе. Я имел такое удовольствие вот. Хотя и твой опыт я под сомнение не ставлю. (Ну честно, не обессуть).

F>>Ну и ессно, мы не ведем речь о приложениях которые сами собой там что-то могут преобразовать — им такого позволения "свыше" не дают.

G>Откуда это "свыше" ? Какие-то религиозные убеждения.
Да. Свыше — значит что новая версия продукта разворачивается у клиента, и никакого там DDL в принципе быть не может. Т.е. оно может, но только по согласованию. Соответственно приходим к тому что пофигу каким именно образом накатить изменения. Но точно что неприемлимо — это натихую накатить новую версию продукта которая начнёт чудить в БД.

F>>Поэтому — механизм интересный (известный опять же задолго до EF) — но муторный.

G>Наоборот, снимает нереальное количество геморроя при разработке и деплое.
Часть снимет. В перспективе — только добавит. Хотя — зависит от размера.

G>Вообще удивительно что 90% комментаторов тупо не доверяют EF, но никаких объективных факторов привести не могут.

G>Причем не только тут, вот на хабре сегодня же: http://habrahabr.ru/post/227351/#comment_7713649
Я резко против EF. Я его могу воспринять только как неизбежное зло. С другой стороны, что какасается технологии/идеи в целом (я о LINQ) — то тут я вижу только преимущества. В мире котором мы живём, и так часто нет выбора — а тут — хочешь — "правильный" linq2sql, хочешь — EF, — хочешь linq2db. В общем — выбирай, что хочешь называется. Конечной принципиальной разницы нет. Поэтому я могу понять кто неприемлит EF — но пока только ты его защищаешь, и требуешь аргументов от других. В этом смысле — тебе никто и ничего не должен и как это водится — все останутся при своём мнении.
Более того — аргументы ни за ни против не нужны — нужен комплексный анализ. По фичам. По скорости. По х.з. чем ещё, до чего мой мозг даже не додумается.
Поэтому именно EF — нахваливать — нет уж. Бред. У них всегда был бред. И модель у них бредовая. Это лично мой взгляд, как ты видишь — в этом конструктива нет — так что не нужно даже пытаться переубеждать.

PS: Неудачный опыт с EF был неудачен не сколько с сами EF, а сколько со спорными решениями вокруг него. На самом деле — отличный инструмент, что бы взять и заюзать. Мне допустим EF абсолютно не подходит, потому что, в случае проблем (а практика показала — что они всегда есть и везде, особенно с такими сложными штуками) — в предпочту код, в котором я хоть немного, но понимаю — а это — linq2db.
Re[6]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 23:19
Оценка:
Здравствуйте, IT, Вы писали:

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


F>>>На последующих — нужны всё равно нормальные скрипты.

G>>Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.

IT>Что с данными во время миграции?


Если удаляешь колонки — данные удаляются, если меняешь тип, то пытается конвертировать, если не получается — отваливается. Никаких пересозданий колонок сам не делает.
Так как все в DDL транзакции, то вполне безопасно.

Если связи меняешь, то пишешь скрипт руками.

EF генерит скрипт миграции, который можно посмотреть.
Re[7]: Entity Framework за! и против!
От: fddima  
Дата: 24.06.14 23:35
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Если удаляешь колонки — данные удаляются, если меняешь тип, то пытается конвертировать, если не получается — отваливается. Никаких пересозданий колонок сам не делает.

G>Так как все в DDL транзакции, то вполне безопасно.
G>Если связи меняешь, то пишешь скрипт руками.
G>EF генерит скрипт миграции, который можно посмотреть.
Я тебе скажу из практики. Реальных "миграций", т.е. с серьёзным затрагиванием структуры БД я написал штук 5. При этом даже с этими всеми миграциями — наши продукты жили так как их и не было. Везло. Правда. Но при этом — бред из EF — был бы абсолютно бесполезный.
Но была одна совсем сильная миграция.
Так вот — суть её — это из Nx профилей сделать Mx профилей, где M<N, при том, что в профиле X записей (может отличаться для любого профиля). Уменьшаем их количество по принципу полного совпадения. Соответственно где-то вообще вводится понятие как профиль, и проставляется. Иначе говоря структура БД меняется кардинально, а конечные пользователи вообще вновь видят новое понятие, как профиль. Учитывая, что такая конверсия, даже на топовом железе могла занять скажем минут 30 — то выкладывать такие вещи в миграции — бред. Прежде чем такое сотворить — нужно как минимум сделать бэкап БД (а иначе вообще никто не будет обновляться). И т.п. Поэтому миграции — они круты при мелочах. А реальные изменения — они всё равно покрыть не могут. Возможность исполнять скрипты — я отмечу — у нас у всех и так была. В том числе делать это версионно (хоть руками, хоть с помощью других средств). Поэтому особо ахрененного преимущества в миграциях — я не вижу. Мы о ком забоится? Разработчик до 1 версии всегда способен пересоздать базу хоть 100 раз на день (и нагенерить данные, если необходимо). А в нормальном прадакшне — могут (и будут) требовать вменяемые скрипты апгрейда. А скрипты апгрейда в разработке как раз и не нужны.
В то же время — тулзы которые автоматом деплоят структуру БД — работают. И от МС куча. И вообще. Но работают они именно так же паршиво как я описал.
Учитесь культуре разных проектов, и не навязывайте всем свою. Ваша — многим не подходит.
Re[6]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.14 23:43
Оценка:
Здравствуйте, fddima, Вы писали:

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


F>>> Ох как. Ну в BLT/linq2db такое то давно уже было. Я имел небольшой опыт с EF, скорее всего с 5-ым. Не могу сказать, что супер плохо — но удовольствия тоже не доставил.

G>>Где было?
F> Ты сейчас про что? Кеширование запросов было и есть в BLToolkit/linq2db. Есть подобие автоматического, есть и ручное. Насчет ручного — я точно не ошибаюсь — а там дальше — нужно IT призывать. Благо ж форумчанин наш.
Ручное в EF и Linq2SQL всегда было.

G>>Да ладно? я вот в примере не создавал базу, ef сам сгенерил. Если я реальный проект буду делать, то включу автомагические миграции и первый месяц вообще не буду думать о том как базу на продакшене обновлять.

F> А что потом? С таблицами миллионниками не справлялись даже database project от МС (они тупо их рекрейтили, что ессно недопустимо). Я весьма не против такого механизма, но — он должен быть жостко контролируемым.
В ef нет пересоздания вообще. Database project пересоздает таблицы только если ему явно разрешишь, по умолчанию никогда данные не трогает. Я знаю что многие ставили флаги, не зная их смысла, а потом удивлялись.

F>То, из того что я видел в EF — было из рук вон плохо.

Что именно?

F>Что касается сложных конверсий — то это вообще издевательство — заставлять разработчика хренячить скрипты где-то там в приложении (а автоматически модель просто не сможет измениться, т.к. таки да — реструктуризация) — то я так и не понял. Ничего миграции нового, кроме как выполнить реструктуризационные скрипты — не предлагают. Ну и ессно не могут. А примитивыне вещи навроде добавили колонку — с этим благо справляются не только миграции, но и всякие внешние тулзы, которые работают только с БД. Так что х.з. х.з. х.з.

То ест писать скрипты используя EF это плохо, а писать скрипты, не используя EF это нормально?


F>>>На последующих — нужны всё равно нормальные скрипты.

G>>Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.
F> Руками писать так и не надо. Руками нужно писать скрипты создания таблиц и только. И они нужны для последователей.
Есть такое важное свойство, как идемпотентность. накатывание скрипта миграции можно повторять много раз, а результат будет такой же, как от одного (успешного). Скрипты по умолчанию не сохраняются, накатываются и все.


F> Никому нафиг не нужны эти миграции через 10 лет. Если ты не работал в проекте которому более 20 лет — то наверное не поймёшь важность и исторических решений, и вообще на саппорт смотришь иначе. Я имел такое удовольствие вот. Хотя и твой опыт я под сомнение не ставлю. (Ну честно, не обессуть).

В чем смысл этой фразы? "Давайте не использовать удобный инструмент, ибо через 10 лет не нужен будет". Странно что вообще интернет появился при таком подходе.


F>>>Ну и ессно, мы не ведем речь о приложениях которые сами собой там что-то могут преобразовать — им такого позволения "свыше" не дают.

G>>Откуда это "свыше" ? Какие-то религиозные убеждения.
F> Да. Свыше — значит что новая версия продукта разворачивается у клиента, и никакого там DDL в принципе быть не может. Т.е. оно может, но только по согласованию. Соответственно приходим к тому что пофигу каким именно образом накатить изменения. Но точно что неприемлимо — это натихую накатить новую версию продукта которая начнёт чудить в БД.
Почему не может? Если это DWH, который клиентом и создан, то в любом случае надо ориентироваться на его структуру, а не пилить свою. А если это база единолично приложением управляется (наиболее частый сценарий), то на кой там что-то согласовывать? И с кем? DBA, которые нифига не понимают в ваших таблицах?

F>>>Поэтому — механизм интересный (известный опять же задолго до EF) — но муторный.

G>>Наоборот, снимает нереальное количество геморроя при разработке и деплое.
F> Часть снимет. В перспективе — только добавит. Хотя — зависит от размера.
Не вижу причин почему может добавить. Рано или поздно придется писать SQL, других способов нет. Чем позднее придется, тем больше времени заниматься полезными вещами.


G>>Вообще удивительно что 90% комментаторов тупо не доверяют EF, но никаких объективных факторов привести не могут.

G>>Причем не только тут, вот на хабре сегодня же: http://habrahabr.ru/post/227351/#comment_7713649
F> Я резко против EF. Я его могу воспринять только как неизбежное зло. С другой стороны, что какасается технологии/идеи в целом (я о LINQ) — то тут я вижу только преимущества. В мире котором мы живём, и так часто нет выбора — а тут — хочешь — "правильный" linq2sql, хочешь — EF, — хочешь linq2db. В общем — выбирай, что хочешь называется. Конечной принципиальной разницы нет. Поэтому я могу понять кто неприемлит EF — но пока только ты его защищаешь, и требуешь аргументов от других. В этом смысле — тебе никто и ничего не должен и как это водится — все останутся при своём мнении.
Профессионалы тем и отличаются от дилетантов, что могут мнение аргументировать. К сожалению ни одного объективного аргумента от противников EF и Linq-to-Database-ORM не увидел вообще. Тем не менее хочется с профессионалами общаться, иначе бы сидел в баре, а не на форуме.

F> Более того — аргументы ни за ни против не нужны — нужен комплексный анализ. По фичам. По скорости. По х.з. чем ещё, до чего мой мозг даже не додумается.

Разве анализ помогает против религиозных аргументов?

F> Поэтому именно EF — нахваливать — нет уж. Бред. У них всегда был бред. И модель у них бредовая. Это лично мой взгляд, как ты видишь — в этом конструктива нет — так что не нужно даже пытаться переубеждать.

Я вот и фичи приводил, и тест производительности и все равно ни одного объективного аргумента, только "бред".

F> PS: Неудачный опыт с EF был неудачен не сколько с сами EF, а сколько со спорными решениями вокруг него. На самом деле — отличный инструмент, что бы взять и заюзать. Мне допустим EF абсолютно не подходит, потому что, в случае проблем (а практика показала — что они всегда есть и везде, особенно с такими сложными штуками) — в предпочту код, в котором я хоть немного, но понимаю — а это — linq2db.

В чем же такая огромная разница между EF и linq2db? Последний я, к сожалению, юзал еще до старта этой темы.
Re[8]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.06.14 00:01
Оценка:
Здравствуйте, fddima, Вы писали:

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


G>>Если удаляешь колонки — данные удаляются, если меняешь тип, то пытается конвертировать, если не получается — отваливается. Никаких пересозданий колонок сам не делает.

G>>Так как все в DDL транзакции, то вполне безопасно.
G>>Если связи меняешь, то пишешь скрипт руками.
G>>EF генерит скрипт миграции, который можно посмотреть.
F> Я тебе скажу из практики. Реальных "миграций", т.е. с серьёзным затрагиванием структуры БД я написал штук 5. При этом даже с этими всеми миграциями — наши продукты жили так как их и не было. Везло. Правда. Но при этом — бред из EF — был бы абсолютно бесполезный.

F> Но была одна совсем сильная миграция.

F> Так вот — суть её — это из Nx профилей сделать Mx профилей, где M<N, при том, что в профиле X записей (может отличаться для любого профиля). Уменьшаем их количество по принципу полного совпадения. Соответственно где-то вообще вводится понятие как профиль, и проставляется. Иначе говоря структура БД меняется кардинально, а конечные пользователи вообще вновь видят новое понятие, как профиль.
Всего-то?

F>Учитывая, что такая конверсия, даже на топовом железе могла занять скажем минут 30 — то выкладывать такие вещи в миграции — бред. Прежде чем такое сотворить — нужно как минимум сделать бэкап БД (а иначе вообще никто не будет обновляться). И т.п.

Какой-то неправильный подход.
Надо было:
1) Создать таблицу для M
2) Сделать триггер\эвент в приложении, который при добавлении\изменении записи в N реплицирует данные в M
3) Выкатить эту версию, отладить, проверить что в M данные корректные
4) Сделать скрипт для миграции всех записей N в M
5) Перелить данные, проверить что все ОК
6) Поменять код для работы с новой таблицей, задеплоить изменения.

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

У меня были миграции, которые длились по 48 часов без права на ошибку. Бекапы то были, но остановить работу сервиса было нельзя. Там я навегда расстался с мыслью об "одной большой реструктуризации базы".

F>Поэтому миграции — они круты при мелочах.

Правильно, вот и разбивай крупные миграции, на мелочи.

F>А реальные изменения — они всё равно покрыть не могут.

Ну смотря что считать "реальными изменениями".

F>Возможность исполнять скрипты — я отмечу — у нас у всех и так была. В том числе делать это версионно (хоть руками, хоть с помощью других средств). Поэтому особо ахрененного преимущества в миграциях — я не вижу.

Миграции синхронизируют исполнение скриптов с изменением кода. Для этого они и были придуманы.

F>Мы о ком забоится? Разработчик до 1 версии всегда способен пересоздать базу хоть 100 раз на день (и нагенерить данные, если необходимо). А в нормальном прадакшне — могут (и будут) требовать вменяемые скрипты апгрейда. А скрипты апгрейда в разработке как раз и не нужны.

Вот и получается ситуация что в базе разработчика одна структура, на продакшене другая, а в коде третья. И не ясно кто прав, хотя в команде только 3 человека.

F> В то же время — тулзы которые автоматом деплоят структуру БД — работают. И от МС куча. И вообще. Но работают они именно так же паршиво как я описал.

Какая куча? У МС ровно один такой инструмент — Database Project. В ef второй, и все.

F> Учитесь культуре разных проектов, и не навязывайте всем свою. Ваша — многим не подходит.

Я никому культуру не навязываю, я спрашиваю аргументы.
Re[3]: Entity Framework за! и против!
От: Alexander Polyakov  
Дата: 25.06.14 04:28
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Результат (вдохни поглубже):

G>
G>Average 2,9131428ms per query
G>

Сначала надо воспроизвести "багу", потом уже демонстрировать ее устранение. Покажи сначала 700ms на LINQtoSQL, потом 2,9ms на EF. Или покажи, что Sam Saffron врет.

А так не понятно, что за цифры ты привел. Скриншотам MiniProfiler-а с реального продакшена от Sam Saffron более убедительны, чем твои выдуманные примеры.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.