Как стать автором
Обновить
20
0
Сергей @sergeyZ

Пользователь

Отправить сообщение

Вот, например

Microtonal (Sixth-tone, 36 ET tuning) Original Composition for Sixth-tone Organ

А еще в 1993 была такая ISA-карточка - "Datel Pro Action Replay for DOS", например с её помощью можно было менять значения в памяти, делать slow motion. На неё есть отличный обзор у LGR - https://www.youtube.com/watch?v=usaioMbE8EQ

Кстати, в NET 6 Preview 2 появилась возможность сохранять prerendered state.

Спасибо за отзыв, это приятно.

После предендера при первом открытии страницы можно не показывать лоадеры, хотя это, конечно, так себе решение. Ведь смысл в том, чтобы пререндер был быстрым, если мы делаем тяжелые запросы в процессе пререндера, пользователь будет ждать их завершения с белым экраном. Для себя я решил, что при пререндере надо вернуть пустую страницу с лоадерами, а данные пусть загружает запустившееся приложение.

Ну и еще надо посмотреть, как они в Microsoft реализуют hot reload, возможно получится использовать решение оттуда.
Естественно я ничего не имею против Vue, Angular, React, тем более сам их использую. А сложности нужны, чтобы писать Frontend и Backend на одном языке. В случае c# это даёт ряд преимуществ: статическую типизацию, общие DTO, общую валидацию, т.д., но главное — это скорость разработки, с Blazor я делаю ту же работу существенно быстрее.

Но у меня не было задачи обращать читателей в свою религию насильно, поэтому я и не добавлял хаб «Веб-разработка» к этой публикации.
Да, Александр, вы сделали крутую библиотеку, я с ней знаком. Из моего примера можно спокойно выкинуть gRPC и System.Reactive и заменить их на Stl.Fusion, но основная идея статьи — переключение между Server и WebAssembly в runtime, без перезагрузки страницы (и WebAssembly уже загружен к моменту переключения), у вас же переключение модели размещения вызывает достаточно долгую перезагрузку страницы.
Да, вы поняли правильно.
Я получаю список таблиц с помощью метода:
public IEnumerable<string> GetTableNames()
{
    DbContext context = contextFactory.CreateContext();
    return context.Model.GetEntityTypes.Select(e => e.Name);
}


Потом получаю информацию о полях нужной таблицы:
public TableInfo GetTableInfo(string entityName)
{
    var entityType = GetEntityType(entityName);

    var properties = entityType.GetProperties();
    var efProperties = entityType.GetServiceProperties();
    var allProperties = entityType.ClrType
        .GetProperties(BindingFlags.Public | BindingFlags.Instance)
        .Where(p => !efProperties.Any(ep => ep.Name == p.Name));

    return new TableInfo
    {
        EntityType = entityType,
        Properties = properties,
        AllProperties = allProperties,
        NavProperties = allProperties.Where(p => !properties.Any(ep => ep.Name == p.Name))
    };
}


public class TableInfo
{
    public IEntityType EntityType { get; set; }
    public IEnumerable<PropertyInfo> AllProperties { get; set; }
    public IEnumerable<PropertyInfo> NavProperties { get; set; }
    public IEnumerable<IProperty> Properties { get; set; }
}


Потом генерирую код запроса в виде строки, компилирую и выполняю его динамически с помощью Roslyn. В статье под спойлером «Пример» есть картинки того, как это у меня выглядит.

Для упрощения работы с результатами запроса использую Z.EntityFramework.Plus.EFCore.
Согласен, но в этом случае без internal API не обойтись. Практика показала, что этот API стабилен. Тем более, мы обходимся без Reflection для доступа к нему, а значит заметим, если он сломается при обновлении.
Здравствуйте! Нет, для перехода на NET 5 ничего, кроме версий пакетов в файле *.csproj менять не надо, всё работает без изменений (использую этот код в проекте на NET 5).
О нет! Вы правы, надо же к IQueryable привести. Поправил.
Это правда. Но как шпаргалка, когда нужно составить отчет, подойдёт, да и выглядит круто. На схеме буду не только таблицы, но и представления.
Нет, там будет SELECT COUNT, я проверял (плохо). К тому же, это лишь пример.

EF нужен, чтобы универсально абстрагироваться от БД. Понятно, что разработчикам удобнее взять LinqPad, или просто написать запрос на SQL. А эту штуку можно сделать один раз, отдать пользователям, и забыть (но это не точно).
В городах России, где клещи кусают часто, есть лаборатории, которые проверяют клещей на клещевой энцефалит, лайм-боррелиоз, эрлихиоз, анаплазмоз. В Свердловской области, например, есть пункты для приёма клещей в 30 городах. В сезон принимают даже по выходным, результат анализа готов через сутки, проверить результат можно по номеру на сайте. Анализ платный, 939 рублей. Сам сдавал им клеща на анализ 01.06.2019, принёс в 8:30 утра в субботу, в воскресенье в 12:00 был готов результат.

На сайте пишут:
Удаленного целого клеща необходимо поместить в плотно закрытую емкость, в неё же добавить смоченную водой вату. Хранить клеща можно в течение трех суток в холодильнике при +4 С.

