Posted on 26. May 2021

Модульные тесты WinUI для настольных ПК

Юнит тесты

С самого начала универсальная платформа Windows поддерживала модульное тестирование с помощью нескольких платформ тестирования. Теперь, когда WinUI Desktop стал общедоступным и с учетом того, что вы не можете проводить разработку через тестирование без тестовой среды, потребовался новый способ создания тестов для него.

В этом сообщении блога мы сразу перейдем к тому, как создать проект модульного теста для WinUI Desktop с помощью MSTest!

MSTest

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

MSTest – это платформа тестирования Microsoft, позволяющая разработчикам создавать тесты, полностью интегрированные с Visual Studio.  MSTest v2 – это полностью поддерживаемая кроссплатформенная реализация MSTest с открытым исходным кодом, которая поддерживает .Net Framework, .Net Core / .NET 5, ASP.Net, UWP, а теперь и WinUI.

Поскольку настольные приложения WinUI выполняются как упакованные в MSIX приложения .NET 5 (подробнее здесь), создание тестов для него очень похоже на создание тестов для .NET 5. Самое большое различие такое же, как и для приложений UWP: UI поток.

Учитывая, что WinUI Desktop еще совсем недавно, еще нет шаблонов в Project Reunion для создания модульных тестов на основе WinUI3, поэтому я проведу вас через шаги, необходимые для создания проекта модульного теста на основе приложения WinUI Desktop. Этот процесс аналогичен выполнению модульных тестов для приложений UWP.

Файл, Новый, Проект

После установки Project Reunion 0.5.7 VSIX можно создать новое упакованное пустое приложение WinUI Desktop:

Название проекта WinUIDesktopUnitTestApp1.

Удалите StackPanel и его содержимое из файла MainWindow.xaml и замените его пустым фреймом:

    x:Class=“WinUIDesktopUnitTestApp1.MainWindow”

    xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”

    xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”

    xmlns:d=“http://schemas.microsoft.com/expression/blend/2008”

    xmlns:local=“using:WinUIDesktopUnitTestApp1”

    xmlns:mc=“http://schemas.openxmlformats.org/markup-compatibility/2006”

    mc:Ignorable=“d”>

 

    />

 

Обязательно удалите myButton_Click из файла MainWindow.xaml.cs. Оба эти шага просто очищают шаблон по умолчанию, поскольку это не нужно в модульных тестах.

А теперь самое интересное!

 

Предварительный просмотр возможностей!

Чтобы использовать модульные тесты в WinUI Desktop, нам необходимо включить предварительную версию MSIX, которая включается свойством EnablePreviewMsixTooling MSBuild. Он перейдет от двух проектов (csproj+ wapproj) к одному проекту (один csproj). В настоящее время эта функция все еще находится на стадии предварительного просмотра, поэтому нет шаблона, который помог бы ее использовать. Тем не менее, миграция существующего проекта для его использования не должна быть сложной задачей. Пройдем по шагам.

Во-первых, давайте вручную отредактируем WinUIDesktopUnitTestApp1.csproj, дважды щелкнув его в обозревателе решений. Внутри первого раздела PropertyGroup добавьте следующее:

 

true
 
Также нужно переместить несколько файлов. Скопируйте папку Images, а также файл Package.appxmanifest из папки, в которой находится wapproj, в папку csproj. Я рекомендую вам сделать это через проводник, чтобы VS не пытался изменить ваш файл csproj. Теперь убедитесь, что ваш csproj ссылается на скопированные файлы, например: 
 
     Include="Package.appxmanifest">
        Designer
    
     Include="Images\LockScreenLogo.scale-200.png" />
     Include="Images\SplashScreen.scale-200.png" />
     Include="Images\Square150x150Logo.scale-200.png" />
     Include="Images\Square44x44Logo.scale-200.png" />
     Include="Images\Square44x44Logo.targetsize-24_altform-unplated.png" />
     Include="Images\StoreLogo.png" />
     Include="Images\Wide310x150Logo.scale-200.png" />
 
Теперь вы можете полностью удалить папкуwapproj (WinUIDesktopUnitTestApp1 (Package)), а также удалить ее из своего решения. Это все, что нужно для использования предварительной версии MSIX Tooling. У вас должно быть гораздо более чистое решение с одним проектом, подобным этому: 
 
Если вы создадите и запустите это приложение как есть, оно должно работать, но вы все равно не сможете создавать тесты. Теперь обновим этот проект, чтобы сделать его настоящим тестовым проектом. Сначала добавьте эту ItemGroup в свой csproj: 
     Include="TestContainer" />
 
Это помогает VS понять, что этот проект является тестовым. Вы можете заметить, что значок проекта в обозревателе решений изменится при сохранении csproj:
Также нужны новые пакеты NuGet, только что появившиеся! 
 
     Include="MSTest.TestAdapter">
        2.2.4
    
     Include="MSTest.TestFramework">
        2.2.4
    
     Include="Microsoft.TestPlatform.TestHost">
        16.10.0
        build
    
 
Обратите внимание на сборку build в узле Microsoft.TestPlatform.TestHost PackageReference.
 
 

Это позволит ссылаться на типы MSTest, а также правильно создавать и запускать тесты.

 

Теперь нужно активировать тестовое приложение, чтобы оно запускало необходимые тесты (по сравнению с простым запуском приложения и запуском всех тестов постоянно). Давайте отредактируем метод OnLaunched из файла App.xaml.cs:

 

using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
 
...
 
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
 
    m_window = new MainWindow();
 
    // Ensure the current window is active
    m_window.Activate();
 
    UITestMethodAttribute.DispatcherQueue = m_window.DispatcherQueue;
 
    // Replace back with e.Arguments when https://github.com/microsoft/microsoft-ui-xaml/issues/3368 is fixed
    Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.Run(Environment.CommandLine);
}

 

Теперь единственная недостающая часть - это собственно тестовый файл с нашими тестами. Создайте новый файл C# с простым тестом внутри него:

using Microsoft.VisualStudio.TestTools.UnitTesting;
 
namespace WinUIDesktopUnitTestApp1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            Assert.AreEqual(0, 0);
        }
    }
}
 
Просто сохранив этот файл, вы увидите, что тесты правильно обнаруживаются в Test Explorer VS:

Щелкните правой кнопкой мыши тест и просто запустите его. Это построит проект, развернет ваш пакет MSIX, запустит ваши тесты и обновит Test Explorer с результатами!

 

Помните, что это все еще находится на стадии предварительного просмотра. Закрытие VS и его повторное открытие обычно помогает решить некоторые проблемы, так что имейте это в виду, если что-то кажется нестабильным.

 

Теперь, когда основы работают, давайте создадим тест, который использует атрибут Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer.UITestMethodAttribute. Это позволяет вам запускать код непосредственно в потоке пользовательского интерфейса вашего окна WinUI3. Весьма вероятно, что вам нужно будет это сделать, учитывая тот факт, что любой код, который создает или изменяет элемент пользовательского интерфейса, обычно должен выполняться из потока пользовательского интерфейса. Такой простой код, как var grid = new Grid(), вызовет исключение, если вы попытаетесь запустить его из обычного TestMethod:

 

TestMethod1
   Source: UnitTest1.cs line 11
   Duration: 44 ms
 
  Message: 
    Test method WinUIDesktopUnitTestApp1.UnitTest1.TestMethod1 threw exception: 
    System.Runtime.InteropServices.COMException: The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD)) For UWP projects, if you are using UI objects in test consider using [UITestMethod] attribute instead of [TestMethod] to execute test in UI thread.
  Stack Trace: 
    ExceptionHelpers.ThrowExceptionForHR(Int32 hr)
    _IGridFactory.CreateInstance(Object baseInterface, IntPtr& innerInterface)
    Grid.ctor()
    UnitTest1.TestMethod1()

К счастью, совершенно ясно, что мы должны сделать, чтобы исправить проблему, поэтому просто замените [TestMethod] на [UITestMethod], добавив оператор используемый Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer, который заставит этот тест выполняться в потоке пользовательского интерфейса.

И вот оно:

 

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

Спасибо, что прочитали, и увидимся в следующий раз!

 

Источник



Posted on 17. April 2021

Анонс о Windows Community Toolkit v7.0

После многих месяцев обновления Windows Community Toolkit множеством улучшений и функций; Microsoft рады сообщить, что сегодня доступна версия 7.0! Это снова стало возможным благодаря поддержке и вкладу сообщества разработчиков.

 Если вы новичок в наборе инструментов, набор инструментов сообщества Windows представляет собой набор помощников, расширений и настраиваемых элементов управления. Он упрощает и демонстрирует общие задачи разработчика для создания приложений UWP и .NET для Windows 10. Набор инструментов является частью .NET Foundation. Вы можете загрузить игровую площадку Sample App, чтобы открыть для себя и опробовать компоненты Toolkit перед тем, как начать работу над проектом.

Это новое обновление включает в себя совершенно новую библиотеку .NET Standard MVVM, более простые в использовании помощники Toast Notification для .NET и UWP, полностью обновленную систему анимации композиции для C # и XAML, новые элементы управления и многое другое !!!

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

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

См. Более подробную информацию об этих изменениях и новых функциях ниже.

 

Новая структура пакета и критические изменения 🚨

Microsoft провели рефакторинг многих пакетов в Toolkit. Это должно было помочь уменьшить количество дополнительных зависимостей для всего пакета, когда они требовались лишь небольшому количеству компонентов. Это позволило нам уменьшить влияние Toolkit на размер приложения в обычных сценариях на 80-90%.

 Если вы новичок в Toolkit или создаете новое приложение, вы можете пропустить этот раздел и перейти к нашим новым функциям ниже!

Проведенный рефакторинг больше всего повлиял на пакеты Animations и Controls. Основные наиболее важные изменения приведены ниже, но подробные сведения см. В примечаниях к выпуску.

• Пакет Animation теперь легче, чтобы напрямую поддерживать только анимацию C # и XAML.

• Разделили ссылку на Behaviors на новый пакет Microsoft.Toolkit.Uwp.UI., который включает в себя различные новые Behaviors и новые хуки для Animations.

• Пакет Controls теперь является метапакетом, который содержит различные подпакеты.

• Наличие родительского пакета должно упростить обновление.

• Дополнительные элементы управления, такие как DataGrid и макеты ItemsRepeater, теперь также будут включены по умолчанию, предоставляя вам доступ ко всему набору инструментов, который может предложить при начале работы.

• Пакет Controls теперь зависит от WinUI 2.5, что поможет нам обеспечить более согласованный стиль управления в дальнейшем и воспользоваться преимуществами последних исправлений и функций, которые может предложить платформа.

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

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

• Большинству для миграции достаточно просто изменить пространство имен/xmlns.

Примечание. Мы предлагаем перейти с использования Dispatcher на DispatcherQueue в соответствии с инструкциями по платформе. Это позволяет использовать компоненты в пределах островов XAML и WinUI 3.

• API-интерфейсы Guard и ThrowHelper перемещены в новый пакет Microsoft.Toolkit.Diagnostics.

• Помощники отложенных событий перешли в Microsoft.Toolkit, поскольку они совместимы с .NET Standard; в Microsoft.Toolkit.Uwp остались только специальные расширения событий UWP.

• Минимальная версия платформы компонентов UWP Toolkit теперь 1809 (17763), чтобы удалить большую часть условных накладных расходов на код XAML и привязаться к текущему выпуску Windows 10 с долгосрочным обслуживанием.

• Перенесли код компонента Gaze на C # для упрощения обслуживания и улучшений в будущем.

• Удалили зависимость Json Serializer по умолчанию из Microsoft.Toolkit.Uwp, которая добавляла значительные накладные расходы приложения, даже если они не использовались.

Примечание. При обновлении существующего приложения 6.1, в котором хранились сложные типы, вы должны убедиться, что вы тестируете обновление существующего хранилища данных или указываете сериализатор Newtonsoft.Json для обеспечения совместимости с существующим приложением.

• Однако теперь разработчик приложения может указывать, какой сериализатор они хотели бы использовать вместо этого, если им нужно поделиться данными с другими аспектами своего внешнего/внутреннего интерфейса.

См. Здесь дополнительные инструкции по указанию настраиваемого сериализатора и примеры использования System.Text.Json, Newtonsoft.Json или DataContractSerializer.

В рамках этого пути также улучшили процессы в самом наборе инструментов, добавив больше непрерывного интеграционного тестирования в конвейер, и у Microsoft есть Wiki с подробностями о том, как начать вносить свой вклад в набор инструментов!

 


MVVM Toolkit для .NET - Серхио Педри

TheMicrosoft.Toolkit.Mvvmpackage - это современная, быстрая и модульная библиотека MVVM. Он построен на следующих принципах:

