<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Санкт-Петербургский центр ИТ, блог </title><link>http://www.spbdev.biz:80/blog/</link><description>Блог о SQL Server, ERP, CRM, базах данных и бизнесе</description><item><title>Роль привязок в Azure Functions</title><link>http://www.spbdev.biz:80/blog/Rol-privyazok-v-Azure-Functions</link><description>&lt;h4&gt;Что такое привязки?&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;В Azure Functions привязки ввода и вывода используются как способ подключения ресурсов к функциям, а данные из Привязок передаются как параметры.&lt;br /&gt;При выполнении функции, привязки для вывода - ресурсы, которые записываются в вывод функции.&amp;nbsp; Для дальнейшего использования нужно определить атрибут привязки для ввода к методу функции.&lt;/p&gt;
&lt;h4&gt;Как привязки работают в функциях библиотеки класса?&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;В функциях библиотеки класса привязки настраиваются с помощью декоратора методов и параметров функций, используя атрибуты&amp;nbsp; С#, например:&lt;/p&gt;
&lt;address&gt;[FunctionName(nameof("FunctionName"))]&lt;/address&gt;&lt;address&gt;public async Task Run([EventGridTrigger] EventGridEvent[] eventGridEvents,&lt;/address&gt;&lt;address&gt;[EventGrid(TopicEndpointUri = "TopicEndpoint", TopicKeySetting = "TopicKey")] IAsyncCollector&amp;lt;EventGridEvent&amp;gt; outputEvents,&lt;/address&gt;&lt;address&gt;ILogger logger)&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Function code&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;В коде выше есть функция, которая запускается сеткой событий и использует привязку ввода сетки событий для публикации событий. Входящее событие привязывается к массиву EventGridEvents, а выходящее публикуется в IAsyncCollector типов EventGridEvent. Тип параметра определяет тип данных для входных данных в эту функцию.&lt;/p&gt;
&lt;h4&gt;Чем привязки отличаются в изолированных функциях процесса?&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Как и функции библиотеки классов привязка определяется с помощью атрибута в параметрах, методах и возвращаемых типах.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Привязки в изолированном проекте .net отличаются тем, что не могут использовать классы привязки, такие как IAsyncCollector&amp;lt;T&amp;gt;. Также нельзя использовать типы, унаследованные от SDK, например DocumentClient. Вместо этого приходится полагаться на строки, массивы и POCO (Plain Old Class Objects).&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Проиллюстрируем это примером. Создана функция, которая получает HTTP POST-запрос и передает документ на хранение&amp;nbsp;&amp;nbsp; в Cosmos DB.&lt;/p&gt;
&lt;p&gt;Вот код функции:&lt;/p&gt;
&lt;address&gt;using System;&lt;/address&gt;&lt;address&gt;using System.IO;&lt;/address&gt;&lt;address&gt;using System.Net;&lt;/address&gt;&lt;address&gt;using System.Threading.Tasks;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.Functions.Worker;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.Functions.Worker.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.Logging;&lt;/address&gt;&lt;address&gt;using Newtonsoft.Json;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace IsolatedBindings&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static class InsertTodo&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Function("InsertTodo")]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [CosmosDBOutput("%DatabaseName%", "%ContainerName%", ConnectionStringSetting = "CosmosDBConnectionString")]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static async Task&amp;lt;object&amp;gt; Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FunctionContext executionContext)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpResponseData response;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var logger = executionContext.GetLogger("InsertTodo");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; logger.LogInformation("C# HTTP trigger function processed a request.");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var request = await new StreamReader(req.Body).ReadToEndAsync();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var todo = JsonConvert.DeserializeObject&amp;lt;TodoItem&amp;gt;(request);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; todo.Id = Guid.NewGuid().ToString();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return todo;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception ex)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; logger.LogError($"Exception thrown: {ex.Message}");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response = req.CreateResponse(HttpStatusCode.InternalServerError);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return response;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p&gt;Эта функция использует привязку для вывода Azure Cosmos DB. К методу функции, который определяет, как записывается POST-запрос в службе Cosmos DB, применяется атрибут привязки. Для того чтобы&amp;nbsp;использовать привязку CosmosDBOutput, необходимо установить следующий пакет:&lt;/p&gt;
&lt;address&gt;Microsoft.Azure.Functions.Worker.Extensions.CosmosDB&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;Поскольку функции, исполняемые в изолированному процессе, используют различные типы привязок важно использовать другой набор пакетов расширения привязки.&lt;/p&gt;
&lt;p&gt;С полным списком можно ознакомиться по ссылке:&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.nuget.org/packages?q=Microsoft.Azure.Functions.Worker.Extensions"&gt;https://www.nuget.org/packages?q=Microsoft.Azure.Functions.Worker.Extensions&lt;/a&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В функциях библиотек классов привязка была бы определена для вывода в атрибуте метода, где определили бы тип вывода и записали выводную функцию в это привязку таким образом.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В изолированных функциях значение, возвращаемое нашим методом - это значение, которое будет записано в привязку&amp;nbsp; Cosmos DB Output. Таким образом, в функции создается POST-запрос, содержащий элемент Todo, который необходимо записать&amp;nbsp; Cosmos DB и когда он будет возвращен из функции, то будет записан в Cosmos DB.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Проверим это! Используем Postman для создания следующего запроса:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="176" alt="" src="/blog/Media/Default/Users/SpbDevBlog/1-4.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p&gt;После запуска функции&amp;nbsp;должна быть получена локальная конечная точка для отправки POST-запроса, например так:&lt;/p&gt;
&lt;address&gt;http://localhost:7071/api/InsertTodo&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;При создании POST-запроса на эту конечную точку получаем следующий ответ:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="131" alt="" src="/blog/Media/Default/Users/SpbDevBlog/2-6.png" /&gt;&lt;/p&gt;
&lt;p&gt;Зайдем в учетную запись Cosmos DB и проверим, что документ был успешно записан в:&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="217" alt="" src="/blog/Media/Default/Users/SpbDevBlog/3-5.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;</description><pubDate>Thu, 30 Sep 2021 08:21:52 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Rol-privyazok-v-Azure-Functions</guid></item><item><title>Создание Serverless API с помощью Azure Cosmos DB</title><link>http://www.spbdev.biz:80/blog/Sozdanie-Serverless-API-s-pomoshchyu-Azure-Cosmos-DB</link><description>&lt;p style="text-align: justify;"&gt;Azure Cosmos DB - глобально распределенная, многомодельная служба базы данных NoSQL, используемая для создания&amp;nbsp; высокодоступных и масштабируемых приложений.&amp;nbsp; Cosmos DB поддерживает приложения, использующие данные модели документов через SQL API and MongoDB API.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp;Azure Cosmos DB реализует проводной протокол для Mongo DB, разрешающий использовать привычные драйверы и инструменты, но с возможностью размещения данных в Azure Cosmos DB.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Стало возможным менять приложения для использования Azure Cosmos DB&amp;nbsp; без внесения кардинальных изменений в базу исходного кода, пользоваться преимуществами Azure Cosmos DB, такими как распределение Turnkey и эластичная масштабируемость как в пропускной способности, так и в хранилище.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Настройка учетной записи с помощью MongoDB API&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Начнем с создания учетной записи Cosmos DB. Войдите в Azure&amp;nbsp; и нажмите " Create a resource". Найдите Azure Cosmos DB и нажмите "New".&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;На странице &amp;lsquo;Create Azure Cosmos DB Account&amp;rsquo; укажите следующую информацию:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;middot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Resource Group &amp;ndash; группы ресурсов в Azure, представляющие собой логическую коллекцию ресурсов.&amp;nbsp; Создайте новую или добавьте свою учетную запись в существующую.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;middot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Account Name&amp;nbsp; - уникальное в Azure имя учетной записи. API &amp;mdash; Azure Cosmos DB - многомодельная база данных, но при создании учетной записи в&amp;nbsp; Cosmos DB выбираем только один API на весь срок действия учетной записи.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;middot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Location&amp;nbsp; - то, где будет зарегистрирована учетная запись. В примере выбрана Восточная Австралия. Выбирайте удобный для себя.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;middot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Capacity Mode&amp;nbsp; - то, как будет обеспечиваться пропускная способность в учетной записи.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;middot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Account Type&amp;nbsp; - выберите производственную среду&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;middot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Version - версия протокола Mongo DB, который будет поддерживать учетная запись.&amp;nbsp;&amp;nbsp; Выбираем 3.6&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;middot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Availability Zones - отключите.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Нажмите&amp;nbsp; Review+Create, затем Create для создания учетной записи Cosmos DB.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;После настройки учетной записи появляется возможность создания базы данных и коллекции.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В учетной записи Cosmos DB зайдите в проводник данных и нажмите&amp;nbsp; &amp;lsquo;New Collection&amp;rsquo;. Введите &amp;lsquo;BookstoreDB&amp;rsquo;&amp;nbsp; в качестве имени базы данных и Books - как название коллекции.&amp;nbsp; Затем выберите ключ для разделения документов из коллекции по узлам.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Сегментирование в Mongo DB - метод распределения данных между несколькими машинами. Важно, этот сегмент поможет приложению масштабироваться как с точки зрения пропускной способности, так и с точки зрения хранения за счет горизонтального масштабирования.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Теперь созданы&amp;nbsp; база данных, коллекция и учетная запись. Но для настройки нужна еще строка подключения.&amp;nbsp; Нажмите Connection String&amp;nbsp; и скопируйте значение PRIMARY CONNECTION STRING.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;h3&gt;&lt;em&gt;Создание Function Application&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img width="580" height="373" alt="" src="/blog/Media/Default/Users/SpbDevBlog/1-3.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Выберите &amp;lsquo;&lt;strong&gt;Azure Functions&lt;/strong&gt;&amp;rsquo; в качестве шаблона для создания проекта (Убедитесь, что выбран язык C#).&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Назовем проект &amp;lsquo;&lt;strong&gt;CosmosBooksApi&lt;/strong&gt;&amp;rsquo;, сохраните проект в выбранном месте и нажмите создать.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Выберите Azure Functions v3 (.NET Core)&amp;nbsp; в качестве среды выполнения кода и создайте пустой проект без триггеров.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Перед началом создания функций важно установить пакет MongoDB.Driver.&amp;nbsp; Для это нажмите правой клавишей мыши на проект и выберите &amp;lsquo;&lt;strong&gt;Manage NuGet Packages&lt;/strong&gt;&amp;rsquo;. В разделе Browse введите MongoDB.Driver и установите последнюю стабильную версию.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;После установки создадим файл &lt;em&gt;Startup.cs&lt;/em&gt;, который создаст экземпляр нашего &lt;em&gt;MongoClient&lt;/em&gt;:&lt;/p&gt;
&lt;address&gt;using CosmosBooksApi;&lt;/address&gt;&lt;address&gt;using CosmosBooksApi.Services;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.Functions.Extensions.DependencyInjection;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.Configuration;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.DependencyInjection;&lt;/address&gt;&lt;address&gt;using MongoDB.Driver;&lt;/address&gt;&lt;address&gt;using System.IO;&lt;/address&gt;&lt;address&gt;using System.Security.Authentication;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;[assembly: FunctionsStartup(typeof(Startup))]&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Startup : FunctionsStartup&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;public override void Configure(IFunctionsHostBuilder builder)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var config = new ConfigurationBuilder()&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .SetBasePath(Directory.GetCurrentDirectory())&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .AddEnvironmentVariables()&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Build();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; builder.Services.AddSingleton&amp;lt;IConfiguration&amp;gt;(config);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl(config["ConnectionString"]));&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; settings.SslSettings = new SslSettings() { EnabledSslProtocols = SslProtocols.Tls12 };&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; builder.Services.AddSingleton((s) =&amp;gt; new MongoClient(settings));&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; builder.Services.AddTransient&amp;lt;IBookService, BookService&amp;gt;();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;Начиная со второй версии Azure Functions появилась поддержка для внедрения зависимостей, разрешающая создавать экземпляр MongoClient как Singleton. Таким образом можно совместно использовать MongoClient среди функций и избежать создания нового экземпляра для клиента каждый раз, когда хотим вызвать Функции.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Для регистрации наших сервисов добавим компоненты в экземпляр&amp;nbsp; IFunctionsHostBuilder, который передается&amp;nbsp; как метод настройки&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Для использования этого метода добавим атрибут&amp;nbsp; FunctionsStartup в сам класс загрузки.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Затем создадим новую конфигурацию типа&amp;nbsp; IConfiguration. Все, что нужно - это выбрать конфигурацию для Function application из файла local.settings.json Затем добавить сервис IConfiguration&amp;nbsp; как Singleton.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Теперь настроим MongoClient. Начинаем с настройки строки подключения путем передачи нашей&amp;nbsp; PRIMARY CONNECTION STRING в качестве объекта&amp;nbsp; MongoUrl() Сохраним это в нашем local.settings.json file.&lt;/p&gt;
&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "IsEncrypted": false,&lt;/address&gt;&lt;address&gt;&amp;nbsp; "Values": {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "AzureWebJobsStorage": "UseDevelopmentStorage=true",&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "FUNCTIONS_WORKER_RUNTIME": "dotnet",&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "ConnectionString": "&amp;lt;PRIMARY_CONNECTION_STRING&amp;gt;",&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "DatabaseName": "BookstoreDB",&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "CollectionName":&amp;nbsp; "Books"&lt;/address&gt;&lt;address&gt;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;Затем передаем ключ настройки в объект MongoUrl.Подключаем SSL, используя протокол Tls12 в SslSettings&amp;nbsp; для MongoClientSettings. Это требование Azure Cosmos DB для подключения к учетной записи API MongoDB.После настройки MongoClientSettings, передаем их в объект MongoClient, который настроен как Singleton Service.Теперь создаем базовый класс для представления нашей модели Book. Напишем следующее:&lt;/p&gt;
&lt;address&gt;using MongoDB.Bson;&lt;/address&gt;&lt;address&gt;using MongoDB.Bson.Serialization.Attributes;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi.Models&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Book&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [BsonId]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [BsonRepresentation(BsonType.ObjectId)]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Id { get; set; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[BsonElement("name")]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string BookName { get; set; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [BsonElement("price")]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public decimal Price { get; set; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [BsonElement("category")]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Category { get; set; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [BsonElement("author")]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Author { get; set; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;В этом классе есть свойства для Book id, имени, цены, категории, автора. ID отмечен BsonId как первичный ключ документа. Также аннотировали ID&amp;nbsp; [BsonRepresentation(BsonType.ObjectId)] для передачи &amp;nbsp;ID как строкового типа, а не ObjectId. &amp;nbsp;Mongo будет обрабатывать преобразование строки в объект.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;Остальные свойства аннотированы с помощью [BsonElement()]. Это определит как свойства будут выглядеть в коллекции.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;Создадим службу, которая обрабатывает логику, работающую с учетной записью Cosmos DB. Дадим интерфейсу название IBookService.cs.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;
&lt;address&gt;using CosmosBooksApi.Models;&lt;/address&gt;&lt;address&gt;using System.Collections.Generic;&lt;/address&gt;&lt;address&gt;using System.Threading.Tasks;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi.Services&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface IBookService&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Get all books from the Books collection&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Task&amp;lt;List&amp;lt;Book&amp;gt;&amp;gt; GetBooks();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Get a book by its id from the Books collection&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;param name="id"&amp;gt;&amp;lt;/param&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Task&amp;lt;Book&amp;gt; GetBook(string id);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Insert a book into the Books collection&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;param name="book"&amp;gt;&amp;lt;/param&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Task CreateBook(Book bookIn);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Updates an existing book in the Books collection&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;param name="id"&amp;gt;&amp;lt;/param&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;param name="book"&amp;gt;&amp;lt;/param&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Task UpdateBook(string id, Book bookIn);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Removes a book from the Books collection&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;param name="book"&amp;gt;&amp;lt;/param&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Task RemoveBook(Book bookIn);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;/// &amp;lt;summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Removes a book with the specified id from the Books collection&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;param name="id"&amp;gt;&amp;lt;/param&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Task RemoveBookById(string id);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p&gt;Это простой интерфейс CRUD, определяющий контракт,&amp;nbsp; который должен быть реализован сервисами.&amp;nbsp; Реализуем этот интерфейс:&lt;/p&gt;
&lt;address&gt;using CosmosBooksApi.Models;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.Configuration;&lt;/address&gt;&lt;address&gt;using MongoDB.Driver;&lt;/address&gt;&lt;address&gt;using System.Collections.Generic;&lt;/address&gt;&lt;address&gt;using System.Linq;&lt;/address&gt;&lt;address&gt;using System.Threading.Tasks;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi.Services&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class BookService : IBookService&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly MongoClient _mongoClient;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IMongoDatabase _database;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IMongoCollection&amp;lt;Book&amp;gt; _books;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public BookService(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MongoClient mongoClient,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IConfiguration configuration)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mongoClient = mongoClient;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _database = _mongoClient.GetDatabase(configuration["DatabaseName"]);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _books = _database.GetCollection&amp;lt;Book&amp;gt;(configuration["CollectionName"]);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task CreateBook(Book bookIn)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; await _books.InsertOneAsync(bookIn);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task&amp;lt;Book&amp;gt; GetBook(string id)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var book = await _books.FindAsync(book =&amp;gt; book.Id == id);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return book.FirstOrDefault();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task&amp;lt;List&amp;lt;Book&amp;gt;&amp;gt; GetBooks()&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var books = await _books.FindAsync(book =&amp;gt; true);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return books.ToList();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task RemoveBook(Book bookIn)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; await _books.DeleteOneAsync(book =&amp;gt; book.Id == bookIn.Id);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task RemoveBookById(string id)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;await _books.DeleteOneAsync(book =&amp;gt; book.Id == id);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task UpdateBook(string id, Book bookIn)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; await _books.ReplaceOneAsync(book =&amp;gt; book.Id == id, bookIn);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;Введем зависимости в MongoClient и IConfiguration, затем создадим базу данных и коллекцию для выполнения операций с ними.&amp;nbsp; Рассмотрим различные методы.InsertOneAsync&amp;nbsp; -&amp;nbsp; асинхронно вставляет документ в IMongoCollection. Передается документ, который хотим сохранить. В данном случае это объект Book. Также можем передать некоторые пользовательские параметры (InsertOneOptions) и CancellationToken.FindAsync - асинхронно находит документ, который соответствует фильтру.&amp;nbsp; Используется лямбда-выражение для поиска книги с тем же ID, который указан &amp;nbsp;в методе.&amp;nbsp; Linq используется для возврата соответствующей книги.DeleteOneAsync&amp;nbsp; - асинхронно удаляет документ, соответствующий &amp;nbsp;выражению.&amp;nbsp; Опять же, используется лямба-выражение для поиска книги, которую необходимо удалить. В этом методе возвращается только результат операции.ReplaceOneAsync - приводит к асинхронной замене документа.Итак, MongoClient&amp;nbsp;создан и есть базовая служба CRUD, которая используется для взаимодействия с учетной записью Cosmos DB. Перейдем к созданию функций.В качестве примера создадим следующие функции:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CreateBook&lt;/li&gt;
&lt;li&gt;DeleteBook&lt;/li&gt;
&lt;li&gt;GetAllBooks&lt;/li&gt;
&lt;li&gt;GetBookById&lt;/li&gt;
&lt;li&gt;UpdateBook&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для создания новой функции щелкните правой клавишей мыши по файлу нашего решения и выберите &amp;lsquo;Add New Azure Function&amp;rsquo;. Появляется всплывающее окно. Выбираем Http Trigger, далее Anonymous в качестве уровня авторизации функции.Начнем с функции &lt;em&gt;CreateBook&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;address&gt;using CosmosBooksApi.Models;&lt;/address&gt;&lt;address&gt;using CosmosBooksApi.Services;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Mvc;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs.Extensions.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.Logging;&lt;/address&gt;&lt;address&gt;using MongoDB.Bson;&lt;/address&gt;&lt;address&gt;using Newtonsoft.Json;&lt;/address&gt;&lt;address&gt;using System;&lt;/address&gt;&lt;address&gt;using System.IO;&lt;/address&gt;&lt;address&gt;using System.Threading.Tasks;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi.Functions&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class CreateBook&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly ILogger&amp;lt;CreateBook&amp;gt; _logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBookService _bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public CreateBook(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ILogger&amp;lt;CreateBook&amp;gt; logger,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBookService bookService)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger = logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _bookService = bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FunctionName(nameof(CreateBook))]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task&amp;lt;IActionResult&amp;gt; Run(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "Book")] HttpRequest req)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;IActionResult result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var incomingRequest = await new StreamReader(req.Body).ReadToEndAsync();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var bookRequest = JsonConvert.DeserializeObject&amp;lt;Book&amp;gt;(incomingRequest);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var book = new Book&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id = ObjectId.GenerateNewId().ToString(),&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BookName = bookRequest.BookName,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Price = bookRequest.Price,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Category = bookRequest.Category,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Author = bookRequest.Author&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; await _bookService.CreateBook(book);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status201Created);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception ex)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_logger.LogError($"Internal Server Error. Exception: {ex.Message}");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status500InternalServerError);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;Здесь вводим &lt;em&gt;IBookService&lt;/em&gt; и&amp;nbsp; &lt;em&gt;ILogger&lt;/em&gt; в&amp;nbsp; функцию. Вызываем эту функцию, отправляя запрос POST на &amp;lsquo;&lt;strong&gt;/Book&lt;/strong&gt;&amp;rsquo;. Берем входящий HttpRequest и выполняем десериализацию в объект Book. Затем вставляет книгу в коллекцию Books. Если все прошло успешно, то получим ответ 201 (Создан). Если нет, ответ 500.&lt;/p&gt;
&lt;p&gt;Теперь рассмотрим функцию &lt;em&gt;DeleteBook&lt;/em&gt;:&lt;/p&gt;
&lt;address&gt;using CosmosBooksApi.Services;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Mvc;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs.Extensions.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.Logging;&lt;/address&gt;&lt;address&gt;using System;&lt;/address&gt;&lt;address&gt;using System.Threading.Tasks;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi.Functions&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class DeleteBook&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly ILogger&amp;lt;DeleteBook&amp;gt; _logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;private readonly IBookService _bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DeleteBook(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ILogger&amp;lt;DeleteBook&amp;gt; logger,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBookService bookService)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger = logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _bookService = bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FunctionName(nameof(DeleteBook))]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task&amp;lt;IActionResult&amp;gt; Run(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "Book/{id}")] HttpRequest req,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string id)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IActionResult result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var bookToDelete = await _bookService.GetBook(id);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (bookToDelete == null)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger.LogWarning($"Book with id: {id} doesn't exist.");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status404NotFound);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;await _bookService.RemoveBook(bookToDelete);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status204NoContent);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception ex)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger.LogError($"Internal Server Error. Exception thrown: {ex.Message}");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status500InternalServerError);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p&gt;На этот раз передаем ID в нашу функцию (&amp;lsquo;&lt;strong&gt;/Book/id&lt;/strong&gt;&amp;rsquo;) для поиска книга, которую необходимо удалить из коллекции.&amp;nbsp; Сначала ищем книгу, используя метод &lt;em&gt;IBookService&lt;/em&gt;.&lt;em&gt;.GetBook(id)&lt;/em&gt;.&amp;nbsp; Если книга не существует, функция выдаст ответ 404 (не найдена).&lt;/p&gt;
&lt;p&gt;Если книга найдена, передаем ее в метод &lt;em&gt;RemoveBook(book)&lt;/em&gt; для удаления из коллекции в Cosmos DB. В случае успешного выполнения - ответ 204.&lt;/p&gt;
&lt;p&gt;Код для функции &lt;em&gt;GetAllBooks&lt;/em&gt;:&lt;/p&gt;
&lt;address&gt;using CosmosBooksApi.Services;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Mvc;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs.Extensions.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.Logging;&lt;/address&gt;&lt;address&gt;using System;&lt;/address&gt;&lt;address&gt;using System.Threading.Tasks;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi.Functions&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class GetAllBooks&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly ILogger&amp;lt;GetAllBooks&amp;gt; _logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBookService _bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public GetAllBooks(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ILogger&amp;lt;GetAllBooks&amp;gt; logger,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBookService bookService)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger = logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _bookService = bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FunctionName(nameof(GetAllBooks))]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task&amp;lt;IActionResult&amp;gt; Run(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "Books")] HttpRequest req)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IActionResult result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var books = await _bookService.GetBooks();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (books == null)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger.LogWarning("No books found!");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status404NotFound);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new OkObjectResult(books);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception ex)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger.LogError($"Internal Server Error. Exception thrown: {ex.Message}");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = new StatusCodeResult(StatusCodes.Status500InternalServerError);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p&gt;В этой функции передается запрос GET на&amp;nbsp; &amp;lsquo;&lt;strong&gt;/Books&lt;/strong&gt;&amp;rsquo;.&amp;nbsp; Эта функция вызовет метод &lt;em&gt;.GetBooks()&lt;/em&gt; в &lt;em&gt;IBookService&lt;/em&gt; для извлечения всех книг из коллекции. Если книг нет - ответ 404. Если книги есть, функция вернет их пользователю в виде массива.&lt;/p&gt;
&lt;p&gt;Функция &lt;em&gt;GetBookById&lt;/em&gt;&amp;nbsp; схожа с &lt;em&gt;GetAllBooks&lt;/em&gt; , но на этот раз передается ID книги, которую нужно вернуть:&lt;/p&gt;
&lt;address&gt;using CosmosBooksApi.Services;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Mvc;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs.Extensions.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.Logging;&lt;/address&gt;&lt;address&gt;using System;&lt;/address&gt;&lt;address&gt;using System.Threading.Tasks;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi.Functions&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class GetBookById&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly ILogger&amp;lt;GetBookById&amp;gt; _logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBookService _bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public GetBookById(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ILogger&amp;lt;GetBookById&amp;gt; logger,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBookService bookService)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger = logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _bookService = bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FunctionName(nameof(GetBookById))]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task&amp;lt;IActionResult&amp;gt; Run(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "Book/{id}")] HttpRequest req,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string id)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IActionResult result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var book = await _bookService.GetBook(id);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (book == null)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger.LogWarning($"Book with id: {id} doesn't exist.");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status404NotFound);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new OkObjectResult(book);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception ex)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger.LogError($"Internal Server Error. Exception thrown: {ex.Message}");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status500InternalServerError);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;Также передается ID на функцию &lt;em&gt;UpdateBook&lt;/em&gt;. Сначала вызываем метод&lt;em&gt;. GetBook(id)&lt;/em&gt; для поиска книги, которую хотим обновить.&amp;nbsp; После нахождения книги читаем входящий запрос и десериализируем его в объект Book. Затем используем десериализованный запрос для обновления объекта Book и передаем этот объект в метод &lt;em&gt;.UpdateBook()&lt;/em&gt;&amp;nbsp; вместе с ID, который использовали для вызова функции.&lt;/p&gt;
&lt;address&gt;using CosmosBooksApi.Models;&lt;/address&gt;&lt;address&gt;using CosmosBooksApi.Services;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.AspNetCore.Mvc;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs;&lt;/address&gt;&lt;address&gt;using Microsoft.Azure.WebJobs.Extensions.Http;&lt;/address&gt;&lt;address&gt;using Microsoft.Extensions.Logging;&lt;/address&gt;&lt;address&gt;using Newtonsoft.Json;&lt;/address&gt;&lt;address&gt;using System;&lt;/address&gt;&lt;address&gt;using System.IO;&lt;/address&gt;&lt;address&gt;using System.Threading.Tasks;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;namespace CosmosBooksApi.Functions&lt;/address&gt;&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class UpdateBook&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly ILogger&amp;lt;UpdateBook&amp;gt; _logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBookService _bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public UpdateBook(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ILogger&amp;lt;UpdateBook&amp;gt; logger,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBookService bookService)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger = logger;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _bookService = bookService;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FunctionName(nameof(UpdateBook))]&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public async Task&amp;lt;IActionResult&amp;gt; Run(&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "Book/{id}")] HttpRequest req,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string id)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IActionResult result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var bookToUpdate = await _bookService.GetBook(id);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (bookToUpdate == null)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger.LogWarning($"Book with id: {id} doesn't exist.");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status404NotFound);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var input = await new StreamReader(req.Body).ReadToEndAsync();&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var updateBookRequest = JsonConvert.DeserializeObject&amp;lt;Book&amp;gt;(input);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Book updatedBook = new Book&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id = id,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BookName = updateBookRequest.BookName,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Author = updateBookRequest.Author,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Category = bookToUpdate.Category,&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Price = updateBookRequest.Price&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; await _bookService.UpdateBook(id, updatedBook);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status202Accepted);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception ex)&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _logger.LogError($"Internal Server Error: {ex.Message}");&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new StatusCodeResult(StatusCodes.Status500InternalServerError);&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;h3&gt;Проверка функции&lt;/h3&gt;
&lt;p&gt;После завершения кодирования функций следующие этапы - развертывание и тестирование.&amp;nbsp; Нажмите F5 для локального запуска функции. Через пару секунд функции будут развернуты и появятся endpoints для функций.&lt;/p&gt;
&lt;p&gt;Функции выполняются в локальном хосте.&amp;nbsp; Используем Postman для тестирования endpoints.&lt;/p&gt;
&lt;p&gt;Начнем с функции CreateBook. Скопируйте и вставьте крайнюю точку функции в Postman. Установите метод запроса POST и щелкните вкладку. Необходимо отправить запрос в качестве JSON payload, поэтому установите для него JSON и добавьте следующее:&lt;/p&gt;
&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp; "BookName" : "Computer Science: Distilled",&lt;/address&gt;&lt;address&gt;&amp;nbsp; "Price": 11.99,&lt;/address&gt;&lt;address&gt;&amp;nbsp; "Category": "Technology",&lt;/address&gt;&lt;address&gt;&amp;nbsp; "Author": "Wladston Ferreira Filho"&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;Нажмите Send для отправки запроса. Получен ответ (201).&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Чтобы убедиться, что документ добавлен в учетную запись, можно просмотреть документ в учетной записи Cosmos DB.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Вставьте еще пару книг прежде, чем двигаться дальше.&amp;nbsp; Теперь попытаемся извлечь все книги из нашей коллекции, используя функцию GetAllBooks. Удалите JSON payload из тела и измените метод запроса на GET. Нажмите Send для создания запроса.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Должен быть получен подобный ответ:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="295" alt="" src="/blog/Media/Default/Users/SpbDevBlog/4-3.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Здесь книги коллекции, возвращенные в качестве массива JSON.&amp;nbsp; Теперь протестируем функцию &lt;em&gt;GetBookById&lt;/em&gt;. В ответ на функцию GetAllBooks, возьмите ID и добавьте его в качестве параметра в маршрут обработки запроса. Все, что здесь изменилось это то, что нужно найти конкретную книгу, используя ее ID.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="168" alt="" src="/blog/Media/Default/Users/SpbDevBlog/5-3.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Нажмите Send для создания запроса. У нас должен быть объект книга, возвращенный к нам:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="149" alt="" src="/blog/Media/Default/Users/SpbDevBlog/6-3.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Теперь удалим книгу из коллекции Cosmos DB. Измените метод запроса на DELETE в Postman и нажмите Send.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="157" alt="" src="/blog/Media/Default/Users/7.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Должен быть получен следующий ответ:&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="71" alt="" src="/blog/Media/Default/Users/SpbDevBlog/8-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Если проверить коллекцию в Azure Cosmos DB, увидим, что книги здесь больше нет.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="196" alt="" src="/blog/Media/Default/Users/SpbDevBlog/10-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Наконец, попробуем обновить книгу.&amp;nbsp; Возьмем следующую книгу из коллекции:&lt;/p&gt;
&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp; "id": "603ae1b621786dd7fd92d5c0",&lt;/address&gt;&lt;address&gt;&amp;nbsp; "bookName": "The Dark Net",&lt;/address&gt;&lt;address&gt;&amp;nbsp; "price": 18.99,&lt;/address&gt;&lt;address&gt;&amp;nbsp; "category": "Technology",&lt;/address&gt;&lt;address&gt;&amp;nbsp; "author": "Jamie Bartlett"&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p style="text-align: justify;"&gt;Возьмем ID и используем его в качестве параметра в функции&amp;nbsp; &lt;em&gt;UpdateBook&lt;/em&gt;. Изменим метод на запрос PUT и добавим следующее в запрос:&lt;/p&gt;
&lt;address&gt;{&lt;/address&gt;&lt;address&gt;&amp;nbsp; "bookName": "The Dark Net v2",&lt;/address&gt;&lt;address&gt;&amp;nbsp; "price": 11.99,&lt;/address&gt;&lt;address&gt;&amp;nbsp; "author": "Jamie Bartlett"&lt;/address&gt;&lt;address&gt;}&lt;/address&gt;&lt;address&gt;&lt;/address&gt;
&lt;p&gt;Эта текстовая часть отправляется как JSON payload. Нажимаем Send для обновления документа книга.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="160" alt="" src="/blog/Media/Default/Users/SpbDevBlog/11-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Получаем следующий ответ.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="67" alt="" src="/blog/Media/Default/Users/SpbDevBlog/12-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Проверим успешность обновления документа в учетной записи Cosmos DB.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="237" alt="" src="/blog/Media/Default/Users/SpbDevBlog/13-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;На этом примере удалось увидеть, что даже если приложения созданы с использованием MongoDb, Вы можете легко изменить его на Azure Cosmos DB, не внося серьезных изменений в базу исходного кода.&lt;/p&gt;
&lt;address&gt;&lt;/address&gt;&lt;address&gt;&lt;/address&gt;</description><pubDate>Fri, 24 Sep 2021 09:12:02 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Sozdanie-Serverless-API-s-pomoshchyu-Azure-Cosmos-DB</guid></item><item><title>Миграция базы данных с сервера Microsoft SQL Server on-premises в Azure SQL database</title><link>http://www.spbdev.biz:80/blog/Migratsiya-bazy-dannykh-s-servera-Microsoft-SQL-Server-on-premises-v-Azure-SQL-database</link><description>&lt;h3&gt;&lt;span&gt;Введение&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;В данном руководстве описан процесс миграции базы данных с сервера Microsoft SQL Server on-premises в Azure SQL database посредством экспорта Data-tier Application и последующего импорта базы Azure SQL database из bacpac-файла.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Перед началом процесса миграции следует обеспечить выполнение следующих условий:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Логин на сервере &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises,&lt;/span&gt; с которого нужно перенести базу (под которым предполагается выполнять этот перенос) должен входить в роль сервера &lt;span&gt;sysadmin&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Должны быть созданы учётная запись и подписка в &lt;span&gt;Azure&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;Сам процесс миграции состоит из следующих шагов:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Создание &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt; и блоб-контейнера в нём в &lt;span&gt;Azure&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Экспорт &lt;span&gt;bacpac&lt;/span&gt;-файла базы данных с сервера &lt;span&gt;Microsoft&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt; &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises&lt;/span&gt; в блоб-контейнер.&lt;/li&gt;
&lt;li&gt;Создание инстанса &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt; в &lt;span&gt;Azure&lt;/span&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Импорт базы данных из bacpac-файла, сохраненного в блоб-контейнере в инстанс SQL Server в Azure&lt;/p&gt;
&lt;h3&gt;Создание storage account и блоб-контейнера в нём в Azure&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Открываем в браузере &lt;span&gt;&lt;a href="https://portal.azure.com"&gt;portal.azure.com&lt;/a&gt;&lt;/span&gt; и после входа в свою учётную запись на домашней странице нажимаем &amp;ldquo;&lt;span&gt;Create&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;resource&lt;/span&gt;&amp;rdquo;. &lt;img width="580" height="112" alt="" src="/blog/Media/Default/Users/SpbDevBlog/1-2.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;На открывшейся странице нажимаем &amp;ldquo;&lt;span&gt;Storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;&amp;rdquo;. &lt;img width="529" height="804" alt="" src="/blog/Media/Default/Users/SpbDevBlog/2-2.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;На открывшейся странице &amp;ldquo;&lt;span&gt;Create&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;&amp;rdquo; указываем следующие значения:
&lt;table width="816" height="432"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;Поле&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;Значение&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Subscription&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Подписка, в которой создаётся &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Resource group&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Существующая или новая группа в зависимости от предпочтений.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Storage account name&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Имя создаваемого &lt;span&gt;storage&lt;/span&gt; аккаунта. Должно быть уникальным среди всех &lt;span&gt;storage&lt;/span&gt; аккаунтов в &lt;span&gt;Azure&lt;/span&gt;, от 3 до 24 символов, только строчные буквы и цифры. &lt;span&gt;На скриншоте ниже - frdsstorageacc.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Region&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Регион в котором будет создан &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;. Рекомендуется использовать тот же регион, в котором будет создан &lt;span&gt;Azure&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;server&lt;/span&gt;.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Performance&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;span&gt;Standard&lt;/span&gt; или &lt;span&gt;Premium&lt;/span&gt; (что по сути означает &lt;span&gt;HDD&lt;/span&gt; или &lt;span&gt;SSD&lt;/span&gt; для создаваемого &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;) в зависимости от потребностей и бюджета. На скриншоте выбрано значение по умолчанию &lt;span&gt;Standard.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Redundancy&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Куда будет реплицироваться &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;, для обеспечения &lt;span&gt;high&lt;/span&gt; &lt;span&gt;availability&lt;/span&gt;. Выбирается опция в зависимости от потребностей и бюджета. На скриншоте выбрано значение по умолчанию &lt;span&gt;Geo-redundant storage (GRS).&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Make read access to data available in the event of regional unavailability.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;span&gt;Оставляем значение по умолчанию.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;img width="580" height="701" alt="" src="/blog/Media/Default/Users/SpbDevBlog/3-2.jpg" /&gt; &lt;/li&gt;
&lt;li&gt;Нажимаем &amp;ldquo;&lt;span&gt;Review&lt;/span&gt; + &lt;span&gt;create&lt;/span&gt;&amp;rdquo; и после валидации всех настроек ещё раз &amp;ldquo;&lt;span&gt;Create&lt;/span&gt;&amp;rdquo;. &lt;span&gt;Создание storage account может занять несколько минут. &lt;img width="580" height="194" alt="" src="/blog/Media/Default/Users/SpbDevBlog/4-2.jpg" /&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;После завершения создания нажимаем&amp;ldquo;&lt;span&gt;Go&lt;/span&gt; &lt;span&gt;to&lt;/span&gt; &lt;span&gt;resource&lt;/span&gt;&amp;rdquo;. &lt;img width="580" height="360" alt="" src="/blog/Media/Default/Users/SpbDevBlog/5-2.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;В левой части страницы созданного &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt; нажимаем &amp;ldquo;&lt;span&gt;Containers&lt;/span&gt;&amp;rdquo;. &lt;img width="414" height="603" alt="" src="/blog/Media/Default/Users/SpbDevBlog/6-2.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;На открывшейся странице нажимаем &amp;ldquo;+ &lt;span&gt;Container&lt;/span&gt;&amp;rdquo;. &lt;img width="580" height="333" alt="" src="/blog/Media/Default/Users/SpbDevBlog/7.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Указываем желаемое имя контейнера, остальные настройки оставляем по умолчанию.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img width="299" height="277" alt="" src="/blog/Media/Default/Users/SpbDevBlog/8.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;9. Нажимаем &amp;ldquo;&lt;span&gt;Create&lt;/span&gt;&amp;rdquo; - контейнер будет создан и отображён на странице аккаунта.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="325" alt="" src="/blog/Media/Default/Users/SpbDevBlog/9.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;На этом процесс создания &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt; и настройки контейнера можно считать завершенным.&lt;/p&gt;
&lt;h3&gt;Экспорт &lt;span&gt;bacpac&lt;/span&gt;-файла базы данных с сервера &lt;span&gt;Microsoft&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt; &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises&lt;/span&gt; в блоб-контейнер&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Открываем &lt;span&gt;SSMS&lt;/span&gt; и подключаемся к &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt;, на котором находится база для переноса.&lt;/li&gt;
&lt;li&gt;Нажимаем на базу правой кнопкой мыши и в появившемся контекстном меню выбираем Tasks -&amp;gt; Export Data-tier. &lt;img width="580" height="518" alt="" src="/blog/Media/Default/Users/SpbDevBlog/10.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;В появившемся окне &lt;span&gt;Introduction&lt;/span&gt; нажимаем &amp;ldquo;&lt;span&gt;Next&lt;/span&gt;&amp;rdquo;. &lt;img width="580" height="529" alt="" src="/blog/Media/Default/Users/SpbDevBlog/11.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;На вкладке Export Settings выбираем &amp;ldquo;Save to Microsoft Azure&amp;rdquo; и нажимаем кнопку &amp;ldquo;Connect...&amp;rdquo; для подключения к storage account. &lt;img width="580" height="527" alt="" src="/blog/Media/Default/Users/SpbDevBlog/12.jpg" /&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;В появившейся форме для аутентификации в &lt;span&gt;Azure&lt;/span&gt; вводим данные своей учётной записи.&lt;/li&gt;
&lt;li&gt;После аутентификации в появившемся окне выбираем подписку, &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt; и блоб контейнер, куда будет сохранён &lt;span&gt;bacpac&lt;/span&gt;-файл и нажимаем &amp;ldquo;ОК&amp;rdquo;.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img width="580" height="406" alt="" src="/blog/Media/Default/Users/SpbDevBlog/13.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;7. Убеждаемся, что в окне &lt;span&gt;Export&lt;/span&gt; &lt;span&gt;Settings&lt;/span&gt; указаны правильные значения и нажимаем &lt;span&gt;Next&lt;/span&gt;, а затем &lt;span&gt;Finish&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="528" alt="" src="/blog/Media/Default/Users/SpbDevBlog/14.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;8. Процесс экспорта отображается в окне &amp;ldquo;&lt;span&gt;Progress&lt;/span&gt;&amp;rdquo;. &lt;img width="580" height="527" alt="" src="/blog/Media/Default/Users/SpbDevBlog/15.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; 9.&amp;nbsp;После завершения экспорта закрываем окно. Можно открыть контейнер на портале Azure и убедиться, что bacpac-файл был успешно&amp;nbsp;&lt;/p&gt;
&lt;p&gt;скопирован.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &lt;img width="580" height="140" alt="" src="/blog/Media/Default/Users/SpbDevBlog/31.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;На этом экспорт &lt;span&gt;bacpac&lt;/span&gt;-файла в блоб контейнер можно считать завершённым.&lt;/p&gt;
&lt;h3&gt;Создание инстанса &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt; в &lt;span&gt;Azure&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Открываем в браузере &lt;span&gt;&lt;a href="https://portal.azure.com"&gt;portal.azure.com&lt;/a&gt;&lt;/span&gt;, переходим на домашнюю &lt;span&gt;страницу и нажимаем &amp;ldquo;Create a resource&amp;rdquo;.&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;img width="580" height="112" alt="" src="/blog/Media/Default/Users/SpbDevBlog/16.jpg" /&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;В строке поиска набираем &amp;ldquo;&lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt;&amp;rdquo; и нажимаем ввод.&amp;nbsp;&amp;nbsp; &lt;img width="580" height="279" alt="" src="/blog/Media/Default/Users/SpbDevBlog/17.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;В результатах поиска находим ресурс &amp;ldquo;&lt;span&gt;Azure&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt;&amp;rdquo; и нажимаем на него.&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;img width="580" height="634" alt="" src="/blog/Media/Default/Users/SpbDevBlog/18.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;На открывшейся странице нажимаем &amp;ldquo;&lt;span&gt;Create&lt;/span&gt;&amp;rdquo;.&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img width="471" height="378" alt="" src="/blog/Media/Default/Users/SpbDevBlog/19.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 5.&amp;nbsp;На открывшейся странице в разделе &amp;ldquo;How do you plan to use the service?&amp;rdquo; доступно три опции - &amp;ldquo;SQL databases&amp;rdquo;, &amp;ldquo;SQL managed instances&amp;rdquo; и &amp;ldquo;SQL virtual machines&amp;rdquo;. В данном руководстве рассмотрен процесс создания SQL databases. Нажав на &amp;ldquo;Show details&amp;rdquo; на панели &amp;ldquo;SQL databases&amp;rdquo;, можно увидеть описание различных типов ресурсов для этой опции - &amp;ldquo;Single database&amp;rdquo;, &amp;ldquo;Elastic pool&amp;rdquo; и &amp;ldquo;Database server&amp;rdquo;. Выбор типа ресурса зависит от потребностей, для данного примера выбираем &amp;ldquo;Database server&amp;rdquo; и нажимаем &amp;ldquo;Create&lt;span&gt;&amp;rdquo;.&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="307" alt="" src="/blog/Media/Default/Users/SpbDevBlog/20.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 6. На открывшейся странице указываем следующие значения&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;Поле&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;Значение&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Subscription&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Подписка, в которой создаётся сервер.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Resource group&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Существующая или новая группа в зависимости от предпочтений.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Server name&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Имя создаваемого сервера. Должно быть уникальным среди всех серверов в &lt;span&gt;Azure&lt;/span&gt;, не должно быть зарезервированным словом. Должно содержать только строчные буквы, цифры и &amp;ldquo;-&amp;rdquo;, но не может начинаться с &amp;ldquo;-&amp;rdquo;. &lt;span&gt;Длина - не более 63 символов. На скриншоте ниже - forrardssql.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Region&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Регион в котором будет создан сервер.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Server admin login&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;span&gt;Логин для админа.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Password&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;span&gt;Пароль для админского логина.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Confirm password&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;span&gt;Ещё раз пароль.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img width="580" height="739" alt="" src="/blog/Media/Default/Users/SpbDevBlog/21.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; 7. Нажимаем &amp;ldquo;&lt;span&gt;Review&lt;/span&gt; + &lt;span&gt;create&lt;/span&gt;&amp;rdquo;, а затем ещё раз &amp;ldquo;&lt;span&gt;Create&lt;/span&gt;&amp;rdquo;. Создание сервера может занять несколько минут.&lt;/p&gt;
&lt;p&gt;На этом создание инстанса &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt; в &lt;span&gt;Azure&lt;/span&gt; можно считать завершённым.&lt;/p&gt;
&lt;h3&gt;Импорт базы данных из &lt;span&gt;bacpac&lt;/span&gt;-файла, сохраненного в блоб-контейнере, в инстанс &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt; в &lt;span&gt;Azure&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;1.&amp;nbsp;&lt;/span&gt;После завершения создания инстанса &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt; в &lt;span&gt;Azure&lt;/span&gt;, на открывшейся странице нажимаем &amp;ldquo;&lt;span&gt;Go&lt;/span&gt; &lt;span&gt;to&lt;/span&gt; &lt;span&gt;resource&lt;/span&gt;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="228" alt="" src="/blog/Media/Default/Users/SpbDevBlog/22.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;2. На открывшейся странице нажимаем &amp;ldquo;&lt;span&gt;Import&lt;/span&gt; &lt;span&gt;database&lt;/span&gt;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="195" alt="" src="/blog/Media/Default/Users/SpbDevBlog/23.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;3. На открывшейся странице нужно указать параметры импортируемой базы данных. &lt;span&gt;Для выбора bacpac-файла, созданного ранее, нажимаем &amp;ldquo;Select backup&amp;rdquo;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="324" height="651" alt="" src="/blog/Media/Default/Users/SpbDevBlog/24.jpg" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;4.&amp;nbsp;&lt;/span&gt;Далее нужно выбрать &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt; и блоб-контейнер в нём, куда был экспортирован &lt;span&gt;bacpac&lt;/span&gt;-файл, а затем выбрать этот файл и нажать &amp;ldquo;&lt;span&gt;Select&lt;/span&gt;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img width="458" height="939" alt="" src="/blog/Media/Default/Users/SpbDevBlog/25.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; 5. Выбранный файл отобразится в окне настройки параметров импорта. Следующим шагом нужно выбрать ресурсы, используемые базой данных. &lt;span&gt;Для этого нажимаем &amp;ldquo;Configure database&amp;rdquo;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="375" height="662" alt="" src="/blog/Media/Default/Users/SpbDevBlog/26.jpg" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 6.&amp;nbsp;&lt;/span&gt;Ресурсы выбираются в зависимости от планируемой нагрузки и бюджета, для данного примера была выбрана минимальная конфигурация. &lt;span&gt;После выбора конфигурации нажимаем &amp;ldquo;Apply&amp;rdquo;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="580" height="132" alt="" src="/blog/Media/Default/Users/SpbDevBlog/27.jpg" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 7.&amp;nbsp;&lt;/span&gt;Выбранная конфигурация отобразится в окне настройки параметров импорта.&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="346" height="643" alt="" src="/blog/Media/Default/Users/SpbDevBlog/28.jpg" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 8.&amp;nbsp;&lt;/span&gt;Последним шагом указываем название базы данных, &lt;span&gt;collation&lt;/span&gt;, а также логин и пароль для входа на сервер (те значения, которые были заданы на этапе создания сервера). После указания всех параметров нажимаем &amp;ldquo;ОК&amp;rdquo;. Импорт базы данных займёт какое-то время в зависимости от количества данных. Следует иметь в виду, что панель с уведомлениями, отображающая прогресс импорта базы через какое-то время может зависнуть и показывать, что импорт продолжается тогда, когда по факту он уже завершился. Для большей надёжности следует проверять состояние базы, открыв её в &amp;ldquo;&lt;span&gt;All&lt;/span&gt; &lt;span&gt;resources&lt;/span&gt;&amp;rdquo;.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="547" height="257" alt="" src="/blog/Media/Default/Users/SpbDevBlog/29.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="224" alt="" src="/blog/Media/Default/Users/SpbDevBlog/30.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;На этом процесс миграции базы данных с сервера Microsoft SQL Server on-premises в Azure SQL database можно считать завершённым.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Полезные ссылки&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;Quickstart: Import a BACPAC file to a database in Azure SQL Database or Azure SQL Managed Instance&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/azure-sql/database/database-import?tabs=azure-powershell"&gt;https://docs.microsoft.com/en-us/azure/azure-sql/database/database-import?tabs=azure-powershell&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;</description><pubDate>Mon, 05 Jul 2021 08:28:10 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Migratsiya-bazy-dannykh-s-servera-Microsoft-SQL-Server-on-premises-v-Azure-SQL-database</guid></item><item><title>Миграция базы данных с сервера Microsoft SQL Server on-premises в Azure SQL managed instance посредством backup/restore</title><link>http://www.spbdev.biz:80/blog/Migratsiya-bazy-dannykh-s-servera-Microsoft-SQL-Server-on-premises-v-Azure-SQL-managedinstance-posredstvom-backup-restore</link><description>&lt;p style="text-align: justify;"&gt;&lt;span&gt;В данном руководстве описан процесс миграции базы данных с сервера Microsoft SQL Server on-premises в Azure SQL managed instance.&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Перед началом процесса миграции следует обеспечить выполнение следующих необходимых условий:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Логин на сервере &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises&lt;/span&gt;, с которого нужно перенести базу (под которым предполагается выполнять этот перенос) должен входить в роль сервера &lt;span&gt;sysadmin&lt;/span&gt;.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Должна быть создана подписка в &lt;span&gt;Azure&lt;/span&gt;.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Должен быть создан ресурс &lt;span&gt;Azure&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;managed&lt;/span&gt; &lt;span&gt;instance&lt;/span&gt; в &lt;span&gt;Azure&lt;/span&gt;.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В &lt;span&gt;Azure&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;managed&lt;/span&gt; &lt;span&gt;instance&lt;/span&gt; также должен быть создан логин, входящий в роль сервера &lt;span&gt;sysadmin&lt;/span&gt;.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Сам процесс миграции состоит из следующих шагов:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;- Создание в &lt;span&gt;Azure&lt;/span&gt; ресурса &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;, в котором будет размещён бэкап базы данных.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;- Бэкап базы данных с сервера &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises&lt;/span&gt; в &lt;span&gt;blob&lt;/span&gt; контейнер в &lt;span&gt;Azure&lt;/span&gt; &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;span&gt;- Рестор базы данных из blob контейнера в Azure storage account в Azure SQL managed instance.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Создание в &lt;span&gt;Azure&lt;/span&gt; ресурса &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;, в котором будет размещён бэкап базы данных&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Открывает в браузере &lt;span&gt;portal&lt;/span&gt;.&lt;span&gt;azure&lt;/span&gt;.&lt;span&gt;com&lt;/span&gt; и входим в свою учётную запись.&lt;/li&gt;
&lt;li&gt;Нажимаем кнопку &amp;ldquo;&lt;span&gt;Create&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;resource&lt;/span&gt;&amp;rdquo; в верхней части страницы портала.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 style="padding-left: 30px;"&gt;&lt;span&gt; &lt;img width="580" height="121" alt="" src="/blog/Media/Default/Users/SpbDevBlog/1-3.png" /&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 style="padding-left: 30px;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style="padding-left: 30px;"&gt;3. В открывшейся странице выбираем &amp;ldquo;Storage account&amp;rdquo;.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;img width="580" height="847" alt="" src="/blog/Media/Default/Users/SpbDevBlog/2-4.png" /&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;4. На открывшейся странице &amp;ldquo;&lt;span&gt;Create&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;&amp;rdquo; указываем следующие значения.&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;Поле&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;Значение&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Subscription&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Подписка, в которой создаётся &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Resource group&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Существующая или новая группа в зависимости от предпочтений.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Storage account name&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Имя создаваемого &lt;span&gt;storage&lt;/span&gt; аккаунта. Должно быть уникальным среди всех &lt;span&gt;storage&lt;/span&gt; аккаунтов в &lt;span&gt;Azure&lt;/span&gt;, от 3 до 24 символов, только строчные буквы и цифры. &lt;span&gt;На скриншоте ниже - frdsstorageacc.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Region&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Регион в котором будет создан &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;. Рекомендуется использовать тот же регион, в котором создан &lt;span&gt;Azure&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;managed&lt;/span&gt; &lt;span&gt;instance&lt;/span&gt;.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Performance&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;span&gt;Standard&lt;/span&gt; или &lt;span&gt;Premium&lt;/span&gt; (что по сути означает &lt;span&gt;HDD&lt;/span&gt; или &lt;span&gt;SSD&lt;/span&gt; для создаваемого &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;) в зависимости от потребностей и бюджета. На скриншоте выбрано значение по умолчанию &lt;span&gt;Standard.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Redundancy&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;Куда будет реплицироваться &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;, для обеспечения &lt;span&gt;high&lt;/span&gt; &lt;span&gt;availability&lt;/span&gt;. Выбирается опция в зависимости от потребностей и бюджета. На скриншоте выбрано значение по умолчанию &lt;span&gt;Geo-redundant storage (GRS).&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="255"&gt;
&lt;p&gt;&lt;span&gt;Make read access to data available in the event of regional unavailability.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="561"&gt;
&lt;p&gt;&lt;span&gt;Оставляем значение по умолчанию.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="718" alt="" src="/blog/Media/Default/Users/SpbDevBlog/3-3.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 5. Нажимаем &amp;ldquo;&lt;span&gt;Review&lt;/span&gt; + &lt;span&gt;create&lt;/span&gt;&amp;rdquo; и после валидации всех настроек ещё раз &amp;ldquo;&lt;span&gt;Create&lt;/span&gt;&amp;rdquo;. &lt;span&gt;Создание storage account может занять пару минут.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="580" height="194" alt="" src="/blog/Media/Default/Users/SpbDevBlog/4-2.png" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 6.&amp;nbsp;После завершения создания жмём &amp;ldquo;Go to resource&amp;rdquo;.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="580" height="360" alt="" src="/blog/Media/Default/Users/SpbDevBlog/5-3.png" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 7.&amp;nbsp;В левой части страницы созданного storage account нажимаем &amp;ldquo;Containers&amp;rdquo;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="414" height="603" alt="" src="/blog/Media/Default/Users/SpbDevBlog/6-2.png" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 8.&amp;nbsp;На открывшейся странице нажимаем &amp;ldquo;+ Container&amp;rdquo;.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="580" height="333" alt="" src="/blog/Media/Default/Users/SpbDevBlog/7-1.png" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 9.&amp;nbsp;Указываем желаемое имя контейнера, остальные настройки оставляем по умолчанию.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;img width="299" height="277" alt="" src="/blog/Media/Default/Users/SpbDevBlog/8.png" /&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;10.&amp;nbsp;Нажимаем &amp;ldquo;Create&amp;rdquo; - контейнер будет создан и отображён на странице аккаунта.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="325" alt="" src="/blog/Media/Default/Users/SpbDevBlog/9.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;На этом процесс создания &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt; и настройки контейнера можно считать завершённым. Страницу аккаунта в браузере следует оставить открытой, при бэкапе базы данных она потребуется для получения доступа к контейнеру.&lt;/p&gt;
&lt;h4&gt;Бэкап базы данных с сервера &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises&lt;/span&gt; в &lt;span&gt;blob&lt;/span&gt; контейнер в &lt;span&gt;Azure&lt;/span&gt; &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li style="text-align: justify;"&gt;Открываем &lt;span&gt;SSMS&lt;/span&gt; и подключаемся к серверу &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises&lt;/span&gt; под логином, входящим в роль сервера &lt;span&gt;sysadmin&lt;/span&gt;.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Открываем окно для выполнения запросов.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Сначала нужно создать credential, под которым SSMS будет выполнять бэкап базы данных в Azure storage account. Для создания потребуется Access key созданного storage account. Возвращаемся в браузер с открытой страницей созданного аккаунта и нажимаем &amp;ldquo;Access keys&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img width="580" height="759" alt="" src="/blog/Media/Default/Users/SpbDevBlog/10.png" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 4. В открывшемся окне нажимаем &amp;ldquo;Show keys&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="452" alt="" src="/blog/Media/Default/Users/SpbDevBlog/11-1.png" /&gt; &lt;img width="580" height="343" alt="" src="/blog/Media/Default/Users/SpbDevBlog/12.png" /&gt;&lt;/p&gt;
&lt;p&gt;Одно из значений &lt;span&gt;Key&lt;/span&gt; для &lt;span&gt;key&lt;/span&gt;1 или &lt;span&gt;key&lt;/span&gt;2 нужно будет использовать на следующем шаге для создания &lt;span&gt;credential&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;5. В общем случае запрос для этого выглядит следующим образом&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="816"&gt;
&lt;p&gt;create credential [AzureStorageBackups] with&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; identity = '&amp;lt;storage account name&amp;gt;'&lt;/p&gt;
&lt;p&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp; secret = '&amp;lt;storage account key from portal (Access key)&amp;gt;';&lt;/p&gt;
&lt;p&gt;go&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style="text-align: justify;"&gt;&lt;span&gt;Здесь &amp;lt;storage account name&amp;gt; нужно заменить на имя созданного storage account - frdsstorageacc, а &amp;lt;storage account key from portal (Access key)&amp;gt; - на одно из значений Key из предыдущего шага.&lt;/span&gt;&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="816"&gt;
&lt;p&gt;create credential [AzureStorageBackups] with&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; identity = 'frdsstorageacc'&lt;/p&gt;
&lt;p&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp; secret = 'sidxe6IRr9lJ4i4HaTnlxQYs2xfw5JNhED1nkMqVYvDtElm00K1LY3QldryLjluhgzKHVXH7bvLVUMM2Oy/uSA==';&lt;/p&gt;
&lt;p&gt;go&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;6.&amp;nbsp;Нажимаем F5 - будет создан credential.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="151" alt="" src="/blog/Media/Default/Users/SpbDevBlog/13.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;7. Далее нужно получить URL контейнера, который был создан последним шагом при создании storage account в Azure. Переходим в браузер и&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;в&amp;nbsp; левой части страницы аккаунта нажимаем &amp;ldquo;Containers&amp;rdquo;.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &lt;img width="392" height="667" alt="" src="/blog/Media/Default/Users/SpbDevBlog/14.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 8.&amp;nbsp;Находим созданный контейнер (на скриншоте - backups) и кликаем по нему правой кнопкой мыши, а затем нажимаем к контекстном меню&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;ldquo;Container properties&amp;rdquo;.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="460" alt="" src="/blog/Media/Default/Users/SpbDevBlog/15.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 9. На появившейся странице видим URL с адресом контейнера.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &lt;img width="580" height="323" alt="" src="/blog/Media/Default/Users/SpbDevBlog/16.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 10.&amp;nbsp; В рамках данного руководства не рассматриваются различные опции, которые могут быть использованы при бэкапе баз данных, запрос&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;написан в простейшем виде для демонстрационных целей. &lt;span&gt;В общем виде он выглядит так.&lt;/span&gt;&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="816"&gt;
&lt;p&gt;backup database [&amp;lt;database name&amp;gt;]&lt;/p&gt;
&lt;p&gt;to url = N'&amp;lt;container address&amp;gt;/&amp;lt;backup_file_name&amp;gt;'&lt;/p&gt;
&lt;p&gt;with credential = '&amp;lt;credential&amp;gt;';&lt;/p&gt;
&lt;p&gt;go&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style="text-align: justify;"&gt;Здесь вместо &amp;lt;database name&amp;gt; указывается имя базы данных, вместо &amp;lt;container address&amp;gt; - URL контейнера из предыдущего шага, вместо &amp;lt;backup_file_name&amp;gt; - имя файла бэкапа и вместо &amp;lt;credential&amp;gt; - credential, созданный на шаге 6.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="816"&gt;
&lt;p&gt;backup database [DataWarehouse]&lt;/p&gt;
&lt;p&gt;to url = N'https://frdsstorageacc.blob.core.windows.net/backups/DataWarehouse_backup_20210525.bak'&lt;/p&gt;
&lt;p&gt;with credential = 'AzureStorageBackups';&lt;/p&gt;
&lt;p&gt;go&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;11.&amp;nbsp;Нажимаем F5 - бэкап будет создан в контейнере внутри Azure storage account.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="222" alt="" src="/blog/Media/Default/Users/SpbDevBlog/17.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;12.&amp;nbsp;Вернувшись в браузер и открыв страницу контейнера, можно убедиться, что он содержит page blob с указанным на предыдущем шаге&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; именем.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="124" alt="" src="/blog/Media/Default/Users/SpbDevBlog/18.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;На этом процесс создания бэкапа можно считать завершённым. Страницу &lt;span&gt;storage&lt;/span&gt; &lt;span&gt;account&lt;/span&gt; в браузере следует оставить открытой, т.к. она понадобится на следующем шаге.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;&lt;span lang="EN"&gt;Рестор базы данных из blob контейнера в Azure storage account в Azure SQL managed instance&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;В &lt;span&gt;SSMS&lt;/span&gt; подключаемся к &lt;span&gt;Azure&lt;/span&gt; &lt;span&gt;SQL&lt;/span&gt; &lt;span&gt;managed&lt;/span&gt; &lt;span&gt;instance&lt;/span&gt; под логином, входящим в роль сервера &lt;span&gt;sysadmin&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Открываем окно для выполнения запросов.&lt;/li&gt;
&lt;li&gt;Перед выполнением рестора нужно создать credential, под которым SSMS будет обращаться к Azure storage account. Credential, создаваемый на этом шаге отличается от того, который создавался для бэкапа базы данных. Возвращаемся на страницу контейнера в браузере и нажимаем &amp;ldquo;Shared access signature&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img width="580" height="357" alt="" src="/blog/Media/Default/Users/SpbDevBlog/19.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 4.&amp;nbsp;На открывшейся странице можно оставить все опции по умолчанию и нажать &amp;ldquo;Generate SAS token and URL&amp;rdquo;.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="428" alt="" src="/blog/Media/Default/Users/SpbDevBlog/20.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;5.&amp;nbsp;На появившейся странице видим Blob SAS token.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="698" alt="" src="/blog/Media/Default/Users/SpbDevBlog/21-1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 6. Запрос для создания &lt;span&gt;credential&lt;/span&gt; выглядит так.&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="816"&gt;
&lt;p&gt;create credential [&amp;lt;container address&amp;gt;] with&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; identity = 'SHARED ACCESS SIGNATURE'&lt;/p&gt;
&lt;p&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp; secret = '&amp;lt;SAS token&amp;gt;';&lt;/p&gt;
&lt;p&gt;go&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style="text-align: justify;"&gt;Здесь вместо &amp;lt;&lt;span&gt;container&lt;/span&gt; &lt;span&gt;address&lt;/span&gt;&amp;gt; нужно указать &lt;span&gt;URL&lt;/span&gt; контейнера, тот же самый, который использовался при бэкапе, а вместо &amp;lt;&lt;span&gt;SAS&lt;/span&gt; &lt;span&gt;token&lt;/span&gt;&amp;gt; - значение &lt;span&gt;Blob&lt;/span&gt; &lt;span&gt;SAS&lt;/span&gt; &lt;span&gt;token&lt;/span&gt; из предыдущего шага.&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="816"&gt;
&lt;p&gt;create credential [https://frdsstorageacc.blob.core.windows.net/backups] with&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; identity = 'SHARED ACCESS SIGNATURE'&lt;/p&gt;
&lt;p&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp; secret = 'sp=r&amp;amp;st=2021-05-25T12:11:13Z&amp;amp;se=2021-05-25T20:11:13Z&amp;amp;spr=https&amp;amp;sv=2020-02-10&amp;amp;sr=c&amp;amp;sig=9k57zcE2nzO666LPgIee%2Bx%2F%2Ba4lAj%2FbWbb%2FdX81fq04%3D';&lt;/p&gt;
&lt;p&gt;go&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 7.&amp;nbsp;Нажимаем F5 - будет создан credential.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="113" alt="" src="/blog/Media/Default/Users/SpbDevBlog/22.png" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;8.&amp;nbsp;Запрос для рестора базы данных:&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="816"&gt;
&lt;p&gt;restore database [DataWarehouse]&lt;/p&gt;
&lt;p&gt;from url = N'&amp;lt;container address&amp;gt;/&amp;lt;backup_file_name&amp;gt;';&lt;/p&gt;
&lt;p&gt;go&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;span&gt;Здесь вместо &amp;lt;container address&amp;gt; нужно указать URL контейнера, а вместо вместо &amp;lt;backup_file_name&amp;gt; - имя файла бэкапа. &lt;/span&gt;Полный &lt;span&gt;URL&lt;/span&gt; должен получиться точно таким же, какой использовался для бэкапа базы данных на сервере &lt;span&gt;on&lt;/span&gt;-&lt;span&gt;premises&lt;/span&gt;.&lt;/p&gt;
&lt;table width="816"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="816"&gt;
&lt;p&gt;restore database [DataWarehouse]&lt;/p&gt;
&lt;p&gt;from url = N'https://frdsstorageacc.blob.core.windows.net/backups/DataWarehouse_backup_20210525.bak';&lt;/p&gt;
&lt;p&gt;go&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;9.&amp;nbsp;Нажимаем F5 - через какое-то время база данных будет восстановлена.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="165" alt="" src="/blog/Media/Default/Users/SpbDevBlog/23-1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;На этом процесс миграции базы данных с сервера Microsoft SQL Server on-premises в Azure SQL managed instance можно считать завершённым.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;span&gt;Полезные ссылки&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;Backup database to Azure Blob Storage:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://dallasdbas.com/sql-backups-azure-storage/"&gt;https://dallasdbas.com/sql-backups-azure-storage/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Restore database to Azure SQL Managed Instance from Azure Blob Storage:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/azure-sql/managed-instance/restore-sample-database-quickstart"&gt;https://docs.microsoft.com/en-us/azure/azure-sql/managed-instance/restore-sample-database-quickstart&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description><pubDate>Tue, 15 Jun 2021 06:51:29 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Migratsiya-bazy-dannykh-s-servera-Microsoft-SQL-Server-on-premises-v-Azure-SQL-managedinstance-posredstvom-backup-restore</guid></item><item><title>Путешествие из локального в облако. Эпизод 2 </title><link>http://www.spbdev.biz:80/blog/puteshestvie-iz-lokalnogo-v-oblako-epizod2</link><description>&lt;p style="text-align: justify;"&gt;Вы знаете, на что похожа миграция? На переезд. Я дважды переезжал. Упаковка, переупаковка, сортировка отнимают много времени. Небольшие коробки я перевозил на машине, но крупногабаритные вещи&amp;nbsp;с помощью компании-перевозчика. Главная проблема переезда, так же как и миграции приложения заключается во времени и усилиях, затраченных на то, чтобы собрать, разобрать и вернуться к нормальной жизни.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;А что, если бы была возможность отключить электричество, газ, воду и переехать на грузовичке на новое место, где, подключившись&amp;nbsp; к службам жизнеобеспечения, продолжить жить? В подобном сценарии переезда не рассматривается процесс разбора или выбрасывания вещей. Мы отключаемся и подключаемся к источникам энергии и возвращаемся к прежнему образу жизни. И если для домашнего переезда это не совсем разумно, то для хостинговой среды приложения - вполне.&amp;nbsp; Лучший путь миграции в облако - наименее ухабистая дорога.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Что такое lift and shift?&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Lift and shift - стратегия миграции, которая выбирает путь наименьшего сопротивления, позволяя повторно размещать существующую рабочую нагрузку без модификаций. Как и при переезде, собирается все,&amp;nbsp; что есть в дата-центре и перемещается это в облако. Но в отличие от переезда на новое местожительства, здесь не снимаются стойки и не вытаскиваются серверы.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Миграция lift and shift перемещает существующий сервер с текущего хоста в облачный с использованием инструментов для репликации того, что запущено на локальном решении. Это означает, что наша база данных SQL, IIS конфигурация, параметры реестра и конфигурация ОС - части нового развертывания на Azure без необходимости переписывания части приложения для PaS. В этом случае происходит перемещение на виртуальные машины Azure и сокращается время работы и усилий.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Ограничения&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Миграция требует принятия ряда решений после выбора стратегии.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Зачем&amp;nbsp; нужна миграция? &amp;ndash; один из популярнейших вопросов. Главная причина &amp;ndash; меньшая зона ответственности. Управление сетями, rack - конфигурации, системы резервного копирования, устройства балансировки нагрузки и другие части инфраструктуры подвергают дополнительному риску. Приходится быть экспертами во всем оборудовании, понимать как части взаимосвязаны между собой. Это сложно сделать только с помощью процесса разработки ПО и документации. Позвольте Azure обрабатывать эти вещи, в то время как Вы работаете над приложением. Иногда приходится сталкиваться с таким возражением:" Разве в облаке не дороже?" Дороже может быть только в случае, если во внимание не принимаются ресурсы, создаваемые в облаке. Выяснение того, что нужно, сколько и когда поможет лучше определить расходы и принести максимальную ценность. Кто будет осуществлять lift and shift?&amp;nbsp; Кто будет следить за каждым шагом процесса миграции? Кто обновляет DNS? Это только несколько вопросов, которы&amp;nbsp; важно проработать команде.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Azure Migrate&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Azure Migrate - набор инструментов в Azure, который помогает в процессе lift and shift, предоставляет возможность обнаружить и определить, как выглядит текущее развертывание приложения. Используйте центральный репозиторий для перемещения таких элементов как резервные копии сервера и баз данных.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Azure Migrate оценивает и подготавливает серверы, веб-приложения, виртуальные рабочие столы и даже большие неструктурированные данные.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Azure Migrate помогает выполнить оценку на существующем развертывании для определения готовности к облачной миграции. Изучите существующие VMWare, Hyper-V, Xen, или даже серверы другой облачной хостинговой компании. Ключевые части оценки включают определение места миграции,&amp;nbsp; размер виртуальных машин, использование и производительность серверов. После завершения Azure Migrate составляет рейтинг&amp;nbsp; успешности миграции. Станет понятно, готовы ли Вы перейти в облако ДО того, как выполните этот процесс.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;После определения того, что нужно, можно реплицировать серверы с использованием Azure Migrate, установленным на виртуализированный сервер Windows. Программно-аппаратный комплекс разворачивается на решениях VMware или Hyper-V, с использованием шаблонов OVA или VHD. Программно-аппаратный комплекс будет координировать взаимодействие, безопасность и процесс миграции данных для приложений.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;После завершения репликации сервера необходимо время, подходящее для завершения миграции наилучшим образом, чтобы перейти на хост в Azure. Произведите некоторые финальные изменения в DNS или расскажите команде о начале использования нового расположения при входе в определенные приложения. Это продолжает процесс коммуникации, упомянутый ранее.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Информация, приведенная здесь, общая. Лучший способ начать изучать как выглядит миграция на практике - обучающий модуль от Microsoft &amp;ldquo;Design your migration to Azure&amp;rdquo;. Вместе с модулем идет много полезной информации на сайте Microsoft Docs. В случае, если что-то пойдет не так, всегда поможет служба поддержки Azure.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp;&lt;/p&gt;</description><pubDate>Mon, 31 May 2021 13:28:11 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/puteshestvie-iz-lokalnogo-v-oblako-epizod2</guid></item><item><title>Требования к облачной миграции </title><link>http://www.spbdev.biz:80/blog/Trebovaniya-k-oblachnoy-migratsii</link><description>&lt;p style="text-align: justify;"&gt;Пандемия COVID-19 вынудила компании быстро менять приоритеты, чтобы оставаться на плаву. Как результат, ожидается, что до 85% предприятий перейдут в облако к 2025 г. Однако, сбор и миграция массивов данных в облако усложняет обеспечение целостности.&amp;nbsp;Проблемы миграции решаются, опираясь на понятия целостности, безопасности и суверенитета.&amp;nbsp; Хотя это и первоначально вызовет затруднения, однако&amp;nbsp;в будущем приведет к оптимальным&amp;nbsp;бизнес-решениям.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Трудности миграции данных в облако.&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;При перемещении данных в облако количество подключений к источникам и местам хранения увеличивается.&amp;nbsp; По мере роста объемов данных возникают проблемы с поддержкой, связанные с согласованностью, точностью, доступностью и качеством.&amp;nbsp; Таким образом, создание программы Data Governance&amp;nbsp; требует дополнительных мер.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Сбор данных в единый источник до миграции в облако гарантирует, что члены команды работают с одной и той же информацией.&amp;nbsp; Помимо объединения данных, инструменты сбора и интеграции, использующие машинное обучение и ИИ, помогут в сортировке поступающих данных.&amp;nbsp; Ведение бизнеса в облаке способно спровоцировать новые расходы, которые при правильном подходе команды Data Management легко нивелируются.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Первый шаг - это проактивный подход к безопасности, которая достигается путем проведения полной инвентаризации, категоризации и классификации данных.&amp;nbsp; Пренебрежение этим шагом гарантирует получение неоптимального результата в таких&amp;nbsp; функциях, как соблюдение требований, управление рисками, оптимизация ценности информации и операционная эффективность.&amp;nbsp; Воспользуйтесь комитетом Data Governance и инструментами классификации контента для категоризации дальнейших данных, которые поддерживают конкретные бизнес-единицы.&amp;nbsp; Этот процесс помогает увеличить осведомленность о данных и повысить точность.&amp;nbsp; Последний шаг - установление правил и процедур для укрепления и поддержки Data Governance в компании.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Целостность данных&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Целостность данных - больше, чем инструмент.&amp;nbsp; Поддержка данных в режиме реального времени требует отдельной команды и стратегии. Отдельное подразделение Data Management во главе с директором по обработке и анализу данных&amp;nbsp; способствует правильному использованию данных. Перемещение данных в облако повысило необходимость наличия таких позиций как главный директор по обработке и анализу данных (CDO), руководитель службы защиты информации (CPO), руководитель по информационной безопасности для совместной работы над Data Governance.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Data Governance - точка пересечения сфер.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Безопасность данных&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Наличие правильных инструментов и выделенной команды Data Governance&amp;nbsp; повышает возможность компании в&amp;nbsp;получение выгоды из данных. У нарушения требований соответствия двойной эффект: денежные штрафа и потеря доверия клиентов.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Безопасность данных - важная часть Data Governance. Защита данных в облаке отличается от on-premise новыми потоками, большей поверхностью атаки и повышенной сложностью конвейера.&amp;nbsp; Данными в облаке легче обмениваться и получать к ним доступ.&amp;nbsp; Информация из одного отдела может быть быстро отправлена в другой.&amp;nbsp; К сожалению, такая доступность приводит к тому, что конфиденциальные данные оказываются не в&amp;nbsp; том месте или не в тех руках.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Конфиденциальность и безопасность -&amp;nbsp; элементы в обеспечении работоспособности и целостности данных, особенно в облаке. Для сохранения данных без ошибок и защиты от нарушения требуется отдельная команда. Команда, сосредоточенная на конфиденциальности и безопасности, может внедрить средства контроля безопасности, которые автоматизируют удаление или анонимизацию конфиденциальной информации и помогают избежать штрафов и потери репутации.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Суверенитет данных&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;В процессе переноса рабочих нагрузок в облако, упускается проблема суверенитета.&amp;nbsp; Суверенитет данных - концепция, согласно которой данные подчиняются законам и структурам управления страны, в которой собираются.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Использование гибридного облачного подхода решает проблемы, связанные с суверенитетом данных. Организации с частными локальными средами преодолевают эти трудности без потери преимуществ, предоставляемых публичным облаком. Гибридные облака дают возможность выбирать данные для развертывания во внешнем облаке и данные для хранения в локальной среде.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Запомните: стратегия данных - это бизнес-стратегия. Инвестирование в правильные инструменты и опытную команду окупит вложенные инвестиции. По мере роста надежных корпоративных хранилищ, растут и доходы&lt;/p&gt;</description><pubDate>Mon, 31 May 2021 13:28:07 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Trebovaniya-k-oblachnoy-migratsii</guid></item><item><title>Миграция кода с использованием автоматизации DevOps</title><link>http://www.spbdev.biz:80/blog/Migratsiya-koda-s-ispolzovaniem-avtomatizatsii-DevOps</link><description>&lt;p style="text-align: justify;"&gt;Миграция из одной системы управления кодом в другую - нетривиальная задача. Командам важно поддерживать историю кода, структуру ветвей, разрешения и интеграции.&amp;nbsp; Рассмотрим случай миграции с Bitbucket в GitHub крупной медицинской компании.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Обнаружив, что команды разработчиков использовали несколько систем управления исходным кодом, что приводило к увеличению затрат на поддержание задвоенных операций и стоимости лицензий, компания выбрала &amp;nbsp;GitHub &amp;nbsp;в качестве единой платформы для управления исходным кодом.&amp;nbsp; Корпоративный продукт GitHub предлагает ряд преимуществ, включая интеграцию инструментов, понятный интерфейс для управления проектами и командами и уведомление о событиях, опцию для облачного или локального развертывания платформы управления исходным кодом.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Миграция нескольких тысяч репозиториев - серьезная проблема. От команды DevOps требуется соблюдение сроков продления лицензии. Во избежание дополнительных затрат, командам требуется перенести базу кода и связанные метаданные.&amp;nbsp; В подходе, описанном ниже, используются следующие инструменты CloudBees Jenkins&amp;trade; , Red Hat Ansible&amp;trade; playbooks и скрипты Python.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Подход&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Рис 1 демонстрирует, что миграция включает создание процесса миграции Jenkins для определения исходного проекта&amp;nbsp; Bitbucket, целевой проект GitHub, информация о принадлежности команды, информация о репозитории, дополнительные требования для интеграции. Эта информация сохраняется в новом файле, добавленном в корень исходного дерева (&amp;lsquo;app-info.yml&amp;rsquo;). Такой подход упрощает будущую автоматизацию интеграции и обеспечивает понятный способ отслеживания метаданных приложения в базе.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="752" alt="" src="/blog/Media/Default/Users/SpbDevBlog/1-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Рис 1 Процесс автоматизации миграции в Github&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В автоматизации миграции прорабатываются факторы, включая обеспечение целевого проекта GitHub соответствующими разрешениями видимости, использование стандартов наименования проектов, интеграция с существующей или будущей автоматизацией сканирования безопасности, применение правил защиты, определенные организацией и поддержка автоматизации необходимых конвейеров CI/CD.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Трансфер кода&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;И хотя технически клонирование кода в новый репозиторий - элементарный вариант, но требует значительных ручных изменений в нескольких ключевых файлах автоматизации, находящихся в корне структуры папок проекта.&amp;nbsp; К сожалению, принимая во внимание, что каждая команда разработчиков использует определенную версию библиотеки, этот шаг выполняется вручную, а не автоматическим.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Правила защиты&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Организация установила набор правил управления версиями деревьев. Например, политика требует, чтобы запрос был одобрен хотя бы одним проверяющим до того, как код объединится для ветвей&amp;nbsp; &amp;lsquo;master&amp;rsquo;, &amp;lsquo;release&amp;rsquo;, и &amp;lsquo;develop&amp;rsquo; в репозитории. Эти правила закодированы в скриптах миграции python и извлекаются из Ansible playbook во время создания проекта GitHub.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Автоматизированные изменения конвейера CI/CD&amp;nbsp;&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Для поддержки существующих конвейеров CI/CD переносимые базы кода требовали обновления файла конфигурации конвейера.&amp;nbsp; Сюда входили ссылки на конфигурацию для автоматического обновления Jira, автоматическое сканирование безопасности, интеграции с библиотекой package control. Эти изменения были записаны в скриптах python и извлечены из Ansible playbook во время миграции кода в GitHub.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Управление ключами доступа и учетными записями&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Автоматизированные процессы&amp;nbsp; CI/CD требуют использования учетных записей и общедоступного секретного ключа для правильного функционирования.&amp;nbsp; В процессе миграции важно сохранить эти ключи доступа для предотвращения неправильного использования журналов, уведомлений или других небезопасных отчетов. Команда миграции использовала функцию&amp;nbsp; Ansible vault и скрипты Groovy&amp;nbsp; для обновления встроенной системы управления учетными записями Jenkins, чтобы гарантировать безопасную передачу ключей проекта/учетных записей во вновь созданные связанные джобы&amp;nbsp;&amp;nbsp; GitHub в процессе миграции.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;GitHub Pre-Migration Setup&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Интеграция GitHub Jenkins построена как отдельная задача для создания "команды"&amp;nbsp; GitHub. Сюда входят конфигурация команды с собственным именем, административные пользователи и соответствие в папке сборки Jenkins. Для каждого репозитория также установлен Jenkins &amp;ldquo;web-hook&amp;rdquo; для гарантии того, что для каждого запуска конвейера CI/CD используется соответствующий мастер Jenkins.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Интеграция автоматизированного тестирования&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Как часть контроля качества кода сканирование кода привязано к определенному репозиторию&amp;nbsp; и подразумевается как часть рабочего процесса Jenkins CI/CD. Результаты сканирования отображаются в отдельной вкладке&amp;nbsp; GitHub. Таким образом, созданный проект может напрямую сообщать разработчикам результаты автоматизированного анализа качества кода.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Результаты&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Команде поддержки DevOps было необходимо уложиться в 4 мес для завершения полной миграции с Bitbucket to GitHub и избежать расходов на продление лицензии. Принимая во внимание масштаб проблемы, единственное подходящее решение - автоматизация большей части миграции. Использование комбинированного инструмента, состоящего из скриптов Jenkins, Ansible playbooks и сценариев Python, позволило команде DevOps успешно завершить процесс миграции и модификации всех баз кода за несколько недель до дедлайна.&amp;nbsp; Как результат, все команды активны в GitHub, а репозитории Bitbucket&amp;nbsp; заархивированы.&lt;/p&gt;</description><pubDate>Mon, 31 May 2021 13:28:01 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Migratsiya-koda-s-ispolzovaniem-avtomatizatsii-DevOps</guid></item><item><title>Миграция из облака в облако: когда делать, а когда забыть.</title><link>http://www.spbdev.biz:80/blog/Migratsiya-iz-oblaka-v-oblako-kogda-delat-a-kogda-zabyt</link><description>&lt;p style="text-align: justify;"&gt;Миграция данных от одного облачного провайдера к другому - не такая простая задача. Когда речь идет о гигабайтах, терабайтах или петабайтах данных, миграция становится долгой и дорогостоящей процедурой.&amp;nbsp; Несмотря на это, бывают ситуации, когда это стоит усилий и в некоторых ситуациях становится единственным способом двигаться вперед. &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Зачем же рассматривать миграцию из облака в облако?&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Необходимость модернизации операций, следующая за слиянием или поглощением, часто приводит бизнес-лидеров к решению о миграции.&amp;nbsp; Хотя это и может показаться рациональным шагом, возможно, затраты и сбои перевесят любые преимущества. Важно полностью понимать происходящее, а затем оценивать потенциальные последствия перед принятием этого шага.&amp;nbsp; Действительно ли Вам нужен полный переход из одного облака в другое? Или есть ли альтернативные подходы, которые помогли бы достичь желаемого результата другим способом? &amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В некоторых ситуациях логика подобной миграции более понятна. Это может быть важно для удовлетворения критических бизнес-требований, связанных с нахождением данных или правилами суверенитета данных.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Что осложняет миграцию из облака в облако?&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Это не просто перенос данных из одной облачной среды в другую. Существует техническая часть, которую необходимо рассмотреть заранее, т.к. различия между ресурсами двух платформ могут потребовать новых решений.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Возьмем балансировщики нагрузки.&amp;nbsp; В AWS они обрабатываются с помощью процедуры завершения SSL, в то время как в Azure требуется Azure Application Gateway. Это два совершенно разных зверя. Иногда кажется, что системы похожи в оркестровке контейнеров, например, Azure Kubernetes Service&amp;nbsp;(AKS)&amp;nbsp;and&amp;nbsp;Amazon&amp;nbsp;Elastic Kubernetes Service&amp;nbsp;(EKS) , но они могут создавать технические трудности.&amp;nbsp; В AWS управление идентификацией и доступом (IAM) в основном используется для контроля доступа, но в Azure этот момент будет покрываться с помощью &amp;nbsp;Azure Active Directory&amp;nbsp;(Azure AD). Любому приложению, мигрирующему от одного облачного провайдера к другому, необходима адаптация для поддержки метода, используемого конечной средой.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Конечное решение может выглядеть и работать одинаково, независимо от того, где оно расположено.&amp;nbsp; Однако, для корректной работы в новой среде требуются изменения и компромисс. Разработчики и инженеры также должны быть готовы работать с новыми ресурсами. &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Как решить, стоит ли это усилий?&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Лица, принимающие решения, должны определить, превышают ли преимущества подобной миграции риски.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Ключевой фактор - влияние на команду.&amp;nbsp; Подумайте, какие наборы знаний уже есть, а также о последствиях обучения и потенциальной утечки персонала. &amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Зрелость существующей деятельности в облаке также имеет значение. Если был достигнут прогресс в модернизации приложений и внедрении подходов DevOps, таких, как Ci/CD, это усложнит работу.&amp;nbsp; Любая инфраструктура как код (IaC) или конфигурация как код (CaC) должны быть переписаны для новой среды. &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Итак, Вы решили пойти на это. Что теперь?&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;К процессу миграции из облака в облако должен быть такой же подход, как и к любой другой миграции. Важно понимать целевые данные, высокоуровневый процесс миграции и как это будет синхронизировано. Потратьте время на изучение того, как методы автоматизации DevOps могут ускорить процесс миграции. Обратите внимание на мультиоблачные инструменты, особенно, если у команды есть опыт работы с ними.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Наверняка наступит период двойных облачных операций, когда используются новая и старая среды.&amp;nbsp; Необходимо обеспечить наличие соответствующих инструментов и навыков для управления этой критической фазой. Необходим системный подход к обучению для подготовки команды к работе в новой облачной среде. &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Наконец, не забывайте, что фаза двойного облака приведет к увеличению затрат.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Если Вы решили забыть об этом. Какие альтернативы?&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В большинстве случаев, альтернативные подходы помогают в достижении желаемого результата без затрат и потрясений, связанных с миграцией из облака в облако. &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Если оптимизация затрат стала толчком к рассмотрению этого шага, то существуют различные варианты, которые можно изучить.&amp;nbsp; Выполнение ревью с фокусом на стоимости может помочь в определении возможностей&amp;nbsp; для экономии затрат на текущей платформе. Большинство облачных поставщиков предлагают корпоративные соглашения, которые помогут обеспечить дальнейшую экономию средств, особенно в отношении устаревшего ПО.&amp;nbsp; Внедрение практик DevOps и реконструкция для повышения производительности в существующих облачных средах, также могут преодолеть или компенсировать некоторые сложности. &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp;&lt;/p&gt;</description><pubDate>Fri, 30 Apr 2021 05:39:32 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Migratsiya-iz-oblaka-v-oblako-kogda-delat-a-kogda-zabyt</guid></item><item><title>3 главные ошибки мультиоблачной архитектуры</title><link>http://www.spbdev.biz:80/blog/3-glavnye-oshibki-multioblachnoy-arkhitektury</link><description>&lt;p style="text-align: justify;"&gt;Оптимизация мультиоблачной архитектуры - это возможность настроить технологию для совершенствования архитектуры под бизнес-требования, а также для минимизации затрат.&amp;nbsp; От каждого доллара, потраченного на облачную технологию, Вы хотите получать максимум отдачи для бизнеса.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Правда заключается в том, что лишь некоторые облачные архитектуры оптимизированы полностью.&amp;nbsp; Сложность состоит в том, что об оптимизации архитектуры нужно подумать до развертывания и введению в эксплуатацию.&amp;nbsp; Потом будет поздно.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Итак, рассмотрим причины, по которым мультиоблачная архитектура не может быть полностью оптимизирована.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;1. Внедрение слишком большого числа технологий.&amp;nbsp; Мультиоблачные архитекторы и команды разработчиков часто добавляют как можно больше технологий для всех типов требований, которые могут возникнуть.&amp;nbsp; Вам может понадобиться только одна технология, но используете три; можете работать с одним ресурсом хранения, но у Вас их семь.&amp;nbsp; В итоге, это дополнительные затраты и никакой дополнительной ценности для бизнеса.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Это сложная для разрешения проблема, потому что большинство архитекторов пытаются строить на будущее, которое еще не наступило.&amp;nbsp; Они выбирают базы данных со встроенной технологией зеркального отображения, потому что могут полностью перейти на распределенные базы данных, хотя перспектива этого может быть отдаленной.&amp;nbsp; Таким образом, количество типов баз данных увеличивается с 2х до 4х без веской на то причины.&amp;nbsp; Имейте в виду, чтобы приблизиться к оптимизированному состоянию, необходимо строить для "минимального срока службы".&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;2. Не строить под конкретные требования.&amp;nbsp; Детальные требования понятны, потому что изначально определяют, какой будет мультиоблачная архитектура, очерчивают схемы проблем, которые архитектура должна решать.&amp;nbsp; Тем не менее до сих пор существует большое количество мультиоблачных проектов, которые проектируются и строятся под общие требования.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Требования определяют минимальный срок службы мультиоблачной архитектуры, а не наоборот.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;3. Отсутствие гибкости. Архитекторы, занятые созданием мультиоблаков, даже если они близки к полной оптимизации, часто игнорируют гибкость при проектировании.&amp;nbsp; В данном случае, гибкость означает понимание, что часть архитектуры должна легко адаптироваться под изменения, которые могут появиться в будущем.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Обязательно поместите волатильность в домен.&amp;nbsp; Например, Вы ищете возможность избежать полной переделки базы данных или приложения вокруг простых изменений.&amp;nbsp; Скажем, Вы используете виртуализацию данных между базами данных и приложениями, позволяющей изменять виртуальную схему&amp;nbsp; так часто, как требуется для использования инструмента отображения без дорогостоящих изменений и рисков для физической базы данных в мультиоблаке. Это отличается от развертывания большинства технологий, т.к. изменение (включая степень и частоту) - само по себе требование.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Архитектура остается больше искусством, чем наукой.&amp;nbsp;&amp;nbsp;Понимание передовых практик принесет гораздо больше пользы бизнесу. В этом и состоит цель.&lt;/p&gt;</description><pubDate>Fri, 30 Apr 2021 05:36:44 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/3-glavnye-oshibki-multioblachnoy-arkhitektury</guid></item><item><title>Путешествие из локального в облако: начало (Эпизод 1)</title><link>http://www.spbdev.biz:80/blog/Puteshestvie-iz-lokalnogo-v-oblako-nachalo-Epizod-1</link><description>&lt;p style="text-align: justify;"&gt;Когда дело доходит до миграции в облако, можно выделить два основных ключа успеха этого процесса.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Во-первых, начинайте с малого. Это означает сфокусироваться на одной простой среде приложения. При перемещении в облако мы будем внедрять инструменты и запускать приложение в новой среде.&amp;nbsp; Эти изменения могут затруднять определение того, насколько успешно перемещено приложение.&amp;nbsp; Чем больше мы знаем о перемещаемом приложении или сервисе, тем больше шансов на успех.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Во-вторых, определите как успех выглядит для Вас, команды, организации. Шаги, предпринимаемые сейчас, готовят почву для успеха в будущем.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Миграция в облако - это нечеткое понятие и может выполняться по различным причинам.&amp;nbsp; Некоторые из этих причин повлияют на то, сколько изменений вы готовы выдержать в процессе миграции в облако.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Поскольку работа будет осуществляться на оборудовании, находящемся под Вашим контролем, необходимы четкие представления о работоспособности приложения для правильного распределения количества ресурсов.&amp;nbsp; Отсутствие этой информации может привести к чрезмерным затратам и отсутствию эффективности в сравнении с Вашим опытом работы в локальной среде.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Определение (взаимных) зависимостей&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Правильно начинать миграцию с понимания того, с чем связано приложением. При миграции в облако некоторые сервисы и данные могут оставаться локальными и необходимо убедиться, что приложение сможет получить к ним доступ.&amp;nbsp; Некоторые необходимо перенести в облако и разместить рядом с приложением.&amp;nbsp; Пока нет четкого понимания, с чем связано приложение, существует риск нарушить поведения приложения в процессе перемещения.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Application Insights&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Полезным инструментом в этом процессе является Application Insights. Хотя его основной функцией является мониторинг приложения, Application Insights может использоваться для формирования осведомленности о службах, к которым подключается приложение.&amp;nbsp; Существует 2 основных метода интеграции Application Insights&amp;nbsp; - Codeless Attach и с использованием SDK.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;И хотя Application Insights - служба, работающая в Azure, Вы не ограничены в использовании только приложений Azure. Application Insights также предлагает простой доступ к рабочим нагрузкам, работающим в IIS через IIS (или Status Monitor М2).&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Application&amp;nbsp;Map&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Application&amp;nbsp;Map помогает визуализировать и отслеживать проблемы в распределенных приложениях.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="447" alt="" src="/blog/Media/Default/Users/SpbDevBlog/ApplicationInsights-ApplicationMap.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Предположим, что большинство приложений обладает некоторыми внешними зависимыми объектами.&amp;nbsp; Приложения без зависимых объектов обычно называются устройствами или виртуальными устройствами.&amp;nbsp; Это, как правило, автономные экосистемы, где у Вас нет достаточного контроля.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Почти у всего остального есть какие-либо взаимодействия, и Application Map помогает обнаружить их.&amp;nbsp; Это особенно полезно для приложений, когда нет команд, назначенных для их обслуживания или предоставляемых подрядчиками или консультантами.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Codeless Attach&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Поговорим о сборе данных с помощью Application Insights. Первый метод - Codeless Attach- &amp;nbsp;позволяет Application Insights отслеживать приложение без изменения кода.&amp;nbsp;&amp;nbsp; Настроить его на Windows Server довольно просто.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Сначала, установите&amp;nbsp; модуль Power Shell Az.ApplicationMonitor.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="965" height="72" alt="" src="/blog/Media/Default/Users/SpbDevBlog/Безымянный-1.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp; &lt;img width="580" height="87" alt="" src="/blog/Media/Default/Users/SpbDevBlog/2-3.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;span&gt;Enable&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;ApplicationInsightsMonitoring &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;ConnectionString&lt;/span&gt;&lt;span&gt; xxxxxxxx&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;xxxx&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;xxxx&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;xxxx&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;xxxxxxxxxxxx&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Теперь любое приложение, которое еще не ссылается на Application Insights SDK будет автоматически инструментировано.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Важный момент: если у приложения уже есть SDK, тогда нужно настроить&amp;nbsp; приложение через код или файл конфигурации, чтобы связать с Application Insights. Это также означает, Вы не будете нарушать существующий мониторинг Application Insights, подключив его для других неинструментированных&amp;nbsp;приложений.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Вы можете проверять состояние каждого веб-сайта в IIS с помощью&amp;nbsp;&lt;span&gt;Get-ApplicationInsightsMonitoringStatus&lt;/span&gt;&amp;nbsp;cmdlet.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Другой вариант - включить Application Insights SDK в приложение.&amp;nbsp; Недавние шаблоны .Net приложений уже включают Application Insights SDK; в таком случае речь идет о конфигурации инструментального ключа или о строке подключения.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="83" alt="" src="/blog/Media/Default/Users/SpbDevBlog/3-2.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Но Вы можете сделать гораздо больше: настроить отображение приложения в Application Map, установив имя облачной роли и/или имя облачного экземпляра. Несмотря на имена свойств, они могут быть использованы независимо от того, где запущено приложение.&amp;nbsp; Они помогают идентифицировать приложение и сервер (или экземпляр сервиса), на которых запущено.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="215" alt="" src="/blog/Media/Default/Users/4.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;После того как приложение инструментировано, Вам нужно дать ему время поработать. Некоторые зависимости могут быть часто недоступны, поэтому продление периода обнаружения - на дни, недели или даже месяцы может помочь выявить доступные ресурсы.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В то время как Application Insights запущен для сбора сведений Application Map, у Вас есть возможность собирать данные о производительности.&amp;nbsp; Это может стать основой того, как приложение должно работать в облаке.&amp;nbsp; Вы увидите вызовы из приложения в зависимости. Это поможет оценить необходимость перемещения зависимости в облако (или же ее можно оставить локально на какое-то время), эффективность сервиса SKU, на котором Вы работаете: нужно ли его масштабировать или у Вас есть место для его уменьшения и экономии денег.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Теперь, когда у Вас есть какие-то данные о приложении и его зависимостях, можно приступать к планированию миграции.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Перемещение приложения и базы данных вместе имеет смысл, учитывая тесную связь и зависимость производительности страницы от результатов работы базы данных.&lt;/p&gt;</description><pubDate>Fri, 30 Apr 2021 05:33:15 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Puteshestvie-iz-lokalnogo-v-oblako-nachalo-Epizod-1</guid></item><item><title>Ключевые принципы развертывания с использованием  архитектуры в масштабе предприятия</title><link>http://www.spbdev.biz:80/blog/Klyuchevye-printsipy-razvertyvaniya-s-ispolzovaniem-arkhitektury-v-masshtabe-predpriyatiya</link><description>&lt;p style="text-align: justify;"&gt;Итак, Вы приняли решение сделать Azure частью своей IT-стратегии.&amp;nbsp; У команды есть опыт локального развертыванием инфраструктуры и сейчас важно изучить возможности запуска рабочих нагрузок в Azure.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Погружаясь в любой новый проект, есть ключевые моменты проектирования и принятия решения, которые должны быть обсуждены и поняты на старте.&amp;nbsp; Развертывание зоны размещения корпоративного масштаба и последующих ресурсов в облаке не отличается.&amp;nbsp; Архитектура в масштабе предприятий основана на принципах проектирования, которые служат компасом для проектных решений в критических технических областях.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Команде необходимо обсудить критические области проектирования, изложенные в документации по зонам размещения в масштабе предприятия. Вот только несколько важных пунктов:&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li&gt;Регистрация корпоративного соглашения и участников Azure Active Directory&lt;/li&gt;
&lt;li&gt;Управление идентификацией и доступом&lt;/li&gt;
&lt;li&gt;Административна группа и организация подписки&lt;/li&gt;
&lt;li&gt;Топология сети и подключения&lt;/li&gt;
&lt;li&gt;Управление и мониторинг&lt;/li&gt;
&lt;li&gt;Непрерывность бизнеса и аварийное восстановление&lt;/li&gt;
&lt;li&gt;Безопасность, управление и соблюдение требований&lt;/li&gt;
&lt;li&gt;Автоматизация платформы и DevOps&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style="text-align: justify;"&gt;Подписки и управление&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Один из первых пунктов, о котором необходимо подумать - настройка среды с точки зрения иерархии административных групп и ответственных лиц за операции платформы.&amp;nbsp; Существует множество способов сегментирования среды.&amp;nbsp; Начните с определения критерия конфигурирования подписки и обязанностей ее владельца. Это позволит создать кросс-функциональную команду платформы DevOps для создания, управления и администрирования архитектуры.&amp;nbsp; Команды разработчиков приложений DevOps получат разрешения владельца подписок на создание и управление источниками приложений с помощью модели DevOps.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Использование подписок для разделения среды помогает с управлением затратами и повседневными обязанностями по управлению.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Некоторые предложения для владельцев подписки:&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li&gt;Выполняйте проверку доступа в Azure Active Directory (Azure AD)&amp;nbsp;Privileged Identity Management ежеквартально или дважды в год, чтобы гарантировать, что права доступа не распространяются по мере перемещения пользователей внутри организации клиента.&lt;/li&gt;
&lt;li&gt;Возьмите полную ответственность за расходование бюджета и использование ресурсов.&lt;/li&gt;
&lt;li&gt;Обеспечьте соблюдение политики и внесите корректировки при необходимости.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style="text-align: justify;"&gt;Работа в сети&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Работа в сети и то, как Вы хотите, чтобы действовала среда- автономно или интегрировалась в существующие среды- будут важной частью встреч по проектированию. Необходимо спланировать IP-адресацию, систему доменных имен, разрешение имен, топологию, шифрование сети и требования к проверке трафика, гибридное подключение.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;У каждой организации будут свои требования, существующие настройки и сложности, которые необходимо преодолеть на пути внедрения облачной стратегии.&amp;nbsp; Обсудив потребности и варианты, команде важно посоветоваться с партнером Microsoft, чтобы использовать внешний опыт и убедиться, что выбранное направление верное.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Безопасность, управление и соблюдение требований&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Предположим, у Вас есть некоторые проблемы с текущей средой.&amp;nbsp; Например, пароли и секретная информация хранятся в защищенной таблице excel. Кроме того, большинство локальных источников нарушают соглашение об именах компании, поэтому важно избежать проблем при переходе в облако.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Для паролей и секретной информации вместо таблицы excel лучше использовать Azure Key Vault. Тем не менее, обязательно убедитесь, что разрешения настроены верно, а сотрудники ИТ-отдела готовы к тому, что будут видеть только то, что нужно.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Внедрение Azure Policy упростит соответствие новых ресурсов соглашению об именовании компании.&lt;/p&gt;</description><pubDate>Fri, 30 Apr 2021 04:54:26 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Klyuchevye-printsipy-razvertyvaniya-s-ispolzovaniem-arkhitektury-v-masshtabe-predpriyatiya</guid></item><item><title>Лучшие друзья DevOps инженеров</title><link>http://www.spbdev.biz:80/blog/Luchshie-druzya-DevOps-inzhenerov</link><description>&lt;p style="padding-left: 30px; text-align: justify;"&gt;Средства обеспечения производительности -&amp;nbsp; лучшие друзья DevOps инженеров, способные помочь в создании отличного кода. Эти бесплатные инструменты помогают сэкономить время, взаимодействовать и общаться в проектах.&amp;nbsp; Они помогают в тестировании приложений с использованием повторяющейся инфраструктуры, совместной работы и коммуникации.&lt;/p&gt;
&lt;h3 style="padding-left: 30px; text-align: justify;"&gt;&lt;strong&gt;Инструменты разработки/повышения производительности&lt;/strong&gt;&lt;/h3&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Здесь приведен список инструментов, помогающий улучшить производительность разработчика. Приведенные инструменты существуют некоторое время и уже зарекомендовали себя с самой лучшей стороны среди разработчиков DevOps.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Vargant&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Среди инструментов DevOps Vagrant широко используется для разработки и тестирования, для имитации производственной среды.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;С помощью Vagrant разработчики могут настраивать виртуальные машины, импортируя блоки (шаблоны виртуальных машин) из облака Vagrant, устанавливая параметры виртуальных машин (такие, как сетевое хранилище, и т.д.) и запуская инструменты конфигурирования, например, Puppet или Chef.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Преимущество Vagrant - наличие множества стеков приложений, которые поставляются в составе блоков vargant. Например, если Вы хотите разрабатывать на стеке LAMP, вы можете найти блок LAMP&amp;nbsp; в облаке Vargant. Он содержит список всех доступных блоков, разработанных сообществом с версиями LAMP.&amp;nbsp; Использование этих блоков помогает экономить время на настройке приложений вручную.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Vargant позволяет запускать среды, помещенные в песочницу, не нарушая конфигурации рабочей станции.&amp;nbsp; Например, если нужны среды разработки Python 2 и 3, у Вас могут быть два блока vargant, работающих на python 2 и 3.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Кроме того, у Вас могут быть свои модули puppet, справочное руководство, или набор сценариев Ansible, которые будут использоваться в конфигурационном файле vargant, автоматизирующем конфигурацию с использованием руководства, модуля или набора сценариев.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Варианты использования Vargant&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Для повторяющихся сред разработки: Вы можете делиться файлом vargant с другими разработчиками, которые будут запускать ту же виртуальную машину, что и у Вас.&amp;nbsp; Это позволяет избежать медленного перемещения конфигурации между конфигурациями рабочих станций разработчиков.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Нагрузочное тестирование/ Имитация производственной среды:&amp;nbsp; Вы можете развернуть блоки vargant за считанные секунды для нагрузочного тестирования или тестирования производительности, затем ликвидировать их.&amp;nbsp; Также, Вы можете создать производственную среду, объединив блоки vargant вместе.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Docker&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Если Вы разработчик, то несомненно полюбите этот инструмент. Docker -&amp;nbsp; инструмент с открытым исходным кодом, позволяющий разработчикам создавать и управлять приложениями в контейнерах Linux.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Docker Hub - онлайн хранилище образов Docker, позволяющее загружать заранее подготовленные образы Docker с большинством стеков.&amp;nbsp; Разработчикам не нужно создавать виртуальные машины или смешивать существующие конфигурации рабочей станции - они могут просто начать работу над приложениями, используя образы docker.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Запуск контейнера осуществляется менее, чем за секунду.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Дополнение Docker &amp;ndash; Kinematic. Оно помогает установить движок Docker в системе.&amp;nbsp; Kinematic автоматизирует установку движка, машины, виртуального блока backend и других компонентов docker.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Kinematic обладает превосходным графическим интерфейсом пользователя для управления контейнерами docker. Среди других функций Kinematic следует отметить возможность поиска образов, переключения между интерфейсом командной строки и графическим интерфейсом пользователя, управления портами, конфигурации переменных, журналов сред и т.д.&amp;nbsp; Docker - подходящий инструмент для создания изолированной среды.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Вы так же можете разворачивать контейнеры в блоке vargant, если не хотите использовать приложение с графическим интерфейсом.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Packer&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Если Вы относитесь к тем, кто работает с облачными виртуальными машинами, то этот инструмент для Вас.&amp;nbsp; Он автоматизирует создание образа для Вашего облачного провайдера. Также, конфигурации, написанные с Packer, являются cloud-агностическими.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Вы можете писать конфигурацию packer для создания образа для определенного стека приложения и использовать его с несколькими облачными провайдерами.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Кроме того, Вы можете использовать &amp;laquo;provisioners&amp;raquo; (Shell, Ansible, Chef и т.д.) для автоматизации конфигурации приложения в образах виртуальных машин.&lt;/p&gt;
&lt;h3 style="padding-left: 30px; text-align: justify;"&gt;&lt;strong&gt;Инструменты непрерывной интеграции &lt;/strong&gt;&lt;/h3&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Непрерывная интеграция больше не является процессом, которому следует разработчик. Когда доходит до практики DevOps, даже инфраструктурный код должен следовать практикам непрерывной интеграции.&amp;nbsp; Давайте рассмотрим некоторые решения с открытым исходным кодом для целей непрерывной интеграции.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Jenkins&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Jenkins - распространенный инструмент непрерывной интеграции с мощной поддержкой сообщества.&amp;nbsp; Просто установите и используйте для работы с проектами Java или .Net. Образы Docker доступны для большинства версий Jenkins.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Github Actions&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Если Ваш код на Github , то можете использовать&amp;nbsp; Github Actions для непрерывной интеграции, создавать определенные рабочие процессы для автоматизации процесса сборки и выпуска.&amp;nbsp; У него есть растущий список интеграций со всеми облачными инструментами и инструментами с открытым исходным кодом.&amp;nbsp;&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Travis CI&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Travis CI - облачная платформа для непрерывной интеграции.&amp;nbsp; Вы можете использовать ее для проектов с открытым исходным кодом.&amp;nbsp; Она совершенно бесплатна, а для непрерывной интеграции самостоятельная настройка не потребуется.&lt;/p&gt;
&lt;h3 style="padding-left: 30px; text-align: justify;"&gt;&lt;strong&gt;Системы контроля версий&lt;/strong&gt;&lt;/h3&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Лучшей практикой является передача даже одного файла сценария в систему контроля версиями.&amp;nbsp;&amp;nbsp; Инженеру DevOps необходимо следовать рекомендациям разработки и использовать системы контроля версиями для кода, который он пишет.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;GitHub&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Инструмент разработки является неполным без GitHub- службы размещения репозиториев.&amp;nbsp; Он предлагает контроль версий, функциональность SCM, функции совместной работы такие, как отслеживание ошибок, управление задачами и другое.&amp;nbsp; Он также предлагает функции социальных сетей, например, подписчики и каналы.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Разработчики могут получить доступ к публичным репозиториям и предоставить их исходный код.&amp;nbsp; Кроме того, будучи самым крупным репозиторием в мире, управление запросами и отслеживание проблем становится пустяковым делом.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Bitbucket&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Bitbucket - совместная система контроля версий, использующая Mercurial и Git. Разработчики могут получать доступ к безлимитным бесплатным частным репозиториям, управлять или делиться репозиториями, совместно работать над кодом и многое другое.&amp;nbsp; Bitbucket интегрирован с JIRA - инструментом управления проектом.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Gitlab&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Если Вам нужна настройка подобная Github, переходите в Gitlab. Настроив один раз, Вы можете использовать ее для размещения кода приложения. Если же Вам не нравится настраивать программное обеспечение, Вы можете использовать образ Gitlab docker для настройки одной строки.&lt;/p&gt;
&lt;h3 style="padding-left: 30px; text-align: justify;"&gt;&lt;strong&gt;Облачные службы&lt;/strong&gt;&lt;/h3&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Работа не всегда происходит на рабочих станциях.&amp;nbsp; Иногда возникает необходимость временной рабочей среды, которую можно разворачивать по требованию и сворачивать, если в ней нет необходимости.&amp;nbsp; Тогда в игру вступает облако.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;С помощью таких опций как AWS, DO, Lightsail разработчики могут настраивать собственный виртуальный частный сервер несколькими кликами и платить только за пропускную способность по часам.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;AWS&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;AWS предлагает мощное решение с виртуальными машинами и несколькими другими службами для разработки сайтов или приложений.&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;AWS - обязательное приложение для разработчиков, ищущих надежную инфраструктуру и недорогие хостинговые решения.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;DigitalOcean&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;DigitalOcean предлагает виртуальные машины с невероятно быстрой скоростью и потрясающими инструментами для разработчика.&amp;nbsp; Облачные экземпляры в DO, называемые каплями, могут быть развернуты в течение всего 55 секунд.&amp;nbsp; Интеллектуальные стратегии, недорогие решения и лучшие облачные предложения внесли ценный вклад в развитие рынка.&amp;nbsp;&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Lightsail&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Еще один отличный продукт от технологического гиганта Amazon - Lightsail - предлагает разработчикам возможность настройки собственного VPS всего в 3 клика.&amp;nbsp; Разработчики могут воспользоваться преимуществом AWS без необходимости изучения сложных сервисов.&amp;nbsp; Всю сложную работу сделает Lightsail - Вы можете сосредоточиться на важных задачах.&lt;/p&gt;
&lt;h3 style="padding-left: 30px; text-align: justify;"&gt;&lt;strong&gt;Инструменты взаимодействия/коммуникации&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Slack&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Slack - прекрасный инструмент для онлайн общения.&amp;nbsp; Он интегрирован со множеством приложений, такими как Google Calendar, Skype, Trello, GitHub, Jira и многое другое.&amp;nbsp; Если Вы в поисках инструмента для мозговых штурмов, общения и взаимодействия, Slack - то, что нужно.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Trello&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Trello - инструмент для управления проектами, в котором проекты размещаются на досках.&lt;/p&gt;
&lt;h4 style="padding-left: 30px; text-align: justify;"&gt;Asana&lt;/h4&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Asana - прекрасный инструмент, который помогает во взаимодействии с партнерами, в управлении проектами.&lt;/p&gt;
&lt;p style="padding-left: 30px; text-align: justify;"&gt;Пользуйтесь этими инструментами и будете успешны в работе.&lt;/p&gt;</description><pubDate>Fri, 30 Apr 2021 04:41:25 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Luchshie-druzya-DevOps-inzhenerov</guid></item><item><title>EXTENDED EVENTS: Обойти XML</title><link>http://www.spbdev.biz:80/blog/EXTENDED-EVENTS-Oboyti-XML</link><description>&lt;p style="text-align: justify;"&gt;Работать с XML&amp;nbsp; - сплошная боль.&amp;nbsp; Писать запросы против XML действительно трудно.&amp;nbsp; Если бы не существовало способов избежать XML, вряд ли кто-то выступал бы за&amp;nbsp; Extended Events. Давайте рассмотрим способы, позволяющие не использовать в работе XML.&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;&lt;strong&gt;Окно Live Data&amp;nbsp; &lt;/strong&gt;&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Концепция проста. Если кликните правой кнопкой мыши на любом сеансе Extended Events внутри SSMS, если это активный сеанс, увидите пункт меню: Watch Live Data. Кликнув на него, откроется окно Live Data. Здесь мы сталкиваемся с проблемой, не менее серьезной, чем XML. Вот результат при первом открытии:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="420" height="1024" alt="" src="/blog/Media/Default/Users/SpbDevBlog/1-1.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В верхней части экрана&amp;nbsp; расположены все события. В таком случае я собираю запросы через &lt;em&gt;sql_batch_completed and rpc_completed&lt;/em&gt;. Выбор любого события в верхней части экрана покажет детали этого события внизу экрана.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Extended Events - универсальное средство просмотра любого события. Но можно настроить и просмотр сеанса.&amp;nbsp; Более того, эта настройка сохраняется автоматически и будет использована повторно.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Итак, как же это работает? Два способа.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Первый: правой кнопкой мыши щелкните на деталях в любом из этих полей.&amp;nbsp; Откроется следующее меню&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="280" height="100" alt="" src="/blog/Media/Default/Users/SpbDevBlog/2-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Щелкните на Show Column in Table и это поле добавится на экране над деталями.&lt;/p&gt;
&lt;p&gt;Второй: правой клавишей мыши щелкните в верхней части, прямо в верхней части сетки. Вы получите меню, которое выглядит так:&lt;/p&gt;
&lt;p&gt;&lt;img width="329" height="233" alt="" src="/blog/Media/Default/Users/SpbDevBlog/3-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Щелкните на &amp;ldquo;Choose Columns&amp;hellip;&amp;rdquo; Откроется новое окно:&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="399" alt="" src="/blog/Media/Default/Users/SpbDevBlog/4-1.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Не будем вдаваться в детали, как с этим работать. Слева есть данные, собранные событиями, определенными в Вашем сеансе.&amp;nbsp; Переместите их вправо, чтобы создать собственное представление.&amp;nbsp; Например, вот представление, которое я использую чаще всего при просмотре данных производительности запросов:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="254" alt="" src="/blog/Media/Default/Users/SpbDevBlog/5-1.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Запрос виден как в качестве пакета, так и оператора, продолжительность, CPU, чтение, запись и все это в хорошем аккуратном формате.&amp;nbsp; Более того, даже после того, как Вы это сделаете, останется возможность щелкнуть на любую заданную строку и посмотреть детали.&amp;nbsp; Теперь Вы обладаете всеми видами дополнительной функциональности.&amp;nbsp; Вы можете искать эти столбцы, можете сортировать, группировать и агрегировать, настраивать фильтр данных по времени, или любому столбцу и значению.&amp;nbsp; Короче говоря, у Вас есть инструмент исследования данных, не прибегая к использованию XML.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Но это подходит для небольших фрагментов данных. В качестве альтернативы, файлы можно открывать напрямую. Можно настроить представление данных и затем повторно использовать эту настройку, не проводя дополнительной работы.&amp;nbsp; Вы даже можете сохранить её, передать коллегам или разместить на нескольких машинах.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;DBATools&lt;/strong&gt;&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Если вы до сих пор не сталкивались с DBATools, тогда Вас ждет приятная неожиданность. Это набор инструментов PowerShell, который полностью изменит способ администрирования и работы с SQL Server.&amp;nbsp; А его стоимость равна нулю.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;DBATools обладает функциональностью Extended Events уже многие годы.&amp;nbsp; И это не просто одна или две команды.&amp;nbsp; Целый ряд функций помогают работать и поддерживать Extended Events.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="338" height="1019" alt="" src="/blog/Media/Default/Users/SpbDevBlog/6-1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Теперь, используя&amp;nbsp; DBATools, вам не нужно пытаться понять XPath. Вместо этого, Вы можете запросить файл непосредственно в удобочитаемой форме. Более того, т.к. Вы уже в PowerShell, просто передайте файл в любой другой формат или расположение.&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Заключение&lt;/strong&gt;&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Используя эти два метода и ничего более, Вы можете легко обойти XML. Extended Events не сложны в использовании.&amp;nbsp; А даже очень просты.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;У всех новых функций в SQL Server есть&amp;nbsp; Extended Events, Trace Events вообще отсутствуют. База данных Azure SQL позволяет использовать только Extended Events. В них больше функциональности, а нагрузку они создают в разы меньше.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;</description><pubDate>Wed, 31 Mar 2021 07:53:56 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/EXTENDED-EVENTS-Oboyti-XML</guid></item><item><title>Код-ревью и DevOps</title><link>http://www.spbdev.biz:80/blog/code-review-and-devops</link><description>&lt;p style="text-align: justify;"&gt;На этот вопрос можно дать несколько&amp;nbsp; ответов. Давайте кратко рассмотрим их.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Система управления версиями&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Если Вы автоматизируете развертывания, наверняка у Вас есть код в системе управления версиями.&amp;nbsp; Итак, если необходимо провести код-ревью, система управления версиями - прекрасное место для старта.&amp;nbsp; Честно говоря, возможно, это наилучшее место.&amp;nbsp; Можно легко запустить отчет на выбранную базу данных и найти все изменения, произведенные с момента последнего ревью.&amp;nbsp; Независимо от того, проводите ли Вы ревью еженедельно, ежедневно или ежечасно, найти&amp;nbsp; изменения будет легко благодаря системе управления версиями. Но лучше всего, то, что можно наблюдать за изменениями по мере их возникновения - не нужно ждать окончания развертывания.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Более того, если Вы фиксируете скрипты изменений, используемые для развертывания в рабочей среде (кстати, отличная практика), то всегда можете просматривать эти скрипты, чтобы понять, что изменилось.&amp;nbsp; Да, это ревью по факту, но при этом отличный способ следить за тем, что происходит с серверами.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Непрерывная интеграция&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Вероятнее всего, если Вы автоматизируете развертывания, у Вас есть механизм начального тестирования, возможно, форма непрерывной интеграции.&amp;nbsp; Это первое место развертывания кода из системы управления версиями.&amp;nbsp; Это отличное место, чтобы увидеть происходящие изменения.&amp;nbsp; Кроме того, процесс CI скорее всего включает отчет об ошибках.&amp;nbsp; Это возможность поймать плохой код на ранних этапах процесса.&amp;nbsp; Здесь также возможно зафиксировать скрипты изменений, используемых для развертывания в среде CI.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Шаг ревью&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Просто добавьте шаг ревью в большинство инструментов DevOps. Сделайте одобрение частью процесса. Вы можете легко получить артефакт, созданный для развертывания, посмотреть код до того, как он попадет в продакшн и при этом у Вас будет полностью автоматизированное развертывание в производственной среде. Если же в организации требуются другие подтверждения, они могут быть также внедрены с помощью такого же метода.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Некоторые разработчики настаивают на ревью каждой строчки кода перед развертыванием: открывают сценарий из 10 000 строк, просматривают первые пару, подтверждают, что он компилируется и дело сделано! Часто, шаг код-ревью происходит из-за отсутствия другого тестирования, другого подтверждения кода перед развертыванием в продакшн Если же&amp;nbsp; есть настроенный процесс CI, среда тестирования, промежуточная среда,&amp;nbsp; они все тестируют развертывания. Если создано дополнительное автоматизированное тестирование, оно также подтверждает развертывание.&amp;nbsp; Вместо того чтобы полагаться на Mark I. опирайтесь на процесс, который сделает код-ревью.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;Заключение&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Используйте инструменты и методы, чтобы убедиться в правильном понимании происходящих&amp;nbsp; изменений.&amp;nbsp; Несмотря на стремление ускорить выпуск релизов, хочется быть уверенными в надежности.&amp;nbsp; Наличие этих процессов гарантирует безопасное развертывание и методы получения знаний о том, что развертывается, добавляет защиту нашим производственным средам.&lt;/p&gt;</description><pubDate>Wed, 31 Mar 2021 07:53:53 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/code-review-and-devops</guid></item><item><title>4 технологических тенденции, которые повлияют на аналитику данных в 2021 г</title><link>http://www.spbdev.biz:80/blog/4-tekhnologicheskikh-tendentsii-kotorye-povliyayut-na-analitiku-dannykh-v-2021</link><description>&lt;p style="text-align: justify;"&gt;Статус аналитики данных до 2021 года не был так высок как сегодня.&amp;nbsp; Столкнувшись с пандемией, правительства стран полагаются на углубленное статистическое моделирование для осмысления потока постоянно меняющихся показателей. Специалисты по обработке данных в этом процессе играют не последнюю роль: консультируют первых лиц компаний, стремящихся внедрить правильные политики в нужное время.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Важно понимать, получение выводов из данных - нечто новое.&amp;nbsp; За последние месяцы стремительное развитие сложных инструментов для анализа в режиме "реального времени", стало&amp;nbsp; тенденцией в развитии компаний. И пока предпосылок к ослаблению нет.&amp;nbsp; Развитие искусственного интеллекта и машинного обучения продолжит трансформировать способы проектирования, совместного использования и внедрения данных; помогут установить новые ориентиры в таких понятиях как доступность, скорость получения выводов,&amp;nbsp; диапазон применения, а также усиление роли в принятии решений.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В этом году четыре тенденции будут господствовать в области разработки:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;Расширенная аналитика &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Это следующий этап в аналитике данных. Веские причины, по которым расширенная аналитика вышла на первый план, определены еще в 2017 г. Помимо прочего, объем информации, доступный организациям, делает эффективную интерпретацию сложным процессом.&amp;nbsp; К 2025 г количество IoT соединений&amp;nbsp; достигнет 5 миллиардов по сравнению с 1,3 млрд в 2019 г. Кроме того, у выводов, полученных на основе данных, короткий срок годности.&amp;nbsp; Если информация не попала к лицу, принимающему решения, через небольшой промежуток времени их ценность равна нулю.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Машинное обучение и искусственный интеллект идеальны для автоматизации и ускорения&amp;nbsp; трудоемких участков работы специалиста по обработке данных.&amp;nbsp; Однако значение расширенной аналитики будет далеко выходить за рамки облегчения работы загруженных специалистов.&amp;nbsp;&amp;nbsp; Сделав сложные инструменты доступными для широкой аудитории, расширенная аналитика повысит возможности специалистов по обработке гражданских данных. Исполнителям работ будут предоставлены инструменты контроля, необходимые для более быстрого принятия решений.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;Непрерывный интеллектуальный анализ данных &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Стремительное развитие непрерывного интеллектуального анализа данных отражает скорость, с которой работают современные предприятия.&amp;nbsp; Чтобы принять правильное решение, нужно знать, что сейчас происходит.&amp;nbsp; Начиная с&amp;nbsp; 2021 г, большинство ответов будет поступать от непрерывного интеллектуального анализа данных.&amp;nbsp; Обрабатывая текущие и исторические данные, непрерывный интеллектуальный анализ гораздо чаще будет использоваться для автоматизации, чем для поддержки процесса принятия решения.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Инструменты, используемые непрерывным интеллектуальным анализом данных разнообразны.&amp;nbsp; Сюда входят расширенная аналитика, а также обработка потока событий, оптимизация, управление бизнес-правилами, машинное обучение. 2020 г дал понять, что подход "установил и забыл" уже не работает.&amp;nbsp; Меняются рынки, поведение, постоянно что-то происходит.&amp;nbsp;&amp;nbsp; Непрерывный интеллектуальный анализ укрепит позиции в 2021 г: он предоставляет инструменты, которые учатся сами по себе, постоянно корректируясь и совершенствуясь. Так же как и расширенная аналитика, непрерывный интеллектуальный анализ встроится в рабочие процессы, перестав быть привилегией специалистов по обработке данных.Расширенное управление данными,&amp;nbsp; Data Discovery, Каталоги данных. Это также станет&amp;nbsp; новостью в 2021 г. Опять же, это возможности машинного обучения и движки искусственного интеллекта, которые приводятся в действие.&amp;nbsp; В этом случае они будут использоваться для поиска и понимания данных и создания категорий управления корпоративной информацией, включая качество данных, управление метаданными, управление основными данными и интеграцию данных, а также системы управления базами данных (DMS), самонастраивающиеся.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;Автоматическое машинное обучение /Объяснимый искусственный интеллект&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Как упоминалось, в 2021 году произойдет ускоренный сдвиг в сторону автоматизации процесса принятия решений. Однако зачастую организациям все равно придется исследовать и обосновывать, как принимаются такие решения. Поэтому руководителям важно уметь создавать модели, которые можно интерпретировать и объяснять. Подход &amp;ldquo;черного ящика&amp;rdquo;, используемый некоторыми решениями, служит только для того, чтобы отгородиться от пользователей. Вместо этого аналитики все чаще будут искать ответственный, объяснимый и интерпретируемый искусственный интеллект. Эта прозрачность дает уверенность в результатах, &amp;nbsp;возможность специалистам по обработке данных учиться и расти вместе со своими системами. Кроме того, модели могут быть модифицированы и точно настроены в соответствии с постоянно меняющимися условиями окружающей среды. В 2021 году и последующие годы не должно быть необходимости выбирать между автоматизацией и демократизацией. При наличии правильных решений они будут идти рука об руку.&lt;/p&gt;</description><pubDate>Wed, 31 Mar 2021 07:53:49 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/4-tekhnologicheskikh-tendentsii-kotorye-povliyayut-na-analitiku-dannykh-v-2021</guid></item><item><title> 6 рекомендаций для успешного внедрения стратегии управления данными</title><link>http://www.spbdev.biz:80/blog/6-rekomendatsiy-dlya-uspeshnogo-vnedreniya-strategii-upravleniya-dannymi</link><description>&lt;p style="text-align: justify;"&gt;Управление данными - сложное поле деятельности, поэтому внедрение и поддержание стратегии сталкивается с рядом сложностей.&amp;nbsp; К счастью, тысячи, если не миллионы организаций используют управление данными для улучшения операционной деятельности, поэтому у Вас есть уникальная возможность учиться на чужих ошибках и успехах.&amp;nbsp;&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;1. Сфокусируйтесь на операционной модели&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Операционная модель, иногда называемая моделью активов, описывает как в организации определены роли, обязанности, бизнес-термины, области данных и т.д. Это влияет на рабочие процессы, функции, на то, как организация работает с данными.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Операционная модель - основа для любой программы управления данными.&amp;nbsp; Идея состоит в создании структуры управления предприятием.&amp;nbsp; В зависимости от организации, структуры могут быть:&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li&gt;Централизованными (все управление происходит центральным органом)&lt;/li&gt;
&lt;li&gt;Децентрализованным или федеративным (существует несколько групп полномочий)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style="text-align: justify;"&gt;&lt;strong&gt;Пример операционной модели:&lt;/strong&gt;&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Кросс-функциональная страховая компания, часто требуется сотрудничество между различными направлениями бизнеса, такими как финансы, продажи, маркетинг и ИТ.&amp;nbsp;&amp;nbsp; В каждом отделе есть свой представитель по управлению данными, бизнес-стюарды (собственники данных) и технические стюарды (собственник инфраструктуры, поддерживающей данные).&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Компания создала структуру управления корпоративными данными и сформировала совет по управлению данными, подотчетный директору по данным. Определение прав помогает социализировать программу и создавать интеллектуальную структуру для прорабатывания программ данных как единого целого.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Представители бизнеса и ИТ формируют различные группы и выстраивают структуру отчетности, часто называемую советом или комитетом по управлению данными. Совет обсуждает проблемные вопросы, связанные с данными, принимает решения и распространяет информацию по всей организации. Совет по управлению данными определяет правильные инструменты и технологии для поддержки стюардов, чтобы те, в сою очередь, могли выполнять свою работу эффективно.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;2. Определите области данных&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;После создания структуры управления данными следующая рекомендация - определение областей данных для каждого направления бизнеса. Наиболее популярные примеры: области данных клиентов, вендоров и продуктов. Каждая область содержит следующие артефакты:&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li&gt;Собственники данных&lt;/li&gt;
&lt;li&gt;Бизнес-глоссарий&lt;/li&gt;
&lt;li&gt;Словари данных&lt;/li&gt;
&lt;li&gt;Бизнес-процессы&lt;/li&gt;
&lt;li&gt;Каталоги данных&lt;/li&gt;
&lt;li&gt;Каталоги отчетов&lt;/li&gt;
&lt;li&gt;Показатели качества данных&lt;/li&gt;
&lt;li&gt;Системы и приложения&lt;/li&gt;
&lt;li&gt;Политики и стандарты&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: justify;"&gt;Обычно организации определяют области данных, когда сталкиваются с проблемами.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;&lt;strong&gt;Пример&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Это пример компании, предоставляющей финансовые услуги, которая преодолела проблемы с данными и следовала методу определения областей данных.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;У фирмы были трудности с доступом к данным, а ей хотелось получать больше информации о клиентах. Требования компании, связанные с этими бизнес-проблемами, включали:&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li&gt;Повысить уровень удовлетворенности клиента&lt;/li&gt;
&lt;li&gt;Контролировать проверку потребностей клиентов&lt;/li&gt;
&lt;li&gt;Увеличить объем дополнительных продаж&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: justify;"&gt;Данные были рассредоточены по разным системам и приложениям без определения владельца.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Фирма создала принадлежность путем определения ключевых заинтересованных сторон, бизнес-процессов и наборов данных, относящихся к предметной области клиентов, и установила контроль над ее жизненным циклом. Это дало пользователям данных ясное понимание, откуда приходят данные, кто их собственник, когда они изменяются и кто должен быть привлечен.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Это простая диаграмма для области данных "Клиент", демонстрирующая все стадии происхождения данных в области.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;3. Определите критические элементы данных в областях данных&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;На ранних этапах Вашей программы управления данными нет необходимости сосредотачиваться на всех артефактах сразу.&amp;nbsp; Важно определить критические для бизнеса.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Рассмотрим на примере технологической компании. Компания нуждалась в управлении данными для подтверждения отчетов клиентов и связанных с ними источников. На первой стадии внедрения компания определила только 10 наиболее важных отчетов и зафиксировала информацию о системах происхождения. Позже, инициатива была расширена, применив сертификационные требования и соответствующую исходную информацию для всех отчетов.&amp;nbsp; Проще говоря, отчет не сертифицируется, если собственники не могут показать его отслеживаемость в системе происхождения.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;4. Определите контрольные измерения&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Управление данными - это не разовый проект.&amp;nbsp; Это постоянная программа для принятия решений на основе данных и создания возможностей для бизнеса. Она готовит организацию к соблюдению бизнес-стандартов. В контрольные измерения входят следующие ключевые активности:&lt;/p&gt;
&lt;ol style="text-align: justify;"&gt;
&lt;li&gt;Определение автоматизированных рабочих процессов и пороговых значений для утверждения, эскалации, проверки и разрешения проблем.&lt;/li&gt;
&lt;li&gt;Применение процессов последовательности операций к структуре управления, области данных и критическим элементам&lt;/li&gt;
&lt;li&gt;Разработка отчетности по реализации программы&lt;/li&gt;
&lt;li&gt;Получение обратной связи с помощью автоматизированных процессов&lt;/li&gt;
&lt;li&gt;Последовательная коммуникация&lt;/li&gt;
&lt;/ol&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;5.&amp;nbsp;Эффективная коммуникация&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Одним из преимуществ управления данными является то, что оно помогает создать общий язык, ведь эффективная коммуникация&amp;nbsp; - лучший метод управления данными. Рассмотрим три сегмента коммуникации: вовлеченность, адаптация и принятие.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;&lt;strong&gt;Вовлеченность&lt;/strong&gt;&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Управление данными оказывает влияние на каждое подразделение организации, поэтому важно убедиться, что руководители понимают ценность стратегии.&amp;nbsp; Расскажите им, как управление данными поможет достичь стратегических целей, каковы риски и последствия, если они не будут участвовать.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;&lt;strong&gt;Адаптация&lt;/strong&gt;&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;К сожалению, не достаточно просто щелкнуть пальцами и всем сразу станут понятны тонкости управления данными; необходимо обучать процессам управления данными. Необходимо донесение ценности управления данными и информирование о том, как управление данными влияет на повседневную жизнь.&lt;/p&gt;
&lt;h4 style="text-align: justify;"&gt;&lt;strong&gt;Принятие&lt;/strong&gt;&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;И наконец, Вам необходимо последовательно и планомерно доносить информацию о ценности управления данными, чтобы руководители и пользователи могли применять методы и технологии управления данными. Вы можете сделать это с помощью:&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li&gt;Встраивания оповещений и уведомлений об управлении данными в ваши инструменты&lt;/li&gt;
&lt;li&gt;Проведения сессий обновлений&lt;/li&gt;
&lt;li&gt;Отчетности по показателям управления данными и прогрессу.&lt;/li&gt;
&lt;li&gt;Предоставления обновлений об изменениях политики&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style="text-align: justify;"&gt;6. Измеряйте свои цели с помощью метрик&lt;/h4&gt;
&lt;p style="text-align: justify;"&gt;Вашим командам необходимо оценивать прогресс программы управления данными и ее влияние на остальную организацию.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Эта рекомендация &amp;nbsp;является наиболее сложным, но важным элементом для обеспечения непрерывного совершенствования.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Первый шаг - понять и определить, как выглядит успех. Ваш успех не будет похож на успех других организаций.&amp;nbsp; Он будет зависеть от Ваших целей. Задайте вопрос себе и вашей команде&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li&gt;Как выглядит успешная программа управления данными?&lt;/li&gt;
&lt;li&gt;Что значит достичь Data Intelligence?&lt;/li&gt;
&lt;li&gt;Как мы узнаем, что достигли Data Intelligence?&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: justify;"&gt;Ответив на эти вопросы, Вы сможете определить цели и критерии оценки. Ключевые показатели производительности должны соотноситься с целями и стратегиями. Некоторые области для отслеживания&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li&gt;Разработка словаря данных и бизнес-глоссария - отслеживайте количество терминов и активов, которые Вы загружаете в систему.&lt;/li&gt;
&lt;li&gt;Доступ - отслеживайте, сколько времени требуется пользователям для получения необходимой информации.&lt;/li&gt;
&lt;li&gt;Принятие - определите, как много сотрудников используют технологию управления , как часто и как долго.&lt;/li&gt;
&lt;li&gt;Разрешение проблем - подсчитайте, сколько проблем, связанных с данными, регистрируется в вашей организации и оцените, насколько хорошо команда решает эти проблемы, как много и как долго.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Качество данных - контролируйте чистоту доступных данных и их соответствие целям.&lt;/li&gt;
&lt;li&gt;Соответствие политике - измерьте, в какой степени организация придерживается стандартов, установленных внешними и внутренними регуляторами.&lt;/li&gt;
&lt;li&gt;Повторное использование и масштабируемость &amp;ndash; ведите учет того, каким процессам ваша организация следует чаще всего и как они развиваются с течением времени.&lt;/li&gt;
&lt;li&gt;Финансовая рентабельность инвестиций&amp;nbsp;&amp;ndash; рассчитайте финансовое влияние управления данными на организацию&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp;&lt;/p&gt;</description><pubDate>Wed, 31 Mar 2021 07:53:44 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/6-rekomendatsiy-dlya-uspeshnogo-vnedreniya-strategii-upravleniya-dannymi</guid></item><item><title>Управление ресурсами Azure с помощью задач автоматизации</title><link>http://www.spbdev.biz:80/blog/Upravlenie-resursami-Azure-s-pomoshchyu-zadach-avtomatizatsii</link><description>&lt;p style="text-align: justify;"&gt;Существуют различные способы управления ресурсами в зависимости от потребностей.&amp;nbsp; С помощью задач автоматизации Azure предлагает простой способ управления ресурсом или группой ресурсов, используя шаблоны задач автоматизации.&amp;nbsp; Эти шаблоны зависят от ресурса. Например, для виртуальной машины Azure вы можете создать задачу автоматизации, которая включает или выключает виртуальную машину по заданному расписанию или отправляет отчет о стоимости ресурса. Это особенно полезно, если Вы пытаетесь снизить стоимость ваших виртуальных машин Azure.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Задача автоматизации - это фактически рабочий процесс, который на самом деле работает в службе Azure Logic Apps.&amp;nbsp; Задачи автоматизации в настоящее время находятся в предварительном просмотре и поддерживают отправку ежемесячной стоимости всех ресурсов Azure и специальных шаблонов для виртуальных машин, учетных записей Azure Storage и Azure Cosmos DB.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp;У Вас может возникнуть вопрос: в чем отличие задач автоматизации от Azure Automation? На сегодняшний день задача автоматизации может быть создана на уровне ресурсов, доступен просмотр истории выполнения задачи и изменения логики, лежащей в основе выполнения задачи, которая управляется Azure Logic Apps. Задачи автоматизации более простые и легкие, чем &lt;span&gt;Azure Automation&lt;/span&gt;.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;span&gt;Azure Automation&lt;/span&gt;&amp;nbsp;&amp;ndash; это облачная служба автоматизации и конфигурации, поддерживающая согласованность в управлении между средами Azure и другими средами. Эта служба включает в себя автоматизацию для процессов оркестровки с использованием перечней задач, управление конфигурацией с отслеживанием изменений, управление обновлением, гетерогенные функции; дает полный контроль в процессе развертывания, работы и вывода из эксплуатации рабочих процессов и ресурсов.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Как создать задачу автоматизации&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Создать задачу автоматизации очень просто.&amp;nbsp; На портале Azure найдите ресурс, которым хотите управлять, в меню ресурсов перейдите в раздел Автоматизация (Automation) и выберите Задачи (Tasks).&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="338" alt="" src="/blog/Media/Default/Users/SpbDevBlog/1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style="margin: 0cm; background: white;"&gt;&lt;span style="font-family: 'Helvetica',sans-serif; color: #333333;"&gt;Теперь Вы видите существующие задачи автоматизации или можете кликнуть на "Добавить" (Add) и добавить новую задачу из шаблона. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0cm; background: white;"&gt;&lt;img width="580" height="412" alt="" src="/blog/Media/Default/Users/SpbDevBlog/2.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Вы можете выбрать шаблон, который хотите использовать.&amp;nbsp; В разделе "Аутентификация" (Authentication) обозначены необходимые подключения к этой конкретной задаче.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="432" alt="" src="/blog/Media/Default/Users/SpbDevBlog/3.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;В разделе Конфигурация (Configuration) Вы можете добавить дополнительную информацию для задачи.&amp;nbsp; В этом примере виртуальная машина запускается каждый день в 10 утра.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="417" alt="" src="/blog/Media/Default/Users/SpbDevBlog/4.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;После того как задача автоматизация создана, ее можно увидеть в разделе Задачи (Tasks).&amp;nbsp; Здесь вы можете видеть задачи и просматривать выполнения, а также редактировать задачу.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="225" alt="" src="/blog/Media/Default/Users/SpbDevBlog/5.jpg" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p&gt;Вы можете провести оперативное редактирование для внесения простых изменений, но также можете открыть его в Logic Apps Designer.&lt;/p&gt;
&lt;p&gt;&lt;img width="580" height="224" alt="" src="/blog/Media/Default/Users/SpbDevBlog/6.jpg" /&gt;&lt;/p&gt;</description><pubDate>Wed, 24 Feb 2021 11:36:43 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Upravlenie-resursami-Azure-s-pomoshchyu-zadach-avtomatizatsii</guid></item><item><title>4 примера использования Azure Synapse</title><link>http://www.spbdev.biz:80/blog/4-primera-ispolzovaniya-Azure-Synapse</link><description>&lt;p style="text-align: justify;"&gt;Azure Synapse Analytics - это безграничный аналитический сервис, который создан для объедения двух миров больших данных и хранилищ данных в единую платформу.&amp;nbsp;&lt;br /&gt;Azure Synapse предоставляет полное готовое решение, предназначенное для ускорения процесса анализа и повышения гибкости бизнеса. Azure Synapse- единственная сквозная платформа, которая объединяет прием данных, аналитику больших данных и хранение данных; предлагает готовые варианты настройки для быстрого получения результатов, обеспечивает контроль и гибкость с точки зрения ценообразования, позволяя выбирать подходящий вариант для каждой рабочей нагрузки.&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;Пример №1&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Aggreko - мировой лидер по поставкам &amp;nbsp;электрогенераторов, систем контроля температуры и энергетических услуг, обеспечивающих резервное энергоснабжение и энергоснабжение в любое время и в любом месте, где это необходимо клиентам. Aggreko использует Azure Synapse для повышения операционной эффективности.&lt;br /&gt;Конвейер приема данных Aggreko был настроен на запуск каждые восемь часов, потому что для выполнения приема требовалось четыре часа. Кроме того, хранилище данных приходилось перестраивать каждый день из-за ограничений хранения. Это означало, что между поступлением данных и их доступностью для конвейеров задержка составляла в 8-24 часа.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="315" alt="" src="/blog/Media/Default/Users/SpbDevBlog/вар%201.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;С помощью Azure Synapse, Aggreko улучшила срок анализа данных, уменьшив сложность приема и увеличив скорость.&amp;nbsp;Время приема сократилось с четырех часов до менее чем пяти минут. Это, в свою очередь, означало, что для Aggreko данные теперь доступны для аналитических конвейеров почти в режиме реального времени (с задержкой менее пяти минут). Команда также подсчитала, что они сэкономили 30-40 процентов своего времени, которое было потрачено на решение технологических проблем в устаревших системах. Благодаря внедрению Azure Synapse данные теперь доступны для мгновенного изучения, а это означает, что у команды Aggreko есть больше времени, чтобы сосредоточиться на решении бизнес-задач.&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;Пример №2&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Clearsale, ведущая бразильская компания по обнаружению мошенничеств, использовала Azure Synapse для модернизации платформы оперативной аналитики данных.&amp;nbsp;Ежедневно компания&amp;nbsp;помогает клиентам проверять в среднем полмиллиона транзакций, используя аналитику больших данных с целью выявления подлогов по всему миру. Набор данных Clearsale удваивается каждые два года, при этом компания должна предоставлять услуги в течение нескольких секунд. Это требует большого уровня масштабируемости и производительности:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="435" alt="" src="/blog/Media/Default/Users/SpbDevBlog/вар%202.png" /&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;С помощью Azure Synapse Clearsale сократила время, необходимое для обучения новых моделей для улучшения процесса обнаружения мошенничества. Использование старой локальной платформы требовало 7 дней для приема, подготовки и обучения модели машинного обучения. С помощью Azure Synapse этот показатель сократился до менее чем шести часов. Такое улучшение повысило эффективность и снизило операционные расходы.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;Пример №3&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Компания GE Aviation - &amp;nbsp;мировой лидер в производстве авиационных двигателей и разработке авиационного программного обеспечения. Кроме этого GE&amp;nbsp; предоставляет расширенную аналитику данных авиакомпаниям по всему миру. Для каждого полета GE принимает серии данных за весь полет, которые включают в себя до 350 000 точек данных. Понятно, что анализ данных в таких объемах данных &amp;ndash; сложная задача. Чтобы решить эту проблему, команда выбрала платформу Azure Synapse:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="310" alt="" src="/blog/Media/Default/Users/SpbDevBlog/вар%203.png" /&gt; &lt;br /&gt;Использование Azure Synapse значительно упростило и ускорило создание сложных прогностических моделей машинного обучения. Встроенная интеграция между Microsoft Power BI и Azure Synapse оказалась чрезвычайно полезной. Теперь данные анализируются быстрее, и когда в отчетах Power BI обнаруживается аномалия, аналитики могут провести детализированный анализ и понять, почему произошли скачки и что необходимо предпринять для корректировки.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;Пример №4&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Представьте себе крупную транснациональную розничную компанию, у которой магазины в Австралии, Новой Зеландии и Японии. Здесь продаются потребительские товары, электроника и предметы личной гигиены. Аналитика данных нужна компании для создания представления о своих клиентах. Цель состоит в повышении качества обслуживания и увеличении прибыли. Чтобы добиться этого, команда по анализу данных приняла Azure Synapse в качестве подходящей платформы для достижения поставленной цели:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;img width="580" height="353" alt="" src="/blog/Media/Default/Users/SpbDevBlog/вар%204.png" /&gt; &lt;br /&gt;Azure Synapse позволила группе обработки данных объединить свои данные, разработчиков и бизнес-пользователей способами, которые ранее были невозможны. Azure Synapse упростила прием и обработку данных, организацию хранения все операционные и исторические данные, которые могут быть обновлены почти в режиме реального времени. Azure Synapse также упростила исследование и обнаружение данных без необходимости преобразования данных из одного формата в другой или перемещения их в другие системы.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В современных условиях у организаций должно быть четкое представление о результатах деятельности в режиме реального времени для постоянного развития.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Azure Synapse предлагает безграничный, унифицированный, мощный аналитический сервис, который позволяет компаниям начинать с малого и масштабироваться по мере необходимости. Вы платите только за то, что используете, и только тогда, когда вам это нужно.&lt;/p&gt;</description><pubDate>Wed, 17 Feb 2021 14:52:37 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/4-primera-ispolzovaniya-Azure-Synapse</guid></item><item><title>Использование облачного хранилища данных и важность управление данными</title><link>http://www.spbdev.biz:80/blog/Ispolzovanie-oblachnogo-khranilishcha-dannykh-i-vazhnost-upravlenie-dannymi</link><description>&lt;p style="text-align: justify;"&gt;Облаку присущи как операционные, так и конкурентные преимущества, поэтому инициативы в области цифровой трансформации входят в число важных в процессе обработки данных.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Из-за увеличения числа внутренних и внешних нарушений, организациям необходимо согласовывать работы по цифровой трансформации и миграции с другими стратегическими требованиями (например, соблюдение Общего регламента по защите персональных данных).&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Сегодня умение ориентироваться в пост-ковидном мире,&amp;nbsp; который заставляет организации становиться гибкими, бережливыми и сосредоточенными на результатах, позволяющих бизнесу не только выжить, но и процветать в новой действительности.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Однако облачная миграция это не только стратегия "lift and shift." Обычно, когда организации переходят из локальной среды в облачную, они преобразуют две различные технологии.&amp;nbsp; Также следует стоит обратить внимание на проблемы, связанные с данными.&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;&lt;em&gt;Бюджет и затраты&lt;/em&gt;&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Для 47% компания главная причина миграции в облако - оптимизация расходов. Однако, облачные миграции могут быть дорогостоящими; затраты возрастают по мере увеличения времени миграции.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Компании нечасто выделяют соответствующий бюджет на технологию миграции.&amp;nbsp; В 2020 г организации превысили бюджет на публичные облака в среднем на 23%.&amp;nbsp; Это связано с отсутствием планирования, приводящим к длительной и затяжной миграции и опрометчивым решениям по продукту.&amp;nbsp; Кроме того,&amp;nbsp; ручные миграции занимают больше времени и стоят гораздо дороже, чем автоматизированные.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;В разрезе бюджета и затрат, автоматизированные инструменты, сканирующие репозитории в среде, помогают добавить структуру и бизнес-контекст: где находится, кто может получить доступ, и т.д. в момент трансформации устаревших структур.&amp;nbsp; Новые структуры обеспечат новые возможности для данных и бизнес-процессов.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Автоматизированные инструменты помогут снизить риски и расходы, а также сократить время на реализацию проекта. Автоматизированное программное обеспечение работает с каталогизацией данных, локализует, моделирует и управляет облачными массивами данных.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Инструменты для планирования и выполнения облачных миграций несложно найти.&amp;nbsp;Их предлагают крупные облачные провайдеры; они способны упростить миграцию на платформу провайдера.&amp;nbsp; Но независимый от технологий подход к таким инструментам повышает ценность проектов миграции в облако.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Инструменты, предоставляемые поставщиками, ведут клиентов в их среду.&amp;nbsp; Независимые же инструменты помогают понять, какая облачная среда подходит для организаций.&amp;nbsp; Их цель - определить облачную платформу и стратегию, которые принесут наибольшую пользу после определения бюджета и требований к функциям.&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;&lt;em&gt;Институциональная память&lt;/em&gt;&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Институциональная память - это другое препятствие, с которым сталкиваются компании при изучении облачных миграций. Покидая компанию, люди уносят с собой понимание того, как&amp;nbsp; и почему осуществлялся порядок действий.&amp;nbsp; Поэтому Вы можете не знать, какие данные есть и как их использовать. Проблема возникает, когда приходит время миграции; необходимо понимать, что есть, как это используется, в чем ценность и что требуется перенести. В противном случае будут потрачены время и деньги на миграцию данных, а в итоге обнаружится, что ими не пользовались несколько лет и необходимости в их переносе не было.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Кроме того, если Вы планируете использовать мультиоблачный подход, важно убедиться, что используемые облака совместимы.&amp;nbsp; Только у 24% ИТ - компаний высокая степень совместимости между облачными средами. Это означает, что более 3/4 компании страдает от неэффективных облачных настроек и отсутствия возможности анализировать данные из нескольких облачных сред.&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;&lt;em&gt;Управление данными. &lt;/em&gt;&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Миграция данных в облако - это только половина истории; другая часть - управление ими.&amp;nbsp; Ваши массивы данных должны быть доступны для использования нужными людьми для правильных целей для максимальной безопасности, качества и ценности.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Около 60% предприятий беспокоятся о соблюдении нормативно-правового соответствия, выполнении требований облачных служб, об управлении.&amp;nbsp; Сложность заключается в создании надлежащего процесса управления данными, при этом избегая риска и извлекая как можно больше из этих данных.&amp;nbsp;&amp;nbsp; Более 3/4 (79%) компаний ищут наиболее эффективный вариант встроенных средств безопасности и управления данными, которые размещаются в облаке.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Миграция дает возможность не просто переносить данные такими как есть, но и производить стратегические изменения.&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;К сожалению, 72% компаний заявляют, что решение о том, какие рабочие нагрузки необходимо перенести в облако - один из барьеров на пути внедрения облачных технологий.&amp;nbsp; Однако облачная миграция - не конечная точка; это всего лишь следующий шаг, чтобы сделать бизнес гибким в долгосрочной перспективе. Определение, какие массивы данных необходимо перенести может помочь подготовиться к росту.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;h3 style="text-align: justify;"&gt;&lt;em&gt;Автоматизированная облачная миграция и управление данными.&lt;/em&gt;&lt;/h3&gt;
&lt;p style="text-align: justify;"&gt;Описанные выше сложности облачной миграции могут показаться пугающими, особенно организациям, которые накапливают и управляют огромным количеством данных.&amp;nbsp; Когда компании сталкиваются с ручной, громоздкой работой, касающейся бизнес-процессов, ИТ-инфраструктуры, и т.д., они часто обращаются к автоматизации.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Автоматизированные программные средства могут помочь в планировании и тяжелом подъеме облачных миграций.&amp;nbsp;&amp;nbsp; Они должны учитываться при выборе платформ, прогнозировании расходов, понимании ценности данных, рассматриваемых для миграции.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Автоматизация -&amp;nbsp; критический фактор для инструментов облачной миграции и управления данными.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Ключевые преимущества:&lt;/p&gt;
&lt;ul style="text-align: justify;"&gt;
&lt;li style="text-align: justify;"&gt;Снижение затрат: автоматические инструменты сканируют репозитории в вашей среде и добавляют структуру и контекст в трансформации устаревших структур.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Сокращение рисков: автоматизированные инструменты сокращают риски, расходы и время на достижение желаемого результата.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Платформенно-независимый подход повышает значение проектов облачной миграции.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Любое облако к любому облаку: автоматический сбор абстрактных сущностей данных упростит передачу информации на другую облачную платформу или технологию, если или когда, вы снова решите осуществить миграцию.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Сохранение институциональной памяти: сбор и сохранение институциональных знаний вокруг данных и обеспечение прозрачности.&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;Непрерывное управление данными: автоматизация помогает ИТ-компаниям решать проблемы управления данными во время облачной миграции, а затем на протяжении жизненного цикла данных и минимизирует вмешательство человека.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: justify;"&gt;Любая среда и данные уникальны.&amp;nbsp; Поэтому первый шаг в работе - оценить стратегию облачной миграции.&amp;nbsp; Затем составляется дорожная карта автоматизации и разрабатываются стыковочные пакеты &amp;laquo;умных данных&amp;raquo;, чтобы помочь ИТ-службам достичь перспективного состояния архитектуры, включая ускорение приема данных и преобразование ETL.&lt;/p&gt;</description><pubDate>Wed, 10 Feb 2021 12:02:32 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Ispolzovanie-oblachnogo-khranilishcha-dannykh-i-vazhnost-upravlenie-dannymi</guid></item><item><title>Безболезненный процесс миграции: что нужно знать</title><link>http://www.spbdev.biz:80/blog/Bezboleznennyy-protsess-migratsii-chto-nuzhno-znat</link><description>&lt;p style="text-align: justify;"&gt;Вы готовы переехать в облако, но не знаете, с чего начать? Тогда эта статья то, что нужно. Здесь будут даны пять советов, в основе которых лежит опыт работы с клиентами по совершенствованию технологии миграции.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;Совет №1:&lt;/strong&gt;&lt;strong&gt; Важно знать, зачем нужна миграция в облако&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Убедитесь, что все вокруг тоже в курсе. Обычно миграция не происходит ради самой миграции. Так почему же вы пошли на это?&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Необходимость снижения эксплуатационных расходов?&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Или увеличения скорости анализа?&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;От Вас требуется соответствие новым стандартам безопасности? Каждая организация уникальна, поэтому миграция - это стратегический или культурный сдвиг.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;Совет №2: Проведите аудит текущих активов. &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Некоторые организации ведут текущий учет технических активов и их использования. Эти инструменты будут не лишними в процессе миграции технологий: так Вы знаете, что есть, кто использует и как часто.&amp;nbsp; Аудит также приводит в порядок информацию, разбросанную по множеству документов и спецификаций, и упрощает выполнение текущих и будущих бизнес-требований.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Если вы не делали подобное раньше, а сейчас задумались о том, как начать, создайте типовые варианты использования.&amp;nbsp; Вариант использования - аналитический метод и точка соприкосновения бизнес-пользователей и технических специалистов, которая фиксирует взаимодействие пользователя с технологией.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Документирование вариантов использования включает:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;- Определение и описание бизнес-процесса&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;- Определение пользователей или ролей, которые используют технологию&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;- Обсуждение входных условий, основного потока, потоков исключений, и постусловий, определенных для каждого варианта использования.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Вы можете думать о вариантах использования как об инструменте, который позволяет задавать вопросы, раскрывающие проблемы в понимании и требованиях.&amp;nbsp; Информация, собранная в ходе этого процесса, фундаментальна; она будет использоваться в словаре данных, в диаграммах "сущность-связь"&amp;nbsp; и графических схемах программ для учета и документирования других текущих ресурсов.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;Совет №3: Используйте преимущества перехода&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Переходы, включая миграцию технологий, предоставляют возможности улучшения бизнес-процессов и результатов.&amp;nbsp; В Совете №2 мы рассмотрели момент ознакомления с текущими вариантами использования и ресурсами.&amp;nbsp; А теперь, подумайте, как можно улучшить их для максимальной поддержки цели миграции.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Пришло ли время перейти от транзакционной отчетности к аналитическим выводам?&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Нужна ли Вам эластичная масштабируемость и высокое время задержки в сравнении с текущим решением?&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Можете ли Вы объединить и параметризовать ресурсы для повышения их ценности и охвата?&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Какая техника миграции наилучшим образом оптимизирует приложения для достижения бизнес-целей?&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;Совет №4: У Вас должен быть процесс содержательного проектирования&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Важный компонент вовлечения заинтересованных сторон - включение в проектирование процесса миграции.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Содержательное проектирование дает повышенные возможности для каждого. Набор инструментов и методология содержательного проектирования Microsoft - удачное место для старта, которое фокусируется на 3 принципах:&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Выявить исключения&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Определить для одного, применить для многих.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Обучение на разнообразии&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;&lt;em&gt;&lt;strong&gt;Совет №5: Начинайте с малого&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Обязательства, коммуникация и размеры проекта не означают, что Вам необходимо прикладывать чрезмерные усилия по развертыванию с самого начала.&amp;nbsp; Лучший способ проведения эффективных изменения - начать с малого и развивать коллектив. Определите инициативу или приоритет и начините с этого.&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Дайте коллективу увидеть и понять воздействие маленькой победы и ее влияние на "почему ".&lt;/p&gt;
&lt;p style="text-align: justify;"&gt;Философия - думай масштабно, но начинай с малого - помогает доносить ценность изменений для всей организации.&lt;/p&gt;</description><pubDate>Mon, 01 Feb 2021 06:52:00 GMT</pubDate><guid isPermaLink="true">http://www.spbdev.biz:80/blog/Bezboleznennyy-protsess-migratsii-chto-nuzhno-znat</guid></item></channel></rss>