Если вас укусил клещ, но вы находитесь недалеко от крупного города, для извлечения клеща можете обратиться в травмпункт, у них большой опыт извлечения клещей.
The WebSocket connection starts its life with an HTTP or HTTPS handshake. When the page is accessed through HTTP, you can use WS or WSS (WebSocket secure: WS over TLS). However, when your page is loaded through HTTPS, you can only use WSS — browsers don't allow to «downgrade» security.
отсюда
Проверил ASP.NET Core SignalR по HTTP: в Chrome и Edge работает, в Firefox и IE 11 нет. Похоже, WebSocket только добавит проблем. Пока некоторые браузеры игнорируют стандарт, танцев с бубном не избежать (пока не умрёт IE 11).
Код бенчмарка BenchmarkDotNet
[RyuJitX64Job]
public class ForLoopBench
{
    private const int N = 1;
    private const int X = Int16.MaxValue;
    private const int Y = Byte.MaxValue;

    private Random rnd = new Random(DateTime.UtcNow.Millisecond);

    [Benchmark]
    public void TwoDimArray_ForLoop_NestedLoop()
    {
        int[,] arr = new int[X, Y];
        for (int i = 0; i < arr.GetLength(0); i++)
        {
            for (int j = 0; j < arr.GetLength(1); j++)
            {
                arr[i, j] = i + j;
            }
        }
    }

    [Benchmark]
    public void TwoDimArray_ForLoop_NestedLoop_LenVar()
    {
        int[,] arr = new int[X, Y];
        int len1 = arr.GetLength(0), len2 = arr.GetLength(1);
        for (int i = 0; i < len1; i++)
        {
            for (int j = 0; j < len2; j++)
            {
                arr[i, j] = i + j;
            }
        }
    }

    [Benchmark]
    public void TwoDimArray_ForLoop_Flat()
    {
        int[,] arr = new int[X, Y];
        for (int i = 0; i < arr.GetLength(0) * arr.GetLength(1); i++)
        {
            arr[i % arr.GetLength(0), i % arr.GetLength(1)] = i;
        }
    }

    [Benchmark]
    public void TwoDimArray_ForLoop_Flat_LenVar()
    {
        int[,] arr = new int[X, Y];
        var len1 = arr.GetLength(0);
        var len2 = arr.GetLength(1);
        var len = len1 * len2;
        for (int i = 0; i < len; i++)
        {
            arr[i % len1, i % len2] = i;
        }
    }

    [Benchmark]
    public int[] OneDimArray_ForLoop_Flat()
    {
        int[] arr = new int[X * Y];

        for (int i = 0; i < arr.Length; i++)
        {
            arr[i] = i;
        }
        return arr;
    }

    [Benchmark]
    public int[] OneDimArray_ForLoop_NestedLoop()
    {
        int[] arr = new int[X * Y];

        for (int i = 0; i < arr.Length / X; i++)
        {
            for (int j = 0; j < arr.Length / Y; j++)
            {
                arr[i + j * Y] = i + j * Y;
            }
        }
        return arr;
    }

    [Benchmark]
    public int[] OneDimArray_ForLoop_NestedLoop_Rand()
    {
        int[] arr = new int[X * Y];

        for (int i = 0; i < arr.Length / X; i++)
        {
            for (int j = 0; j < arr.Length / Y; j++)
            {
                arr[i + j * Y] = rnd.Next(Int32.MinValue, Int32.MaxValue);
            }
        }
        return arr;
    }
}

Резултьтаты:


| Method                                |      Mean |     Error |    StdDev |
|-------------------------------------- |-----------|-----------|-----------|
| TwoDimArray_ForLoop_NestedLoop        | 165.63 ms | 9.2170 ms | 27.176 ms |
| TwoDimArray_ForLoop_NestedLoop_LenVar |  44.66 ms | 0.8797 ms |  1.233 ms |
| TwoDimArray_ForLoop_Flat              | 512.00 ms | 9.9678 ms | 11.866 ms |
| TwoDimArray_ForLoop_Flat_LenVar       | 164.14 ms | 3.2359 ms |  5.917 ms |
| OneDimArray_ForLoop_Flat              |  29.80 ms | 1.4352 ms |  4.232 ms |
| OneDimArray_ForLoop_NestedLoop        |  91.30 ms | 1.7957 ms |  2.688 ms |
| OneDimArray_ForLoop_NestedLoop_Rand   | 335.05 ms | 6.7007 ms | 16.811 ms |

Платформа
BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.471 (1803/April2018Update/Redstone4)
Intel Core i5-2430M CPU 2.40GHz (Sandy Bridge), 1 CPU, 4 logical and 2 physical cores
  [Host]    : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3260.0
  RyuJitX64 : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3260.0

Job=RyuJitX64  Jit=RyuJit  Platform=X64  

Выводы:


  1. Самое дорогое в коде автора — вызов rnd.Next() (80%)
  2. Nomad1 прав — одномерный массив выгоднее, и не нужно отдельной переменной для длины (30 ms против 45 ms).
  3. Вложенность циклов дешевле, чем многомерность массивов.
Да, порты меньше 1024 считаются привилегированными, и для их прослушивания нужны права администратора. Порты от 1025 можно прослушивать без прав администратора. Зря я не уточнил это в статье. Спасибо за дополнение.
А в чём разница? Хоть сами себя, хоть снаружи — всё равно нужны права на прослушивание префикса.
URL ACL не нужны, когда мы биндимся к localhost:port вместо +:port. Эту же магию использует IIS Express, ему тоже не нужны права.
Также с Nancy можно использовать Kestrel, он не использует HTTP.SYS

Информация

В рейтинге
Не участвует
Откуда
Amsterdam, Noord-Holland, Нидерланды
Зарегистрирован
Активность