Независимость от платформы и среды выполнения - .NET Standard 2.x🚀 (т.е. независимость от UI Framework Agnostic)

Простота получения и использования - Отсутствие строгих требований к структуре приложения или парадигмам кодирования (за пределами «MVVM»), т.е. гибкое использование.

À la carte - Свобода выбора, какие компоненты использовать.

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

Пакет нацелен на .NET Standard, поэтому его можно использовать на любой платформе приложений: UWP, WPF, Xamarin, Uno Platform и других; и в любой среде выполнения: .NET Native, .NET Core, .NET Framework или Mono. Он работает на всех из них и предоставляет общую поверхность API для всех случаев.

Это значительно упрощает абстрагирование базовой модели и логики ViewModel от приложения позже, особенно для проектов, которые могут быть ориентированы на несколько платформ пользовательского интерфейса.

Созданием этой новой библиотеки было почти годичное усилие сообщества под руководством Серджио Педри и вдохновением от работы, проделанной Лораном Бюньоном MVVM Light. Команда Windows Template Studio также вносит поддержку библиотеки в свой набор шаблонов проектирования. Microsoft MVP (Мэтт Лейси, Джеймс Крофт, Ник Рэндольф, Дидерик Кролс и Мартин Зикмунд) и сообществом над разработкой, тестированием и проверкой основных сценариев библиотеки перед ее выпуском.

Здесь вы можете найти образцы и дополнительную информацию о MVVM Toolkit.

 


Улучшенная поддержка уведомлений для Win32 и .NET 5

 

Распакованные приложения Win32 C # теперь могут без труда использовать всплывающие уведомления, ярлык в меню «Пуск» не требуется! Просто вызовите следующий API, и это все!

new ToastContentBuilder()

.AddText("Hello toast!")

 

.Show();


new ToastContentBui

 

Кроме того, этот же упрощенный API одинаково работает и для UWP, и для упакованных приложений MSIXC #! Больше никаких longyToastNotificationManager.CreateToastNotifier (). Show (content.GetXml ()). Чтобы попробовать это, перейдите на страницу документации. В этом видео вы можете увидеть, как мы добавляем уведомления от начала до конца в приложение WPF менее чем за 2 минуты!

 


Явные помощники по анимации - 🏆 Серхио Педри

Как было сказано выше, мы обновили наш пакет Animations в наборе инструментов. Помимо этого, добавили новую систему ‘Explicit Animation’. Если вы использовали помощники по неявной анимации в прошлом, они вам понравятся!  

Есть не только мощный новый класс AnimationBuilder, который поможет вам создавать великолепные и мощные композиционные анимации в C #, но Microsoft также представили его для XAML. Посмотрите, что вы можете сделать ниже без кода программной части!

Теперь все ваши композиционные анимации могут быть выполнены с помощью красивого C # API или XAML, как и помощники неявной анимации, которые были так широко любимы в прошлом. Наслаждайтесь своими творениями и делитесь ими с #WindowsCommunityToolkit в Twitter.

 


TabbedCommandBar - 🏆 Йоши Асхарун


TabbedCommandBar - это интерфейс навигации на уровне приложения, который предоставляет гибкое пространство для управления командами в вашем приложении. Он обеспечивает знакомый интерфейс, который есть во многих приложениях для повышения производительности, и позволяет разработчику приложения группировать похожие команды вместе. Он также предоставляет возможность добавлять контекстные вкладки для отображения параметров, которые могут быть полезны только тогда, когда пользователь вносит определенные изменения в приложение.

 


Улучшенный ColorPicker - 🏆 Роберт Луенгоед


После обсуждений в WinUI GitHub о возрождении элемента управления ColorPicker сообщество сделало шаг вперед, чтобы представить себе новый опыт выбора цветов. Роберт разработал новую версию ColorPicker, чтобы каждый мог использовать и попробовать. Microsoft планирует предоставить обратную связь и улучшения, основанные на этом новом опыте, команды платформы, когда они в следующий раз обновят ColorPicker.

 


Switch Presenter - 🏆 Майкл Хокер


SwitchPresenter - это новый способ разметки и организации вашего XAML. Он предоставляет эквивалент инструкции switch из C# в XAML! Это может упростить группировку элементов, связанных со сценарием, вместо того, чтобы смешивать их вместе с помощью множества привязок видимости. Или вы можете использовать его, чтобы полностью заменить часть пользовательского интерфейса, основываясь на каком-то другом факторе. Посмотрите пример в документации.

 


На горизонте


Предварительный просмотр Project Reunion 0.5


Как вы, знаете, Microsoft предоставляет предварительные версии Toolkit, которые работают для WinUI 3, вместе с их предварительными версиями. Выпущена предварительная версию инструментария, который работает с настольными приложениями с .NET в предварительной версии Project Reunion 0.5, анонсированной на прошлой неделе. Узнайте больше о том, как попробовать.

 

Будущие изменения идентификатора пакета NuGet


Через несколько недель представят обновленную версию элементов управления на основе WinUI 3 для NuGet для Project Reunion 0.5. В рамках этого изменения также начнем использовать новый корневой идентификатор пакета CommunityToolkit. * Для пакетов. Существующие пакеты UWP останутся как Microsoft.Toolkit.Uwp. *; однако новые пакеты для WinUI будут находиться в CommunityToolkit.WinUI. *.

Microsoft планирует отказаться от пакетов UWP в тот момент, когда сообщество в целом может перейти на WinUI 3, если оно будет поддерживать функции, которые сообщество UWP знает и любит. До этого времени планируется поддерживать существующих разработчиков UWP в первую очередь с помощью существующих пакетов, созданных на основе UWP + WinUI 2.x, и поставлять параллельные версии для WinUI 3. Следовательно, каждый следующий выпуск набора инструментов для UWP (например, 7.1) будет иметь соответствующую версию 7.1, которая содержит тот же набор функций, но для WinUI 3 (за исключением того, что в настоящее время еще не поддерживается в WinUI 3).

 


Еще больше!


Не забудьте также ознакомиться с новым синтаксическим анализатором языка Win2D Path Mini от 🏆 Ratish Philip, обновлениями HighPerformance от Sergio Pedri и улучшениями приложения Lottie Viewer.

В этом выпуске есть множество исправлений, других помощников и улучшений, поэтому обязательно ознакомьтесь с примечаниями к выпуску, чтобы узнать все подробности!

 


Начни сегодня!


Напоминаем, что вы можете начать работу, следуя руководству на docs.microsoft.com, или просмотреть последние функции, установив образец приложения Windows Community Toolkit из Microsoft Store (оно также ссылается на каждую страницу документов). Если вы хотите внести свой вклад, присоединяйтесь на GitHub и ознакомьтесь с новой Wiki! Чтобы следить за беседой в Twitter - #WindowsCommunityToolkit или присоединяйтесь на канале в Discord сообщества UWP

 


 



.S






Источник 



Posted on 5. April 2021

GC Perf Infrastructure - Часть 1

Microsoft открывает новый проект GC Perf! Теперь это часть репозитория производительность .Net.

Прежде всего, позвольте отметить, что целевой аудиторией этой инфраструктуры, помимо очевидной (то есть тех, кто вносит изменения в производительность GC), являются люди, которым необходимо провести углубленный анализ GC / производительности управляемой памяти и / или построить автоматизацию вокруг этого. Таким образом, предполагается, что у вас уже есть достаточное количество знаний о том, что искать при анализе.

Во-вторых, в инфраструктуре много движущихся частей, и, поскольку она все еще находится в стадии разработки, я не удивлюсь, если вы столкнетесь с проблемами при ее использовании. Пожалуйста, будьте терпеливы, когда мы решаем проблемы! У нас нет много ресурсов, поэтому мы не сможем получить к ним доступ сразу. И, конечно, если вы хотите внести свой вклад, для нас это будет очень ценно. Я знаю многих людей, которые читают это, увлечены анализом производительности и проделали огромную работу по созданию / улучшению ее для .NET. А внесение вклада в анализ производительности - это фантастический способ узнать о настройке GC, если вы хотите начать с чего-то. Поэтому я настоятельно рекомендую вам внести свой вклад!

 

Топология

Мы обсудили, хотим ли мы открыть исходный код для этого в своем собственном репо, и пришли к выводу, что мы не будем делать это в основном из-за логистических соображений, поэтому это стало частью репозитория perf в каталоге src/benchmarks/gc (к которому я буду обращаться в качестве корневого каталога). Это не зависит от чего-либо это означает, что вам не нужно ничего создавать вне этого каталога, если вы просто хотите использовать инфракрасную часть GC perf.

Файл readme.md в корневом каталоге описывает общий рабочий процесс и основное использование. Дополнительную документацию можно найти в каталоге документов.

Есть 2 основных компонента инфраструктуры:

Запуск тестов производительности

Это запускает наши собственные тесты перфорирования - это для людей, которым нужно действительно вносить изменения производительности в GC. Это обеспечивает следующие функциональные возможности –

Задание различных аргументов командной строки для генерации разных характеристик perf в тестах, например, разных коэффициентов построения для SOH / LOH и разных коэффициентов пиннинга;

Определение сборок для сравнения;

Задание различных сред, например, различных переменных env для указания конфигураций GC, работы в контейнерах или ситуаций с высокой загрузкой памяти;

Задание различных параметров для сбора трасс с помощью, GCCollectOnly или ThreadTime.

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

Вам не нужно запускать тесты - вы можете запускать все что угодно, если только вы можете указать это как программу командной строки, и при этом использовать все остальное, что мы предоставляем, например запуск в контейнере.

Это задокументировано в файле readme, и я буду говорить об этом более подробно в одной из будущих записей в блоге.

Источник для этого находится в exec dir.

Анализ производительности

Это может использоваться без бегущей части вообще. Если вы уже собрали следы перфектов, вы можете использовать их для анализа. Я предполагаю, что больше людей заинтересуются этим, чем бегущей частью, поэтому я посвятим больше контента анализу. В последней публикации GC я уже говорил о том, что вы можете сделать это с помощью Jupyter Notebook (я покажу больше примеров с реальным кодом в следующих записях блога). На этот раз я сосредоточусь на фактической настройке и использовании команд, которые мы предоставляем. Не стесняйтесь попробовать это сейчас

Источник находится в  analysis.

Настройка анализа

После копирования репозитория с производительностью dotnet вы увидите файл readme в директории gc infra root. Настройка подробно описана в этом документе. Если вам просто нужен анализ, вам не нужно выполнять все шаги по настройке. Единственные шаги, которые вам нужны –

Установите Python. 3.7 является минимально необходимой версией и рекомендуемой версией. 3.8 есть проблемы с Jupyter Notebook. Я хотел указать на это, потому что 3.8 - последняя версия релиза на странице python.

Установите необходимые библиотеки python - вы можете сделать это через «py -m pip install -r src / needs.txt», как сказано в readme, и если ошибок не возникает, отлично; но вы можете получить ошибки с pythonnet, который является обязательным для анализа. На самом деле установка pythonnet может быть настолько хлопотной, что мы посвятили ей целый документ. Я надеюсь, что однажды в VSCode будет достаточно хороших библиотек для построения диаграмм на С#, и С# в Jupyter Notebook, будут работать,  поэтому нам больше не понадобится pythonnet.

Создайте библиотеку анализа С#, запустив «dotnet publish» в каталоге src\analysis\managed-lib dir.

Укажите, что анализировать

Допустим, вы собрали трассировку ETW (это может быть из .NET или .NET Core) вам нужно его проанализировать, какой процесс будет для вас интересен (в Linux вы собираете события для интересующего процесса с помощью dotnet-trace, но поскольку инфраструктура работает как в Windows, так и в Linux, это те же шаги). Определение процесса для анализа означает простую запись файла .yaml, который мы называем «файлом статуса теста». Из файла readme для файла состояния теста, который вы пишете только для анализа, нужны только эти 3 строки:

success: true

trace_file_name: x.etl # A relative path. Should generally match the name of this file.

process_id: 1234 # If you don’t know this, use the print-processes command for a list

Вы можете задаться вопросом, зачем вообще указывать строку «success: true» - это просто потому, что нижеприведенная схема также может использоваться для анализа результатов выполнения тестов. Когда вы запускаете множество тестов и анализируете их результаты в области автоматизации, мы ищем эту строку и анализируем только те, которые были успешными.

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

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

C:\perf\src\benchmarks\gc>py . help

Сначала прочтите README.md. Для помощи с отдельной командой используйте py . command-name –help. (Вы можете пропустить --help –hidden чтобы увидеть скрытые аргументы.)

Запустите команду

[пропустить]

команды анализа

Команды для анализа результатов теста (файлы трассировки). Чтобы сравнить небольшое количество конфигурации, используйте diff. Для сравнения используйте chart-configs. Для подробного анализа одной трассы используйте analyze-single или chart-individual-gcs.

analysis-single: с учетом одной трассы, показателей печати и, при необходимости, показателей для отдельных GC.

analyse-single-gc: выводит подробную информацию об одном GC в пределах одной трассы.

[больше вывода опущено и выполнено некоторое форматирование вывода]

 

(Я прошу прощения за форматирование - меня поражает, что у нас, похоже, нет приличной программы редактирования html для ведения блогов, а написание блога в основном состоит из ручного написания html, что очень больно)

Как говорится в справке высокого приоритета, вы можете получить помощь по конкретным командам. Поэтому мы последуем этому предложению и сделаем

C: \ perf \ src \ benchmarks \ gc> py. помочь печатным процессам

 

Напечатайте все PID процесса и имена из файла трассировки.

[больше выходных данных пропущено; Я также сделал некоторое форматирование, чтобы избавиться от некоторых столбцов, чтобы строки не были слишком длинными]

 

В качестве примера я специально выбрал тест, который, по моему мнению, не подходит для работы с Server GC, потому что он имеет только один поток, поэтому я ожидаю увидеть некоторый дисбаланс потоков. Я знаю, что дисбаланс возникнет, когда мы отметим объекты старшего поколения, удерживающие объекты молодого поколения, поэтому я буду использовать команду chart-individual-gcs, чтобы показать мне, сколько времени потребовалась каждому потоку.

C:\perf\src\benchmarks\gc>py . chart-individual-gcs C:\traces\fragment\fragment.yaml –x-single-gc-metric Index –y-single-heap-metrics MarkOlderMSec

Это покажет 8 куч. Подумайте о прохождении --show-n-heaps.

Конечно, одна из куч всегда занимает значительно больше времени, чтобы пометить объекты молодого поколения, на которые ссылаются объекты более старого поколения, и чтобы убедиться, что это не из-за каких-то других факторов, я также посмотрел, сколько повышается за кучу –

C:\perf\src\benchmarks\gc>py . chart-individual-gcs C:\traces\fragment\fragment.yaml –x-single-gc-metric Index –y-single-heap-metrics MarkOlderPromotedMB

Это покажет 8 куч. Подумайте о прохождении --show-n-heaps.

Это подтверждает теорию - потому что мы пометили значительно больше одной кучи, что привело к тому, что эта куча потратила значительно больше времени на маркировку.

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

Вот пример .md, который показывает примеры использования некоторых команд. Обратите внимание, что анализ объединения еще не проверен - пиар вышел, и я хотел потратить больше времени на CR, прежде чем объединять его.

Источник



Posted on 29. March 2021

Анонс о Project Reunion 0.5!

Выпуск Project Reunion 0.5 является отправной точкой в создани приложений для Windows в гораздо более быстром темпе, не дожидаясь обновления ОС Windows с новыми функциями. В версии 0.5 уделили большое внимание тому, что слышали от сообщества разработчиков где говорилось о том, чтобы снова упростить сборку настольных приложений. Вот почему вы найдете поддержку более низкого уровня для Windows 10 версии 1809, возможность использовать Project Reunion с приложением .NET 5, а также WinUI 3 и WebView2 для современной совместимой разработки пользовательского интерфейса - все с поддержкой производственного уровня при использовании упакованные приложения! Project Reunion 0.5 - один из многих важных шагов, которые предстоит сделать на пути к версии 1.0 в этом году.

Что значит поставлять вместе с Project Reunion?

Когда вы создаете приложение, использующее Project Reunion, вы получаете доступ к современным технологиям Windows и новым функциям, а также лучшим из существующих функций рабочего стола (также известного как Win32). Вы также сможете постепенно внедрять эти технологии и гораздо быстрее, поскольку они отделены от ОС. Обычно нужно дождаться, пока пользователи обновятся до последней версии ОС Windows, прежде чем вы сможете рассмотреть возможность внедрения новейших функций и их интеграции в свое приложение. Для некоторых из вас это может означать задержку на 1-2 года с выпуском новой функции, возможность принять ее, а пользователи увидят ее в приложениях. Теперь вы можете использовать последнюю версию Project Reunion, когда захотите получить новейшие функции, и можете быть уверены, что они будут работать для всех ваших пользователей в Windows 10 версии 1809 (текущая версия Enterprise LTSC) и новее.

В выпуске 0.5 эти функции включают MRTCore и DWriteCore - сначала они были представлены в предварительной версии 0.1, но теперь с обновлениями и полной поддержкой. Кроме того, выпуск 0.5 содержит долгожданную производственную версию WinUI 3 для настольных приложений, которая также включает элемент управления WebView2.

Функции, которые Microsoft выпускает сегодня, поставляются как часть пакета фреймворка Project Reunion. Вы можете думать об этом пакете фреймворка как об объединением всей части семейства Project Reunion - например, WinUI 3, который не находится непосредственно в репозитории Project Reunion GitHub - в одном месте, чтобы разработчики могли легко использовать его.

При создании приложения с помощью Project Reunion вы начнете с загрузки Project Reunion Visual Studio Extension (VSIX). Это предоставляет шаблоны проектов и элементов WinUI 3 и настраивает ваше приложение для ссылки на пакет Project Reunion и любые необходимые зависимости. Создав новый проект, вы снова вернетесь в зону разработки Windows, к которой привыкли.

 

Что поддерживается в Project Reunion 0.5

Project Reunion 0.5 поддерживает упакованные приложения, использующие MSIX в качестве метода развертывания. Существует большой спрос на неупакованную поддержку, Microsoft создали план для предварительных выпусков, которые скоро появятся.

Наиболее заметным дополнением к выпуску Project Reunion 0.5 является WinUI 3, который представляет собой резкое расширение библиотеки элементов управления WinUI 2 до полноценной, сквозной автономной среды UX. Если вы еще не знакомы с WinUI, вы можете узнать о нем все в обзорной документации, а также на веб-сайте.

Версия WinUI 3, поставляемая с этим выпуском, является первой версией, подходящей для производственных приложений и имеющей прямую совместимость. С WinUI 3 теперь вы можете создавать настольные приложения, которые можно публиковать в Microsoft Store. В настоящее время существует два поддерживаемых метода создания приложения WinUI 3:

• Создание нового настольного приложения WinUI 3 с нуля

• Перенос существующих настольных приложений на WinUI 3 путем добавления нового проекта WinUI 3 к вашему решению и корректировки или рефакторинга вашей логики

Имейте в виду, что некоторые из вас в настоящее время могут использовать предварительную версию WinUI 3 - Project Reunion 0.5, которая имеет несколько дополнительных функций, включая поддержку создания приложений WinUI 3 UWP и поддержку многооконного режима в классических приложениях. Вы не сможете использовать эти функции предварительной версии или вызывать какие-либо связанные с ними API в этой новой стабильной версии WinUI 3. Если вы хотите поэкспериментировать с этими функциями, вы все равно можете продолжать использовать предварительную версию, оставив предварительную версию VSIX. Скоро вы сможете использовать нашу предварительную версию 0.8, так как у нас будут параллельные выпуск и предварительная версия.

Команда стремится выпускать регулярные превью (в промежутках между стабильными выпусками и одновременно с ними) для тех из вас, кто хотел бы быть в курсе. Функции предварительного просмотра будут постоянно стабилизироваться, чтобы поставляться в составе будущих стабильных выпусков.

Как использовать Project Reunion 0.5

Чтобы начать использовать Project Reunion, см. Раздел Начало работы с Project Reunion, чтобы настроить среду разработки и узнать больше о компонентах, включенных в этот выпуск. Если вы просто ищете информацию о создании приложения WinUI 3, начните со статьи с обзором WinUI и примечаниями к выпуску. После того, как вы настроите начало создания приложения WinUI 3, ознакомьтесь с документами по началу работы с WinUI 3 с настольными приложениями и Создание базового настольного приложения WinUI 3.

Если вы обнаружите проблемы, характерные для разработки с WinUI 3, сообщите о проблеме в репозиторий WinUI - и если вы обнаружите какие-либо проблемы с другими частями Project Reunion 0.5, сообщите о проблеме в репозитории Project Reunion.

Растущая экосистема

Следующие экосистемные технологии уже поддерживают или работают над поддержкой Project Reunion 0.5. Эти технологии предоставляют уникальные функции и элементы управления в дополнение к WinUI 3, и вы можете прочитать больше о каждой из них ниже.

Actipro Software переносит свои обширные предложения по управлению пользовательским интерфейсом на WinUI 3, включая редактор кода SyntaxEditor, сетку свойств, поля редактирования собственных типов, стыковку / MDI, диаграммы и многое другое.

DevExpress: DevExpress выпустила 20 новых элементов управления WinUI с поддержкой Project Reunion 0.5, включая Data Grid, Scheduler, Charts, Ribbon Toolbar и многое другое. Все 20 компонентов пользовательского интерфейса доступны бесплатно.

GrapeCity планирует перенести свои популярные элементы управления пользовательским интерфейсом рабочего стола в WinUI в конце этого года! Узнайте больше об их компонентах службы подключения к данным для WinUI.

Инфрагистика: Ultimate UI для WinUI предоставляет важные для бизнеса, высокопроизводительные и многофункциональные средства управления бизнесом для ваших приложений, ориентированных на любую платформу, работающую под управлением Windows (включая Windows на ARM64).

Syncfusion: обновили свои проекты до Microsoft.ProjectReunion из Microsoft.WinUI, следуя инструкциям по обновлению. Все их элементы управления работают нормально.

Пользовательский интерфейс Telerik для WinUI: первый на рынке набор элементов управления пользовательским интерфейсом для создания приложений Win32 и UWP с WinUI 3, поставляется с многофункциональными элементами управления, такими как лента, DataGrid, диаграммы, датчики, штрих-код и многое другое.

Платформа Uno: используйте WinUI 3 - Reunion 0.5, XAML и C# для создания собственных приложений с идеальной пиксельной базой и единой кодовой базой, которые могут работать в Интернете, на настольных компьютерах и мобильных устройствах. Это бесплатно, с открытым исходным кодом и доступно уже сегодня.

Windows Community Toolkit (Microsoft): WCT в настоящее время работает над поддержкой Project Reunion 0.5 в ближайшем будущем. Он предоставляет множество новых элементов управления и возможностей для использования в вашем приложении WinUI. Посмотрите их репозиторий с открытым исходным кодом.

Что дальше

В течение оставшейся части этого календарного года в Project Reunion будет добавлено больше технологий, таких как: жизненный цикл приложения для повышения производительности системы и времени автономной работы, современная оконная система, сочетающая возможности окон Win32 с простотой UWP, поддержка уведомлений как для локальных, так и push-сценариев, поддержка распакованных приложений и многое другое.

В ближайшем будущем планируют выпустить Project Reunion 0.8 в ближайшие несколько месяцев и Project Reunion 1.0 в конце этого года с серией предварительных версий, которые будут поставляться вместе с этими стабильными версиями. WinUI 3 и другие востребованные функции - так что публикуйте свои проблемы и спецификации в репозиторий! - будет обновляться в каждом из этих выпусков. Для получения дополнительной информации ознакомьтесь с будущей roadmap.

Оставайтесь в курсе

Вы можете быть в курсе последних событий команды в репозитории WinUI GitHub и Project Reunion на GitHub, а также через ежемесячные звонки сообщества WinUI, а вскоре и через звонки сообщества Project Reunion, на которых часто делятся планами действий и другими интересными новостями.

Вы также можете связаться в Twitter, используя  #ProjectReunion и  @WindowsUI!

 

Источник

 



Posted on 31. March 2020

Подключение проекта C ++ / CLI к .NET Core

 

Одной из новых функций Visual Studio 2019 (начиная с версии 16.4) и .NET Core 3.1 является возможность создавать проекты C ++ / CLI, ориентированные на .NET Core. Это можно сделать напрямую с помощью cl.exe и link.exe (с использованием новой опции  /clr:netcore) или с помощью MSBuild (с помощью NetCore ). В этой статье я расскажу о шагах, необходимых для переноса простого проекта взаимодействия C ++ / CLI в .NET Core. Более подробную информацию можно найти в документации .NET Core.

Пример проекта

Во-первых, мне нужно сделать пример решения для миграции. Я собираюсь использовать приложение с собственной точкой входа, которая отображает форму Windows Forms через C ++ / CLI. Миграция решения с управляемой точкой входа, взаимодействующей с коренными зависимостями через C ++ / CLI, была бы такой же простой. Для начала я создал решение с тремя проектами:

1. NativeApp. Приложение C ++ для Windows из шаблона Visual Studio «Настольное приложение Windows».

1. Это будет точкой входа в приложение.

2. Я обновил его, чтобы он отображал управляемую форму (через проект CppCliInterop) и вызывал для нее метод при вызове команды IDM_ABOUT.

2. ManagedLibrary. Библиотека C # Windows Forms для .NET Core.

1. Это обеспечит форму WinForms для отображения собственного приложения.

2. Я добавил текстовое поле в форму и метод для установки текста текстового поля. Я также нацелил этот проект на .NET Core и .NET Framework, чтобы его можно было использовать с любым из них. Таким образом, мы можем сосредоточиться на переносе только части образца C ++ / CLI.

3. CppCliInterop. Библиотека .NET Framework C ++ / CLI.

1. Это будет использоваться в качестве уровня взаимодействия для подключения приложения к управляемой библиотеке WinForms.

2. Он ссылается на ManagedLibrary и позволяет коренным проектам использовать его.

3. Это проект, который необходимо перенести в .NET Core.

 

Пример кода доступен на GitHub. При запуске приложения, если вы щелкнете по меню Справка -> О программе, форма WinForms будет отображаться с текстом в текстовом поле, предоставленном проектом NativeApp.

Миграция vcxproj в .NET Core

Теперь для интересной части - обновление примера приложения для запуска на .NET Core. Необходимые изменения на самом деле минимальные. Если вы ранее переносили проекты C # в .NET Core, перенос проектов C ++ / CLI еще проще, поскольку формат файла проекта не меняется. В управляемых проектах проекты .NET Core и .NET Standard используют новый формат файла проекта в стиле SDK. Однако для проектов C ++ / CLI тот же формат vcxproj используется для таргетинга на .NET Core, как и .NET Framework.

Все, что нужно, - это внести несколько изменений в файл проекта. Некоторые из них могут быть сделаны через Visual Studio IDE, но другие (такие как добавление ссылок на WinForms) еще не могут быть. Таким образом, самый простой способ обновить файл проекта - это просто выгрузить проект в VS и отредактировать vcxproj напрямую или использовать редактор, такой как VS Code или Notepad.

1. Замените true на NetCore. Это говорит компилятору использовать /clr:netcore вместо /clr при сборке.

1. Это изменение может быть сделано через интерфейс конфигурации проекта Visual Studio, если вы предпочитаете.

2. Обратите внимание, что указывается отдельно в каждой группе свойств конфигурации / платформы в файле проекта примера проекта, поэтому обновление необходимо выполнить в четырех разных местах.

2. Замените 4.7 на netcoreapp3.1.

1. Эти параметры можно изменить с помощью интерфейса конфигурации проекта Visual Studio на вкладке «Дополнительно». Однако обратите внимание, что изменение параметра поддержки CLR проекта, как описано в предыдущем шаге, не приведет к автоматическому изменению  , поэтому обязательно очистите параметр «.NET Target Framework Version» перед выбором .NET Core Runtime Support.

3. Замените ссылки .NET Framework (на System, System.Data, System.Windows.Forms и System.Xml) следующей ссылкой на компоненты WinForms из Windows Desktop .NET Core SDK. Этот шаг пока не поддерживает Visual Studio IDE, поэтому его необходимо выполнить, отредактировав vcxproj напрямую. Обратите внимание, что необходима только ссылка на Windows Desktop SDK, поскольку .NET Core SDK (который включает в себя такие библиотеки, как System, System.Xml и т. Д.) Включается автоматически. Существуют разные ссылки на Framework для WinForms, WPF или обоих (как описано в документах по миграции).

1.  

После внесения этих изменений проект C ++ / CLI будет успешно ориентирован на .NET Core.

Если вы используете последнюю версию Visual Studio 2019 (16.5 или 16.6 Preview 1), все должно работать и во время выполнения.

До предварительного просмотра Visual Studio 2019 16.5 2 библиотеки C ++ / CLI не создавались файл .runtimeconfig.json, необходимый для библиотек C ++ / CLI, чтобы указать, какую версию .NET Core они используют, поэтому его нужно было добавить вручную. Итак, если вы используете более старую версию Visual Studio, вам нужно будет вручную создать этот файл CppCliInterop.runtimeconfig.json и убедиться, что он скопирован в выходной каталог:

Теперь приложение может работать на .NET Core! Версия источника доступна в  the NetCore branch в репозитории GitHub. Вот форма Windows, запущенная перед загруженными модулями, показывающая выгруженный coreclr.dll.

Билд без MSBui

Миграция этого примера приложения в .NET Core была просто вопросом обновления файла проекта для целевой платформы .NET Core вместо .NET Framework. Если вам нужно собирать сборки C ++ / CLI напрямую с помощью cl.exe и link.exe. Необходимые шаги:

1. Используйте /clr:netcore вместо /clr при вызове cl.exe.

2. Справочные сборки .NET Core с использованием необходимой ссылки /FU (справочные сборки .NET Core обычно устанавливаются в папку % ProgramFiles% \ dotnet \ packs \ \ \ ref).

3. При компоновке включайте каталог хоста приложения .NET Core как LibPath. Хост-файлы приложения .NET Core обычно устанавливаются в папку % Program Files% \ dotnet \ package \ Microsoft.NETCore.App.Host.win-x64 \ \ runtime \ win-x64 \ native).

4. Убедитесь, что файл ijwhost.dll (необходимый для запуска среды выполнения .NET Core) скопирован локально из расположения узла приложения .NET Core. MSBuild делает это автоматически при сборке проекта vcxproj.

5. Создайте файл .runtimeconfig.json, как говорилось ранее.

Несколько предостережений

1. Как видите, с Visual Studio 2019 и .NET Core 3.1 направленность  на .NET Core с проектами C ++ / CLI легко. Однако есть несколько ограничений C ++ / CLI. Поддержка C ++ / CLI возможна только в Windows, даже при работе в .NET Core. Если вам нужна межплатформенная совместимость, ссылайтесь на платформу.

2. Проекты C ++ / CLI не могут быть нацелены на .NET Standard - только .NET Core или .NET Framework - и многоцелевой таргетинг не поддерживается, поэтому для создания библиотеки, которая будет использоваться как вызывающими .NET Framework, так и .NET Core, потребуются два файла проекта.

3. Если в проекте используются API, которые недоступны в .NET Core, эти вызовы необходимо будет обновить до альтернатив .NET Core. .NET Portability Analyzer может помочь найти любые зависимости Framework, которые не будут работать в .NET Core.

Подведение итогов и ресурсы

Надеемся, что в этом примере показано, как воспользоваться преимуществами новой функциональности в Visual Studio 2019 и .NET Core 3.1 для переноса проектов C ++ / CLI в .NET Core. Следующие ссылки могут быть полезны для дальнейшего чтения.

C++/CLI .NET Core migration docs

Пример, использований в этом посте (исходный пример находится в основной ветке, а обновления .NET Core - в ветви netcore)

.NET Portability Analyzer

Источник



Posted on 21. March 2020

Обновление конструктора .NET Core Windows Forms

Microsoft выпустили предварительную версию Visual Studio 16.6 - Visual Studio 2019 версии 16.6 Preview 1 и вместе с ней новую версию .NET Core конструктора Windows Forms.

 

В этом релизе представлено

Поддержка следующих элементов управления:

·      FlowLayoutPanel,

·      GroupBox,

·      ImageList,

·      MenuStrip (через PropertyBrowser и контекстное меню),

·      Panel,

·      SplitContainer,

·      Splitter,

·      TabControl,

·      TableLayoutPanel,

·      ToolStrip (через  PropertyBrowser, контекстное меню  и дизайнерские действия).

○ Локальные ресурсы и локализованные формы были включены в конструкторе.

○ Поддержка для LayoutMode и ShowGrid/SnapToGrid настроек через Tools->Options.

○ Улучшение производительности и точности.

○ Другие мелкие исправления и правки.

 

Последование

В будущих выпусках мы будем работать над User Controls поддержки сторонних контроллеров, интеграции с популярными поставщиками контролей, поддержки элементов управления данными и связанных с ними сценариев, улучшения производительности и другие функции.

 

Как пользоваться конструктором

• Вам нужно воспользоваться Visual Studio Preview channel

•Нужно включить конструктор в Visual Studio. Перейдите по  Tools > Options > Environment > Preview Features и выбрать опцию Use the preview Windows Forms designer for .NET Core apps.

 

Как сообщить о проблемах

Ваше мнение очень важно для Microsoft! Пожалуйста, сообщайте о проблемах и отправляйте запросы функций через канал обратной связи Visual Studio. Используйте значок «Отправить отзыв» в правом верхнем углу Visual Studio, как показано ниже, и укажите, что он связан с областью «WinForms .NET Core».

Источник



Posted on 20. March 2020

Обзор Hosted App Model

В Windows 10 версии 2004 представлено концепцию размещенных приложений в Windows App Model. Размещенные приложения регистрируются как независимые приложения в Windows, но для их запуска требуется хост-процесс. Примером может служить файл сценария, который требует установки его хоста (например, Powershell или Python). Сам по себе это всего лишь файл, и он не имеет возможности отображаться как приложение для Windows. С помощью модели размещенного приложения приложение может объявить себя хостом, а затем пакеты могут объявить зависимость от этого хоста и называться размещенными приложениями. Когда запускается размещенное приложение, исполняемый файл узла запускается с идентификатором пакета размещенного приложения, а не с его собственной идентификацией. Это позволяет хосту иметь доступ к содержимому пакета размещенного приложения, а при вызове API он делает это с помощью идентификатора размещенного приложения.

Предыстория

Современные приложения определяются для Windows через подписанные пакеты MSIX. Пакет обеспечивает идентификацию, поэтому он известен системе и содержит все файлы, активы и регистрационную информацию для приложения. У многих приложений есть сценарии, в которых они хотят разместить контент и двоичные файлы, такие как точки расширения, из других приложений. Существуют также сценарии, в которых хост-приложение представляет собой скорее механизм времени выполнения, который загружает содержимое сценария. Вдобавок ко всему, существует желание, чтобы эти размещенные приложения выглядели и вели себя как отдельное приложение в системе - где у него есть собственная стартовая плитка, идентификация и глубокая интеграция с такими функциями Windows, как BackgroundTasks, Notifications и Share. С помощью модели размещенного приложения можно легко переименовать приложение розничного киоска, или скрипт Python или Powershell теперь можно рассматривать как отдельное приложение.

Разработчики пытаются сделать это сегодня одним из двух способов. Во-первых, они просто используют ярлык на рабочем столе для запуска хоста. Но как показывает опыт, это не имеет какой-либо глубокой интеграции с Windows и оболочкой, поскольку «приложение» - это исполняемый файл узла, а не сценарий. Чтобы получить более глубокую интеграцию, разработчики могут создать упакованное приложение, включающее двоичные файлы хоста в пакете. Хотя пакет теперь будет отдельным приложением и будет иметь возможность глубокой интеграции с Windows, этот подход неэффективен, поскольку каждое приложение должно было бы перераспределять хост а это может повлечь за собой потенциальные проблемы с обслуживанием и лицензированием.

Модель размещенных приложений удовлетворяет потребности этих размещенных приложений. Это зависит от двух частей: «хоста», доступного для других приложений, и «размещенного приложения», которое указывает на  зависимость от хоста. Когда запускается размещаемое приложение, в результате хост запускается под идентификатором пакета размещенного приложения, так что он может загружать визуальные ресурсы, содержимое из местоположения пакета размещенного приложения, и когда он вызывает API, он делает это с идентификатором, объявленным в размещенном приложении. Размещенное приложение получает пересечение возможностей, объявленных между хостом и размещенным приложением - это означает, что, если размещенное приложение не может запросить больше возможностей, чем предоставляет хост. В этом первоначальном выпуске модели размещенных приложений поддерживаются упакованные настольные приложения, и Windows будет расширять поддержку узлов UWP в будущих выпусках.

Что такое хост и размещенное приложение?

В частности, Host - это исполняемый файл в пакете, объявленном расширением HostRuntime который указывает на основной исполняемый файл или процесс выполнения для размещенного приложения. Расширение HostRuntime имеет атрибут Id, и этот идентификатор упоминается в качестве зависимости размещенным приложением в манифесте пакета. Хост может определить идентификатор пакета, под которым он в данный момент работает, ссылаясь на API Windows.ApplicationModel.Package.Current. Размещенное приложение - это приложение, которое объявляет зависимость пакета от хоста и использует для активации идентификатор HostRuntime вместо указания исполняемого файла Entrypoint в своем собственном пакете. Обычно он содержит контент, визуальные ресурсы, сценарии или двоичные файлы, к которым хост может получить доступ.

Пакеты размещенных приложений могут быть подписаны или не подписаны:

• Подписанные пакеты могут содержать исполняемые файлы. Это полезно в сценариях, которые имеют механизм расширения, загружать dll или зарегистрированный компонент в пакет размещенного приложения.

• Неподписанные пакеты могут содержать только неисполняемые файлы. Это полезно в сценариях, где hostruntime требуется только для загрузки изображений, ресурсов и контента. Неподписанные пакеты должны включать в свой идентификатор специальный OID неподписанного издателя, иначе им не будет разрешено зарегистрироваться. Это не позволяет неподписанным пакетам подделывать подписанные идентификаторы пакетов.

Объявление о хосте

Объявление хоста довольно просто. Все, что вам нужно сделать, это указать расширение пакета HostRuntime в вашем AppxManifest.xml. Расширение HostRuntime распространяется на весь пакет и поэтому объявляется дочерним элементом пакета. Ниже приведен отрывок из примера AppxManifest.xml, показывающий запись HostRuntime, которая объявляет приложение в качестве хоста с идентификатором «PythonHost».

hostRuntime - расширение пакета, определяющее информацию о времени выполнения, используемую при активации размещенного приложения.

Executable - исполняемый двоичный файл, который будет хост-процессом

RuntimeBehavior и TrustLevel - размещенное приложение будет работать с определениями, выраженными в расширении. Например, размещенное приложение, использующее узел, объявленный выше, будет запускать исполняемый файл PyScriptEngine.exe с уровнем доверия MiddleIL.

Host Runtime Is - уникальный идентификатор, используемый для указания хоста в пакете. Пакет может иметь несколько приложений хоста, и у каждого должен быть уникальный идентификатор HostRuntime. На этот идентификатор ссылается размещенное приложение.

Объявление о размещении приложения

Размещенное приложение должно объявить зависимость пакета от хоста и указать HostId для использования. Если пакет не подписан, он должен включать OID неподписанного издателя, чтобы удостоверение пакета не конфликтовало с подписанным пакетом. Также TargetDeviceFamily должен соответствовать хосту, поэтому он не пытается развертываться на устройствах, которые не поддерживаются хостом. Ниже приведен пример манифеста для размещенного приложения, который принимает зависимость от хоста Python.

Unsigned Publisher OID – 2.25.311729368913984317654407730594956997722=1 Этот идентификатор требуется, когда размещенное приложение будет неподписанным. Этот идентификатор гарантирует, что любой неподписанный пакет не сможет подделать удостоверение подписанного пакета.

HostRuntimeDependency - пакет размещенного приложения должен объявить HostRuntimeDependency в приложении хоста. Он состоит из имени и издателя пакета хоста и минимальной версии, от которой он зависит. Их можно найти в элементе в пакете Host. При развертывании, если HostRuntimeDependency не может быть найден, регистрация завершается неудачно.

HostId - вместо того, чтобы объявлять обычный исполняемый файл и EntryPoint для приложения или расширения, атрибут HostId выражает зависимость от приложения хоста. В результате размещенное приложение наследует атрибуты Executable, EntryPoint и среды выполнения Host с указанным HostId. При регистрации, если HostId не найден, развертывание не выполняется.

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

 

Динамическая регистрация для неподписанных размещенных приложений

Одним из преимуществ нового HostRuntime является то, что он позволяет хосту динамически регистрировать пакет размещенного приложения во время выполнения. Этот динамически зарегистрированный пакет не требует подписи. Что позволяет хосту динамически генерировать контент и манифест для пакета размещенного приложения, а затем регистрировать его. Разработчики работают с новым браузером Microsoft Edge, чтобы использовать преимущества модели размещенных приложений для Progressive Web Apps (PWA) - преобразование манифеста веб-приложения в манифест приложения, упаковка дополнительного веб-содержимого в пакет MSIX и его регистрация. В этой модели PWA - это собственное независимое приложение, зарегистрированное в системе, даже если оно размещено на Edge.

Новые API для регистрации пакета:

Management.Deployment.PackageManager.AddPackageByUriAsync () используется для регистрации пакета MSIX

• Management.Deployment.PackageManager.RegisterPackageByUriAsync () используется для регистрации свободного файла AppxManifest.xml.

В случае, когда размещенное приложение не подписано, его манифест должен соответствовать следующим требованиям:

1. Неподписанный пакет не может содержать никаких атрибутов Executable в своих элементах Application или Extension (например, нет или ), и он не может указывать какие-либо другие данные активации (Executable, TrustLevel и т. д.). Узел приложения поддерживает только элементы HostId и Parameters.

2. Неподписанный пакет должен быть основным типом пакета - он не может быть пакетом Bundle, Framework, Resource или Optional.

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

1. Процесс должен иметь идентичность пакета

2. Процесс должен иметь возможность управления пакетами

Примеры хоста и размещенного приложения

Давайте посмотрим на два примера. Первый, WinFormsToastHost, - это хост с подписанным размещенным приложением, который показывает, как включить расширение, которое динамически загружается в хост. Второй, NumberGuesser, пример использования python в качестве хоста и файла сценария в качестве пакета размещенного приложения. Вы можете найти пример кода для обоих по адресу https://aka.ms/hostedappsample.

WinFormsToastHost

Хост

Хост в этом примере - это простое приложение Windows Forms, которое отображает идентификацию своего пакета, местоположение и вызывает API-интерфейсы ToastNotification. Он также может загружать двоичное расширение из пакета размещенного приложения. При запуске под собственной идентификацией он не отображает информацию о расширении. Приложение поставляется вместе с проектом упаковки приложений Windows, который включает декларации манифеста о том, что он является хостом.

WinformsToastHost-Extension

Размещенное приложение - это библиотека .NET, которая реализует механизм расширения для загрузки хоста. Он также включает в себя проект упаковки, который объявляет свою идентичность и зависимость от hostruntime. Эта личность будет отображаться в значениях, отображаемых при запуске приложения. После регистрации hostruntime имеет доступ к расположению пакета в hostedapp и, таким образом, может загрузить расширение.

Запуск образца

Вы можете загрузить исходный код в Visual Studio следующим образом:

1. Откройте WinformsToastHost.sln в VS2019

2. Build и deploy  WinformsToastHost.Package

3. Build и deploy HostedAppExtension

4. Перейти в меню «Пуск» и запустить «WinformsToastHost»

5. Перейдите в меню «Пуск» и запустите «Hosted WinformsToastHost Extension»

Вот скриншот работающего хоста. Обратите внимание на его идентификатор пакета и путь, а UX для загрузки сборки недоступен, поскольку он не работает  как размещенное приложение.

Теперь запустите размещенное приложение. Обратите внимание, что идентификатор и путь изменились, и что UX для динамической загрузки сборки расширения включен.

При нажатии кнопки «Run hosted» вы получите диалог из двоичного расширения:

Вот подробное представление диспетчера задач, показывающее, что оба приложения работают одновременно. Обратите внимание, что двоичный файл хоста является исполняемым для обоих:

При нажатии на кнопку «Показать тост» для каждого приложения система распознает две разные личности в центре действий:

NumberGuesser – Игры и  Python

Хост

В этом примере хост состоит из 2 проектов. Первый - это PyScriptEngine, который является оболочкой, написанной на C #, и использует пакет nuget Python для запуска скриптов Python. Эта оболочка анализирует командную строку и имеет возможность динамически регистрировать манифест, а также запускать исполняемый файл python с путем к файлу сценария. Вторым проектом является PyScriptEnginePackage, который представляет собой проект упаковки приложений Windows, который устанавливает PyScriptEngine и регистрирует манифест, который включает расширение HostRuntime.

Хостинг приложения

Размещенное приложение состоит из скрипта Python, NumberGuesser.py и визуальных ресурсов. Он не содержит PE-файлов. Он имеет манифест приложения, в котором объявляются заявления для HostRuntimeDependency и HostId, которые идентифицируют PyScriptEngine в качестве своего хоста. Манифест также содержит запись OID неподписанного издателя, которая требуется для неподписанного пакета.

Запуск образца

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

1. Откройте расширение PyScriptEngine.sln в Visual Studio

2. Установите PyScriptEnginePackage в качестве проекта запуска

3. Сборка PyScriptEnginePackage

4. Развернуть PyScriptEnginePackage

5. Поскольку приложение хоста объявляет appexecutionalias, вы сможете перейти в командную строку и запустить «pyscriptengine», чтобы получить уведомление об использовании:

6. Используйте хост python для регистрации игры Number Guesser из командной строки:

7. Теперь нажмите «Number Guesser (Manifest)» в меню «Пуск» и запустите игру! Посмотрите, сколько попыток нужно, чтобы угадать число:

Давайте подтвердим, что это работает. Обратите внимание, как PyScriptEngine выполняется под идентификатором пакета NumberGuesser!

Подведем итоги!

Таким образом, Microsoft предоставляет нам больше возможностей и возможностей для платформы Windows, и команды рады видеть, какие креативные идеи у вас есть для модели размещенного приложения. В дополнение к Microsoft Edge, ведется разработка с командами по всей компании и ожидается больше приложений, использующих Hosted App Model в будущем.

 

Источник



Posted on 19. March 2020

Асинхронное объединение ValueTask в .NET 5

Функция async / await в C # произвела революцию в том, как разработчики, нацеленные на .NET, пишут асинхронный код. Прибавьте немного async и await, измените, некоторые типы возвращаемых данных на задачи, и вы получите асинхронную реализацию. Теоретически.

На практике, очевидно, я преувеличивал легкость, с которой кодовая база может быть сделана полностью асинхронной, как и со многими задачами в разработке программного обеспечения, загвоздки часто в деталях. Одной из таких «загвоздок», с которыми, вероятно, знакомы разработчики .NET, ориентированные на производительность, является объект конечного автомата, который позволяет асинхронному методу выполнить свою магию.

Распределения и конечные автоматы

Когда вы пишете асинхронный метод в C #, компилятор переписывает это в конечный автомат, где большая часть вашего кода в вашем асинхронном методе перемещается в MoveNext сгенерированного компилятором типа (структура в сборках Release),  и с этим MoveNext  завален переходами и метками, которые позволяют методу приостановить и резюмировать в пункты  await. К незавершенным задачам await подключено продолжение (обратный вызов), которое при окончательном завершении задачи вызывает метод MoveNext и переходит к месту, где функция была приостановлена. Для того чтобы локальные переменные могли поддерживать свое состояние через эти выходы и повторные входы метода, соответствующие «локальные объекты» переписываются компилятором в поля типа конечного автомата. И для того, чтобы этот конечный автомат как структура сохранялся в тех же самых приостановках, он должен быть перемещен в кучу.

Компилятор C # и среда выполнения .NET изо всех сил стараются не помещать этот конечный автомат в кучу. Многие вызовы асинхронных методов фактически завершаются синхронно, и компилятор и среда выполнения настраиваются на этот вариант использования.  Как указано, в релизном билде, конечный автомат, сгенерированный компилятором, является структурой, и когда вызывается асинхронный метод, конечный автомат начинает свою жизнь в стеке. Если асинхронный метод завершается без приостановки, конечный автомат успешно завершится, никогда не вызывая распределение. Однако, если асинхронный метод когда-либо нужно приостановить, конечный автомат должен быть каким-то образом собран.

В .NET Framework, момент Task или  ValueTask возвращение асинхронного метода (как общего, так и не универсального) приостанавливается впервые, происходит несколько выделений:

1. Структура конечного автомата копируется в кучу через стандартный бокс времени выполнения; каждый конечный автомат реализует IAsyncStateMachine  интерфейс, среда выполнения буквально приводит структуру к этому интерфейсу.

2. Среда выполнения фиксирует текущий ExecutionContext а затем выделяет объект (он называет это «бегун»), который он использует для хранения обоих конечных автоматов в штучной упаковке и ExecutionContext  (обратите внимание, что в .NET Framework, регистрация ExecutionContext  если это не значение по умолчанию, это также приводит к одному или нескольким выделениям).

3. Среда выполнения выделяет Action , который указывает на метод в этом объекте запуска, потому что шаблон ожидающего требует Action  которые будут переданы ожидающему методу {Unsafe}OnCompleted; при вызове Action будет использовать ExecutionContext для вызова метода MoveNext на конечном компьютере.

4. Среда выполнения выделяет объект Task, который будет завершен после завершения асинхронного метода и это возвращается из асинхронного метода к его синхронному вызывающему (если асинхронный метод набран для возврата ValueTask, структура ValueTask просто оборачивается вокруг объекта Task).

Это как минимум четыре средства, когда асинхронный метод в первый раз приостанавливается. Кроме того, каждый последующий раз асинхронный метод приостанавливается, если мы окажемся с нестандартным ExecutionContext  (например, он переносит состояние для AsyncLocal),  среда выполнения перераспределяет это в запускающийся объект, затем перераспределяет действие, которое указывает на него (потому что делегаты неизменны), каждый раз выполняя минимум два дополнительных выделения, когда асинхронный метод приостанавливается после первого раза. Вот простое повторение этого в Visual Studio с правым окном, в котором отображаются распределения в соответствии с инструментом отслеживания распределения объектов .NET:

Это было значительно улучшено, в .NET Core, особенно с .NET Core 2.1. Когда асинхронный метод приостанавливается, выделяется Task. Но это не базовый тип Task или Task. Структура конечного автомата хранится в строго типизированном поле для этого производного типа, устранение необходимости в отдельном распределении бокса. Этот тип также имеет поле для захваченного ExecutionContext (который является неизменным в .NET Core, это означает что захват никогда не выделяется), нам не нужен отдельный объект ранера. И у среды выполнения теперь есть специальные пути кода, которые поддерживают передачу этого типа AsyncStateMachineBox напрямую всем ожидающим, о которых среда выполнения знает, это означает, что пока асинхронный метод ожидает только TaskTaskValueTask или ValueTask (напрямую или через их аналоги ConfigureAwait), ему вообще не нужно выделять Action. Затем, поскольку у нас есть прямой доступ к полю ExecutionContext, последующие приостановки не требуют выделения нового участника (участники полностью отсутствуют), это также означает, что даже если нам нужно было распределить действие, нам не нужно его перераспределять. Это значит, тогда как в .NET Framework у нас есть как минимум четыре выделения для первой приостановки и часто по крайней мере два распределения для каждой последующей приостановки, в .NET Core у нас есть одно распределение для первого приостановления (наихудший случай два, если используются пользовательские ожидающие), и это все. Другие изменения, такие как переписывание инфраструктуры очередей ThreadPool, также значительно сократили распределение.

 

Это изменение оказало очень ощутимое влияние на производительность (и, как оказалось, не только на производительность; оно также очень полезно для отладки), и мы все можем радоваться удалению ненужных ассигнований. Однако, как уже было отмечено, одно распределение все еще остается, когда асинхронный метод завершается асинхронно. Но ... что если мы тоже сможем избавиться от этого?  Что если бы мы могли сделать так, чтобы вызов асинхронного метода имел (амортизировался) накладные расходы при нулевом распределении независимо от того, завершился он синхронно или асинхронно?

ValueTask

ValueTask был введен в период .NET Core 1.0, чтобы помочь разработчикам избежать выделения ресурсов,  когда асинхронные методы завершаются синхронно. Это была относительно простая структура, представляющая различаемое объединение между TResult и Task. При использовании в качестве типа результата асинхронного метода, если вызов асинхронного метода возвращается синхронно, независимо от значения результата TResult, метод требует нулевого распределения накладных расходов: конечный автомат не нужно перемещать в кучу, и нет необходимости в задании Task для результата; значение результата просто сохраняется в поле TResult возвращенной ValueTask. Однако, если асинхронный метод завершается асинхронно, среда выполнения возвращается к поведению так же, как и в случае с задачей Task: он создает единственную задачу AsyncStateMachineBox, который затем возвращается в структуру ValueTask.

В .NET Core 2.1 мы представили интерфейс IValueTaskSource, наряду с неуниверсальными аналогами ValueTask и IValueTaskSource. Мы также сделали ValueTask способным хранить не только TResult, но и Task, но также IValueTaskSource (то же самое для неуниверсального ValueTask, который, может хранить Task или IValueTaskSource). Этот продвинутый интерфейс позволяет предприимчивому разработчику написать свое собственное резервное хранилище для задачи,  и они могут делать это таким образом, чтобы повторно использовать этот объект хранилища резервных копий для нескольких не параллельных операций (намного больше информации об этом доступно в этом посте). Например, Socket обычно используется не более чем для одной операции приема и одна операция отправки за раз. Socket  был изменен для хранения повторно используемого / сбрасываемого IValueTaskSource для каждого направления и каждой последующей операции чтения или записи что завершает и асинхронно раздает ValueTask, поддерживаемый соответствующим общим экземпляром. Это означает, что в подавляющем большинстве случаев методы ReceiveAsync/SendAsync на основе ValueTask в Socket  в конечном итоге не выделяются, независимо от того, выполняются они синхронно или асинхронно.  Несколько типов получили эту обработку, но только в тех случаях, где это будет действенно.

Таким образом, в .NET Core 2.1 были добавлены несколько реализаций в ключевых областях, таких как System.Net.SocketsSystem.Threading.Channels и System.IO.Pipelines, но не намного дальше. Впоследствии мы ввели тип ManualResetValueTaskSource, чтобы упростить такие реализации, и в результате было добавлено больше реализаций этих интерфейсов в .NET Core 3.0, а также в .NET 5, хотя в основном внутри различных компонентов, таких как System.Net.Http.

Улучшения в .NET 5

В .NET 5 мы дальше экспериментируем с этой оптимизацией. С .NET 5 Preview 1, если до запуска вашего процесса для переменной среды DOTNET_SYSTEM_THREADING_POOLASYNCVALUETASKS установлено значение true  или 1, среда выполнения будет использовать объекты конечного автомата, которые реализуют интерфейсы IValueTaskSource и IValueTaskSource. Он будет объединять объекты, которые создает, для возвращенных экземпляров из асинхронных методов async ValueTask  или async ValueTask. Итак, если, как и в предыдущем примере, вы повторно вызываете один и тот же метод и ожидаете результата, каждый раз, когда вы в конечном итоге получите ValueTask, который оборачивает один и тот же объект, просто сбрасывайте его каждый раз, чтобы позволить отслеживать другое выполнение. Магия.


Почему он не включен по умолчанию прямо сейчас? Две основные причины:

1. Объединение не является бесплатным. Разработчик может оптимизировать свой код различными способами. Один из них - просто улучшить код, чтобы больше не нуждаться в выделении; с точки зрения производительности это, как правило, очень низкий риск. Другой - повторно использовать уже доступный объект, например, добавив дополнительное поле к существующему объекту с аналогичным сроком службы; это все еще требует более подробного анализа производительности. Затем приходит объединение. Оно может быть очень полезным, когда создание объединяемой вещи очень ценно; хорошим примером этого является пул соединений HTTPS, где стоимость установления нового безопасного соединения, как правило, на несколько порядков дороже, чем доступ к нему даже в самой наивной структуре пулов данных. Более спорная форма объединения - это когда пул предназначен для дешевых объектов с целью избежать затрат на сборку мусора. Используя такой пул, разработчик делает ставку на то, что он может реализовать собственный распределитель (который действительно является пулом), который лучше, чем универсальный распределитель GC. Победить в сборной нетривиально. Но разработчик может это сделать, учитывая знания, которые они имеют в своем конкретном сценарии. Например, .NET GC очень хорошо умеет эффективно собирать недолговечные объекты, которые становятся коллекционными в поколении 0, и попытка объединения таких объектов может легко сделать программу более дорогой (даже если это выглядит хорошо на микробенчмарке, сфокусированном на измерении распределения). Но если вы знаете, что ваши объекты, вероятно, выживут в gen0, например, если они используются для представления потенциально асинхронных операций с большой задержкой, вполне возможно, что пользовательский пул может сбрить некоторые накладные расходы. Мы еще не сделали этот асинхронный пул async ValueTask по умолчанию, потому что, хотя он хорошо выглядит на микробенчмарках, мы не уверены, что это действительно значительное улучшение рабочих нагрузок в реальном мире.

2. ValueTasks имеют ограничения. Типы Task  и Task были разработаны, чтобы быть очень надежными. Вы можете их кешировать. Вы можете ждать их любое количество. Они поддерживают несколько продолжений. Они потокобезопасны, с любым количеством потоков, способных одновременно регистрировать продолжения. И в дополнение к ожиданию и поддержке асинхронных уведомлений о завершении, они также поддерживают модель блокировки, при этом синхронные абоненты могут ожидать получения результата. Ничто из этого не относится к ValueTask и ValueTask. Потому что они могут быть поддержаны сбрасываемыми экземплярами IValueTaskSource, вы не должны их кэшировать (то, что они переносят, может быть использовано повторно) и не ждать их несколько раз. Вы не должны пытаться зарегистрировать несколько продолжений (после первого завершения объект может попытаться сбросить себя для другой операции), будь то одновременно или нет. И вы не должны пытаться блокировать ожидание их завершения (реализации IValueTaskSource не должны предоставлять такую семантику). Пока вызывающие абоненты напрямую ожидают результата вызова метода, который возвращает  ValueTask или ValueTask, все должно работать хорошо, но как только кто-то сходит с этого золотого пути, все может быстро измениться; это может означать получение исключений или коррупцию в процессе. Кроме того, эти сложности обычно проявляются только тогда, когда ValueTask или ValueTask переносят реализацию IValueTaskSource; когда они переносят Task, вещи обычно «просто работают», так как ValueTask наследует надежность Task, и когда они оборачивают необработанное значение результата, ограничения технически вообще не применяются. И это означает, что, переключая асинхронные методы async ValueTask с поддержкой Task, вместо поддержки этих объединенных реализаций IValueTaskSource, мы могли бы выявлять скрытые ошибки в приложении разработчика, либо напрямую, либо через библиотеки, которые они используют. Предстоящий выпуск Roslyn Analyzers будет включать в себя анализатор, который должен помочь найти большинство нецелевых использований.

Призыв к действию

Если у вас есть приложение, которому, по вашему мнению, будет полезно это объединение, мы будем рады получить от вас сообщение. Скачивайте .NET 5 Preview 1. Попробуйте включить эту функцию. Что-нибудь сломается, в вашем коде, или в другой библиотеке, или в самом .NET. Или вы увидите значительные изменения в производительности, такие как пропускная способность или задержка, или рабочий набор, или что-то еще интересное. Обратите внимание, что изменение касается только асинхронных методов async ValueTask и async ValueTask, поэтому, если у вас есть async Task или async Task, вам также может потребоваться сначала изменить их, чтобы использовать их эквиваленты ValueTask.

Выпуск dotnet / runtime # 13633 отбражает виденье того, что мы должны делать с этой функцией для .NET 5, и Microsoft хочет услышать ваш фидбек; команда будет рада, если вы опубликуете какие-либо мысли или результаты.


Источник



Posted on 18. March 2020

Анонс Entity Framework Core 5.0

https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-5-0-preview-1/

Microsoft объявила о первом анонсе EF Core 5.0.

Предпосылки

Для предварительного просмотра EF Core 5.0 требуется .NET Standard 2.1. Это означает:

• EF Core 5.0 работает на .NET Core 3.1; это не требует .NET 5.

○ Это может измениться в будущих превью в зависимости от того, как будет развиваться план для .NET 5.

EF Core 5.0 работает на других платформах, поддерживающих .NET Standard 2.1.

EF Core 5.0 не будет работать на платформах .NET Standard 2.0, включая .NET Framework.

Как скачать EF Core 5.0?

EF Core распространяется исключительно как набор пакетов NuGet. Например, чтобы добавить поставщика SQL Server в свой проект, вы можете использовать следующую команду с помощью инструмента dotnet:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 5.0.0-preview.2.20120.8

 

Пакеты EF Core, опубликованные сегодня:

Microsoft.EntityFrameworkCore - основной пакет EF Core

Microsoft.EntityFrameworkCore.SqlServer - поставщик базы данных для Microsoft SQL Server и SQL Azure

Microsoft.EntityFrameworkCore.Sqlite - поставщик базы данных для SQLite

Microsoft.EntityFrameworkCore.Cosmos - поставщик базы данных для Azure Cosmos DB

Microsoft.EntityFrameworkCore.InMemory - поставщик базы данных в памяти

Microsoft.EntityFrameworkCore.Tools - команды EF Core PowerShell для консоли диспетчера пакетов Visual Studio

Microsoft.EntityFrameworkCore.Design - общие компоненты времени разработки для инструментов EF Core

Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite - поддержка SQL Server для пространственных типов

Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite - поддержка SQLite для пространственных типов

Microsoft.EntityFrameworkCore.Proxies - загрузка и отслеживание изменений прокси

Microsoft.EntityFrameworkCore.Abstractions - разделенные EF Core абстракции

Microsoft.EntityFrameworkCore.Relational - общие компоненты EF Core для поставщиков реляционных баз данных

Microsoft.EntityFrameworkCore.Analyzers - анализаторы C # для EF Core

Microsoft.EntityFrameworkCore.Sqlite.Core - поставщик базы данных для SQLite без упакованного собственного двоичного файла

Microsoft опубликовали анонс о Framework Core 5.0 от  поставщика ADO.NET Microsoft.Data.Sqlite.Core.

Установка dotnet ef

Как и в случае EF Core 3.0 и 3.1, инструмент командной строки dotnet ef больше не включается в .NET Core SDK. Прежде чем вы сможете выполнить команды переноса EF Core или создания лесов, вам необходимо установить этот пакет как глобальный или локальный инструмент.

Чтобы установить инструмент предварительного просмотра глобально, сначала удалите любую существующую версию с помощью:

dotnet tool uninstall --global dotnet-ef

 

Затем установите с помощью:

dotnet tool install --global dotnet-ef --version 5.0.0-preview.2.20120.8

Эту новую версию dotnet ef можно использовать с проектами, в которых используются более старые версии среды выполнения EF Core.

Номера версий пакетов

В процессе сборки .NET 5 произошла ошибка, в результате которой пакеты EF preview 1 были ошибочно помечены как «5.0.0-preview.2.20120.8».

Это не должно иметь никакого функционального воздействия и не должно повлиять на Preview 2, который все еще запланирован на конец года.

Что нового в EF Core 5 Preview 1

Microsoft поддерживаем документацию новых функциях, представленных в каждом предварительном просмотре.

Некоторые из основных моментов из предварительного просмотра 1 вызываются ниже.

Простая регистрация

Эта опция функционально похожа на Database.Log в EF6. Таким образом, он предоставляет простой способ получения журналов из EF Core без необходимости настройки какого-либо внешнего каркаса ведения журналов.

EF Core заменяет Database.Log методом LogTo, вызываемым для DbContextOptionsBuilder в AddDbContext или OnConfiguring. Например:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(Console.WriteLine);

 

Существуют перегрузки для:

• Установите минимальный уровень журнала

Пример: .LogTo(Console.WriteLine, LogLevel.Information)

• Фильтр только для определенных событий

Пример: .LogTo(Console.WriteLine, new[] {CoreEventId.ContextInitialized, RelationalEventId.CommandExecuted})

• Фильтр для всех событий в определенных категориях:

Пример: .LogTo(Console.WriteLine, new[] {DbLoggerCategory.Database.Name}, LogLevel.Information)

• Используйте пользовательский фильтр по событию и уровню:

Пример: .LogTo(Console.WriteLine, (id, level) => id == RelationalEventId.CommandExecuting)

 

Формат вывода может быть минимально сконфигурирован (API постоянно меняется), но вывод по умолчанию выглядит примерно так:

warn: 12/5/2019 09:57:47.574 CoreEventId.SensitiveDataLoggingEnabledWarning[10400] (Microsoft.EntityFrameworkCore.Infrastructure)
      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data, this mode should only be enabled during development.
dbug: 12/5/2019 09:57:47.581 CoreEventId.ShadowPropertyCreated[10600] (Microsoft.EntityFrameworkCore.Model.Validation)
      The property 'BlogId' on entity type 'Post' was created in shadow state because there are no eligible CLR members with a matching name.
info: 12/5/2019 09:57:47.618 CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure)
      Entity Framework Core 5.0.0-dev initialized 'BloggingContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: SensitiveDataLoggingEnabled
dbug: 12/5/2019 09:57:47.644 CoreEventId.ValueGenerated[10808] (Microsoft.EntityFrameworkCore.ChangeTracking)
      'BloggingContext' generated temporary value '-2147482647' for the 'Id' property of new 'Blog' entity.
...

 

Простой способ получить сгенерированный SQL

В EF Core 5.0 представлен метод расширения ToQueryString, который будет возвращать SQL, который EF Core сгенерирует при выполнении запроса LINQ. Например, код:

var query = context.Set<customer>().Where(c => c.City == city);
Console.WriteLine(query.ToQueryString())

приводит к таким выводам при использовании поставщика базы данных SQL Server:

DECLARE p0 nvarchar(4000) = N'London';
 
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
WHERE [c].[City] = @__city_0

 

Обратите внимание, что объявления для параметров правильного типа также включены в вывод. Это позволяет копировать / вставлять в SQL Server Management Studio или аналогичные инструменты, так что запрос может быть выполнен для отладки / анализа.

Используйте атрибут C #, чтобы указать, что у объекта нет ключа

Тип объекта теперь можно настроить как “не имеющий ключа”, используя новый KeylessAttribute. Например:

[Keyless]
public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public int Zip { get; set; }
}

 

Соединение или строка соединения могут быть изменены при инициализации DbContext

Теперь проще создать экземпляр DbContext без какого-либо соединения или строки соединения. Кроме того, соединение или строка соединения теперь могут быть изменены в экземпляре контекста. Это позволяет одному и тому же экземпляру контекста динамически подключаться к разным базам данных.

Прокси отслеживания изменений

EF Core теперь может генерировать прокси во время выполнения, которые автоматически реализуют INotifyPropertyChanging и  INotifyPropertyChanged. Затем они сообщают об изменениях значений свойств сущностей непосредственно в EF Core, избегая необходимости сканировать изменения. Однако прокси-серверы имеют свои собственные ограничения, поэтому они не для всех.

Расширенные представления отладки

Представления отладки - это простой способ взглянуть на внутренности EF Core при отладке проблем. Представление отладки для Модели было реализовано. Для EF Core 5.0 Microsoft  также упростили представление модели и добавили новое представление отладки для отслеживаемых объектов в диспетчере состояний.

Модель отладки

Разверните свойство Model объекта DbContext в выбранном отладчике и раскройте свойство DebugView.

LongView - это вид модели, который у нас был в течение некоторого времени. ShortView является новым и не включает аннотации моделей, которые значительно облегчают чтение. Например, вот одна из наших тестовых моделей:

Model:

  EntityType: Chassis

    Properties:

      TeamId (int) Required PK FK AfterSave:Throw

      Name (string)

      Version (no field, byte[]) Shadow Concurrency BeforeSave:Ignore AfterSave:Ignore ValueGenerated.OnAddOrUpdate

    Navigations:

      Team (_team, Team) ToPrincipal Team Inverse: Chassis PropertyAccessMode.Field

    Keys:

      TeamId PK

    Foreign keys:

      Chassis {'TeamId'} -> Team {'Id'} Unique ToDependent: Chassis ToPrincipal: Team

  EntityType: Driver

    Properties:

      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd

      CarNumber (Nullable)

      Championships (int) Required

      Discriminator (no field, string) Shadow Required

      FastestLaps (int) Required

      Name (string)

      Podiums (int) Required

      Poles (int) Required

      Races (int) Required

      TeamId (int) Required FK Index

      Version (no field, byte[]) Shadow Concurrency BeforeSave:Ignore AfterSave:Ignore ValueGenerated.OnAddOrUpdate

      Wins (int) Required

    Navigations:

      Team (_team, Team) ToPrincipal Team Inverse: Drivers PropertyAccessMode.Field

    Keys:

      Id PK

    Foreign keys:

      Driver {'TeamId'} -> Team {'Id'} ToDependent: Drivers ToPrincipal: Team

    Indexes:

      TeamId

  EntityType: Engine

    Properties:

      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd

      EngineSupplierId (int) Required FK Index Concurrency

      Name (string) Concurrency

    Navigations:

      EngineSupplier (_engineSupplier, EngineSupplier) ToPrincipal EngineSupplier Inverse: Engines PropertyAccessMode.Field

      Gearboxes (_gearboxes, ICollection) Collection ToDependent Gearbox PropertyAccessMode.Field

      StorageLocation (Location) ToDependent Location PropertyAccessMode.Field

      Teams (_teams, ICollection) Collection ToDependent Team Inverse: Engine PropertyAccessMode.Field

    Keys:

      Id PK

    Foreign keys:

      Engine {'EngineSupplierId'} -> EngineSupplier {'Id'} ToDependent: Engines ToPrincipal: EngineSupplier

    Indexes:

      EngineSupplierId

  EntityType: EngineSupplier

    Properties:

      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd

      Name (string)

    Navigations:

      Engines (_engines, ICollection) Collection ToDependent Engine Inverse: EngineSupplier PropertyAccessMode.Field

    Keys:

      Id PK

  EntityType: Gearbox

    Properties:

      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd

      EngineId (no field, Nullable) Shadow FK Index

      Name (string)

    Keys:

      Id PK

    Foreign keys:

      Gearbox {'EngineId'} -> Engine {'Id'} ToDependent: Gearboxes

    Indexes:

      EngineId

  EntityType: Location

    Properties:

      EngineId (no field, int) Shadow Required PK FK AfterSave:Throw ValueGenerated.OnAdd

      Latitude (double) Required Concurrency

      Longitude (double) Required Concurrency

    Keys:

      EngineId PK

    Foreign keys:

      Location {'EngineId'} -> Engine {'Id'} Unique Ownership ToDependent: StorageLocation

  EntityType: Sponsor

    Properties:

      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd

      ClientToken (no field, Nullableint><int>) Shadow Concurrency

      Discriminator (no field, string) Shadow Required

      Name (string)

      Version (no field, byte[]) Shadow Concurrency BeforeSave:Ignore AfterSave:Ignore ValueGenerated.OnAddOrUpdate

    Keys:

      Id PK

  EntityType: SponsorDetails

    Properties:

      TitleSponsorId (no field, int) Shadow Required PK FK AfterSave:Throw ValueGenerated.OnAdd

      ClientToken (no field, Nullableint><int>) Shadow Concurrency

      Days (int) Required

      Space (decimal) Required

      Version (no field, byte[]) Shadow Concurrency BeforeSave:Ignore AfterSave:Ignore ValueGenerated.OnAddOrUpdate

    Keys:

      TitleSponsorId PK

    Foreign keys:

      SponsorDetails {'TitleSponsorId'} -> TitleSponsor {'Id'} Unique Ownership ToDependent: Details

  EntityType: Team

    Properties:

      Id (int) Required PK AfterSave:Throw

      Constructor (string)

      ConstructorsChampionships (int) Required

      DriversChampionships (int) Required

      EngineId (no field, Nullableint><int>) Shadow FK Index

      FastestLaps (int) Required

      GearboxId (Nullableint><int>) FK Index

      Name (string)

      Poles (int) Required

      Principal (string)

      Races (int) Required

      Tire (string)

      Version (no field, byte[]) Shadow Concurrency BeforeSave:Ignore AfterSave:Ignore ValueGenerated.OnAddOrUpdate

      Victories (int) Required

    Navigations:

      Chassis (_chassis, Chassis) ToDependent Chassis Inverse: Team PropertyAccessMode.Field

      Drivers (_drivers, ICollection) Collection ToDependent Driver Inverse: Team PropertyAccessMode.Field

      Engine (_engine, Engine) ToPrincipal Engine Inverse: Teams PropertyAccessMode.Field

      Gearbox (_gearbox, Gearbox) ToPrincipal Gearbox PropertyAccessMode.Field

    Keys:

      Id PK

    Foreign keys:

      Team {'EngineId'} -> Engine {'Id'} ToDependent: Teams ToPrincipal: Engine

      Team {'GearboxId'} -> Gearbox {'Id'} Unique ToPrincipal: Gearbox

    Indexes:

      EngineId

      GearboxId Unique

  EntityType: TestDriver Base: Driver

  EntityType: TitleSponsor Base: Sponsor

    Navigations:

      Details (_details, SponsorDetails) ToDependent SponsorDetails PropertyAccessMode.Field

 

Менеджер “debug view

Состояние менеджера немного скрыто, чем модель. Чтобы найти его, перейдите в свойство ChangeTracker объекта DbContext в выбранном вами отладчике, а затем посмотрите в свойстве StateManager  и разверните DebugView.

Краткий обзор менеджера отображает:

• Каждый объект отслеживается

• Значение первичного ключа

• Состояние объекта: добавлено, не изменено, изменено или удалено.

• Значения свойства внешнего ключа

Например:

Engine (Shared) {Id: 1} Unchanged FK {EngineSupplierId: 1}
Location (Shared) {EngineId: 1} Unchanged FK {EngineId: 1}
Team (Shared) {Id: 4} Modified FK {EngineId: 1} FK {GearboxId: }

 

Длинный вид показывает все в коротком виде:

• Текущее значение каждого свойства

• Независимо от того, помечено ли свойство как измененное

• Исходное значение свойства, если оно отличается от текущего значения

• Сущность, на которую ссылается ссылочная навигация с использованием значения первичного ключа ссылочной сущности

• Список объектов, на которые ссылается навигация по коллекции, снова используя значения первичного ключа

Например:

Engine (Shared) {Id: 1} Unchanged
  Id: 1 PK
  EngineSupplierId: 1 FK
  Name: 'FO 108X'
  EngineSupplier: 
  Gearboxes: null><null>
  StorageLocation: {EngineId: 1}
  Teams: [{Id: 4}]
Location (Shared) {EngineId: 1} Unchanged
  EngineId: 1 PK FK
  Latitude: 47.64491
  Longitude: -122.128101
Team (Shared) {Id: 4} Modified
  Id: 4 PK
  Constructor: 'Ferrari'
  ConstructorsChampionships: 16
  DriversChampionships: 15
  EngineId: 1 FK Modified Originally 3
  FastestLaps: 221
  GearboxId: null><null> FK
  Name: 'Scuderia Ferrari Marlboro'
  Poles: 203
  Principal: 'Stefano Domenicali'
  Races: 805
  Tire: 'Bridgestone'
  Version: '0x000000000001405A'
  Victories: 212
  Chassis: null><null>
  Drivers: []
  Engine: {Id: 1}
  Gearbox: null><null>

 

Улучшена обработка нулевой семантики базы данных

Реляционные базы данных обычно обрабатывают NULL как неизвестное значение и, следовательно, не равны никаким другим NULL. C #, с другой стороны, рассматривает нулл как определенное значение, которое сравнивается с любым другим нулл. EF Core по умолчанию переводит запросы так, чтобы они использовали нулевую семантику C #. EF Core 5.0 значительно повышает эффективность этих переводов.

Свойства индексатора

EF Core 5.0 поддерживает отображение свойств индексатора C #. Это позволяет подразделениям действовать как пакеты свойств, в которых столбцы сопоставляются с именованными свойствами в пакете.

Генерация проверочных ограничений для отображений enum

Миграции EF Core 5.0 теперь могут генерировать ограничения CHECK для сопоставлений свойств перечисления. Например:

EnumColumn VARCHAR(10) NOT NULL CHECK (MyEnumColumn IN('Useful', 'Useless', 'Unknown'))

 

IsRelational

Новый метод IsRelational был добавлен в дополнение к существующим IsSqlServerIsSqlite и IsInMemory.

Это можно использовать для проверки, использует ли DbContext какой-либо поставщик реляционных баз данных. Например:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    if (Database.IsRelational())
    {
        // Do relational-specific model configuration.
    }
}

 

Советующая поддержка  Cosmos с ETags

Поставщик базы данных Azure Cosmos DB теперь поддерживает ETags. Используйте конструктор моделей в OnModelCreating для настройки ETag:

builder.Entity&lt;customer>().Property(c => c.ETag).IsEtagConcurrency();

 

Затем SaveChanges генерирует исключение DbUpdateConcurrencyException при конфликте параллелизма, который может быть обработан для реализации повторных попыток и т. Д.

Как запросить переводы для большего количества конструкций DateTime?

Запросы, содержащие новую конструкцию DateTime, теперь переведены.

Кроме того, теперь сопоставлены следующие функции SQL Server: * DateDiffWeek * DateFromParts

Например:

var count = context.Orders.Count(c => date > EF.Functions.DateFromParts(DateTime.Now.Year, 12, 25));

 

Перевод запросов для большего количества массива байтов

Запросы, использующие свойства Contains, Length, SequenceEqual и т. Д. В byte [], теперь переводятся в SQL. Например:

var blogs = context.Blogs.Where(e => e.Picture.Contains((byte)127)).ToList();

 

Перевод запроса для реверса

Запросы с использованием Reverse теперь переведены. Например:

context.Employees.OrderBy(e => e.EmployeeID).Reverse()

 

Запрос для битовых операторов

Запросы с использованием битовых операторов теперь транслируются в большем количестве случаев. Например:

context.Orders.Where(o => ~o.OrderID == negatedId)

 

Перевод запроса на строки в Cosmos

Запросы, использующие строковые методы Contains, StartsWith и EndsWith, теперь переводятся при использовании поставщика Azure Cosmos DB.

Ежедневные сборки

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

Как и в случае предварительного просмотра, для ежедневных сборок не требуется .NET 5; их можно использовать с GA / RTM-версией .NET Core 3.1.

Документация и отзывы

Отправной точкой для всей документации EF Core является docs.microsoft.com/ef/core/.

Пожалуйста, сообщайте о найденных проблемах и любые другие отзывы dotnet/efcore GitHub repo.

Спасибо команде!

Большое спасибо команде EF всем, кто использовал EF на протяжении многих лет!

Спасибо авторам!

Большое спасибо следующим членам сообщества, которые уже предоставили код или документацию для выпуска EF Core 5!


 

Источник



Posted on 18. March 2020

Анонс Entity Framework Core 5.0 Preview 1

Сегодня Microsoft объявили о первом пред просмотре EF Core 5.0.

Предпосылки

Для предварительного просмотра EF Core 5.0 требуется .NET Standard 2.1. Это означает:

• EF Core 5.0 работает на .NET Core 3.1; это не требует .NET 5.

○ Это может измениться в будущих превью в зависимости от того, как будет развиваться план для .NET 5.

EF Core 5.0 работает на других платформах, поддерживающих .NET Standard 2.1.

EF Core 5.0 не будет работать на платформах .NET Standard 2.0, включая .NET Framework.

Как скачать EF Core 5.0?

EF Core распространяется исключительно как набор пакетов NuGet. Например, чтобы добавить поставщика SQL Server в свой проект, вы можете использовать следующую команду с помощью инструмента dotnet:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 5.0.0-preview.2.20120.8

 

Пакеты EF Core, опубликованные сегодня:

Microsoft.EntityFrameworkCore - основной пакет EF Core

Microsoft.EntityFrameworkCore.SqlServer - поставщик базы данных для Microsoft SQL Server и SQL Azure

Microsoft.EntityFrameworkCore.Sqlite - поставщик базы данных для SQLite

Microsoft.EntityFrameworkCore.Cosmos - поставщик базы данных для Azure Cosmos DB

Microsoft.EntityFrameworkCore.InMemory - поставщик базы данных в памяти

Microsoft.EntityFrameworkCore.Tools - команды EF Core PowerShell для консоли диспетчера пакетов Visual Studio

Microsoft.EntityFrameworkCore.Design - общие компоненты времени разработки для инструментов EF Core

Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite - поддержка SQL Server для пространственных типов

Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite - поддержка SQLite для пространственных типов

Microsoft.EntityFrameworkCore.Proxies - загрузка и отслеживание изменений прокси

Microsoft.EntityFrameworkCore.Abstractions - разделенные EF Core абстракции

Microsoft.EntityFrameworkCore.Relational - общие компоненты EF Core для поставщиков реляционных баз данных

Microsoft.EntityFrameworkCore.Analyzers - анализаторы C # для EF Core

Microsoft.EntityFrameworkCore.Sqlite.Core - поставщик базы данных для SQLite без упакованного собственного двоичного файла

Мы также опубликовали версию 5.0 Preview 1 от  поставщика ADO.NET Microsoft.Data.Sqlite.Core.

Установка dotnet ef

Как и в случае EF Core 3.0 и 3.1, инструмент командной строки dotnet ef больше не включается в .NET Core SDK. Прежде чем вы сможете выполнить команды переноса EF Core или создания лесов, вам необходимо установить этот пакет как глобальный или локальный инструмент.

Чтобы установить инструмент предварительного просмотра глобально, сначала удалите любую существующую версию с помощью:

dotnet tool uninstall --global dotnet-ef

 

Затем установите с помощью:

dotnet tool install --global dotnet-ef --version 5.0.0-preview.2.20120.8

Эту новую версию dotnet ef можно использовать с проектами, в которых используются более старые версии среды выполнения EF Core.

Номера версий пакетов

В процессе сборки .NET 5 произошла ошибка, в результате которой пакеты EF preview 1 были ошибочно помечены как «5.0.0-preview.2.20120.8».

Это не должно иметь никакого функционального воздействия и не должно повлиять на Preview 2, который все еще запланирован на конец года.

Что нового в EF Core 5 Preview 1

Мы поддерживаем документацию новых функциях, представленных в каждом предварительном просмотре.

Некоторые из основных моментов из предварительного просмотра 1 вызываются ниже.

Простая регистрация

Эта опция функционально похожа на Database.Log в EF6. Таким образом, он предоставляет простой способ получения журналов из EF Core без необходимости настройки какого-либо внешнего каркаса ведения журналов.

EF Core заменяет Database.Log методом LogTo, вызываемым для DbContextOptionsBuilder в AddDbContext или OnConfiguring. Например:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(Console.WriteLine);

 

Существуют перегрузки для:

• Установите минимальный уровень журнала

Пример: .LogTo(Console.WriteLine, LogLevel.Information)

• Фильтр только для определенных событий

Пример: .LogTo(Console.WriteLine, new[] {CoreEventId.ContextInitialized, RelationalEventId.CommandExecuted})

• Фильтр для всех событий в определенных категориях:

Пример: .LogTo(Console.WriteLine, new[] {DbLoggerCategory.Database.Name}, LogLevel.Information)

• Используйте пользовательский фильтр по событию и уровню:

Пример: .LogTo(Console.WriteLine, (id, level) => id == RelationalEventId.CommandExecuting)

 

Формат вывода может быть минимально сконфигурирован (API постоянно меняется), но вывод по умолчанию выглядит примерно так:

warn: 12/5/2019 09:57:47.574 CoreEventId.SensitiveDataLoggingEnabledWarning[10400] (Microsoft.EntityFrameworkCore.Infrastructure)
      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data, this mode should only be enabled during development.
dbug: 12/5/2019 09:57:47.581 CoreEventId.ShadowPropertyCreated[10600] (Microsoft.EntityFrameworkCore.Model.Validation)
      The property 'BlogId' on entity type 'Post' was created in shadow state because there are no eligible CLR members with a matching name.
info: 12/5/2019 09:57:47.618 CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure)
      Entity Framework Core 5.0.0-dev initialized 'BloggingContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: SensitiveDataLoggingEnabled
dbug: 12/5/2019 09:57:47.644 CoreEventId.ValueGenerated[10808] (Microsoft.EntityFrameworkCore.ChangeTracking)
      'BloggingContext' generated temporary value '-2147482647' for the 'Id' property of new 'Blog' entity.
...

 

Простой способ получить сгенерированный SQL

В EF Core 5.0 представлен метод расширения ToQueryString, который будет возвращать SQL, который EF Core сгенерирует при выполнении запроса LINQ. Например, код:

var query = context.Set&lt;customer>().Where(c => c.City == city);
Console.WriteLine(query.ToQueryString())

приводит к таким выводам при использовании поставщика базы данных SQL Server:

DECLARE p0 nvarchar(4000) = N'London';
 
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
WHERE [c].[City] = @__city_0

 

Обратите внимание, что объявления для параметров правильного типа также включены в вывод. Это позволяет копировать / вставлять в SQL Server Management Studio или аналогичные инструменты, так что запрос может быть выполнен для отладки / анализа.

Используйте атрибут C #, чтобы указать, что у объекта нет ключа

Тип объекта теперь можно настроить как “не имеющий ключа”, используя новый KeylessAttribute. Например:

[Keyless]
public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public int Zip { get; set; }
}

 

Соединение или строка соединения могут быть изменены при инициализации DbContext

Теперь проще создать экземпляр DbContext без какого-либо соединения или строки соединения. Кроме того, соединение или строка соединения теперь могут быть изменены в экземпляре контекста. Это позволяет одному и тому же экземпляру контекста динамически подключаться к разным базам данных.

Прокси отслеживания изменений

EF Core теперь может генерировать прокси во время выполнения, которые автоматически реализуют INotifyPropertyChanging и  INotifyPropertyChanged. Затем они сообщают об изменениях значений свойств сущностей непосредственно в EF Core, избегая необходимости сканировать изменения. Однако прокси-серверы имеют свои собственные ограничения, поэтому они не для всех.

Расширенные представления отладки

Представления отладки - это простой способ взглянуть на внутренности EF Core при отладке проблем. Представление отладки для Модели было реализовано. Для EF Core 5.0 мы упростили представление модели и добавили новое представление отладки для отслеживаемых объектов в диспетчере состояний.

Модель отладки

Разверните свойство Model объекта DbContext в выбранном отладчике и раскройте свойство DebugView.


LongView - это вид модели, который у нас был в течение некоторого времени. ShortView является новым и не включает аннотации моделей, которые значительно облегчают чтение. Например, вот одна из наших тестовых моделей:

Model:

  EntityType: Chassis

    Properties:

      TeamId (int) Required PK FK AfterSave:Throw

      Name (string)

      Version (no field, byte[]) Shadow Concurrency BeforeSave:Ignore AfterSave:Ignore ValueGenerated.OnAddOrUpdate

    Navigations:

      Team (_team, Team) ToPrincipal Team Inverse: Chassis PropertyAccessMode.Field

    Keys:

      TeamId PK

    Foreign keys:

      Chassis {'TeamId'} -> Team {'Id'} Unique ToDependent: Chassis ToPrincipal: Team

  EntityType: Driver

    Properties:

      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd

      CarNumber (Nullable<int>)

      Championships (int) Required