{"id":25373,"date":"2023-11-07T05:00:00","date_gmt":"2023-11-07T04:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=25373"},"modified":"2024-07-22T14:26:15","modified_gmt":"2024-07-22T12:26:15","slug":"sql-trigger-ktory-wywoluje-metode-w-net-service-broker","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/sql-trigger-ktory-wywoluje-metode-w-net-service-broker\/","title":{"rendered":"SQL Trigger, kt\u00f3ry wywo\u0142uje metod\u0119 w .NET \u2013 Service Broker"},"content":{"rendered":"\n<p>Mechanizm Service Broker w systemie zarz\u0105dzania baz\u0105 danych Microsoft SQL Server (MS SQL) stanowi zaawansowane narz\u0119dzie umo\u017cliwiaj\u0105ce asynchroniczn\u0105 komunikacj\u0119 mi\u0119dzy r\u00f3\u017cnymi bazami danych lub aplikacjami w ramach tej samej bazy danych. Zosta\u0142 opracowany i wdro\u017cony w 2005 roku w celu wspierania zada\u0144 zwi\u0105zanych z przetwarzaniem wiadomo\u015bci, zarz\u0105dzaniem kolejkami komunikat\u00f3w oraz zapewnianiem niezawodno\u015bci dostarczania komunikat\u00f3w.<\/p>\n\n\n\n<p>Service Broker, kt\u00f3ry przybli\u017c\u0119 w niniejszym artykule, stanowi integraln\u0105 cz\u0119\u015b\u0107 systemu MS SQL, umo\u017cliwiaj\u0105c przekazywanie informacji do zewn\u0119trznych odbiorc\u00f3w o zmianach zachodz\u0105cych w bazie danych, takich jak dodanie, usuni\u0119cie lub modyfikacja rekord\u00f3w. Jego funkcjonalno\u015b\u0107 umo\u017cliwia uruchamianie asynchronicznych dzia\u0142a\u0144, podobnie jak w przypadku trigger\u00f3w, co sprawia, \u017ce <strong>jest szczeg\u00f3lnie u\u017cyteczny<\/strong> w wywo\u0142ywaniu metod asynchronicznych napisanych w technologii .NET po zmianach w bazie danych MS SQL.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Potrzeba biznesowa<\/strong><\/h2>\n\n\n\n<p>W \u015brodowisku, w kt\u00f3rym pracuj\u0119 wraz z zespo\u0142em, mamy do czynienia z fabryk\u0105, gdzie poszczeg\u00f3lne maszyny uczestnicz\u0105ce w procesie produkcji komunikuj\u0105 si\u0119 ze sob\u0105 poprzez baz\u0119 danych MSSQL. Urz\u0105dzenia te potrafi\u0105 w spos\u00f3b autonomiczny zapisywa\u0107 informacje do tabeli, aby oznaczy\u0107 rozpocz\u0119cie lub zako\u0144czenie produkcji konkretnego elementu.<\/p>\n\n\n\n<p>Naszym zadaniem by\u0142o przetwarzanie tych wpis\u00f3w w tabeli, wykonanie okre\u015blonych oblicze\u0144 i wprowadzenie odpowiednich danych do tabel w innej bazie danych. Ten temat by\u0142 kluczowy z perspektywy biznesowej, a op\u00f3\u017anienia w jego realizacji nie mog\u0142y zosta\u0107 zaakceptowane. Wcze\u015bniej pr\u00f3bowali\u015bmy rozwi\u0105zywa\u0107 podobne problemy, okresowo sprawdzaj\u0105c, czy pojawi\u0142y si\u0119 nowe wpisy w bazie danych i uruchamiaj\u0105c wtedy ca\u0142\u0105 procedur\u0119 przetwarzania. Jednak\u017ce taka <strong>metoda prowadzi\u0142a do op\u00f3\u017anie\u0144<\/strong>, nieaprobowanych przez naszego klienta.<\/p>\n\n\n\n<p>W tym kontek\u015bcie klient wyra\u017anie za\u017c\u0105da\u0142, aby <strong>ca\u0142a logika biznesowa by\u0142a realizowana natychmiast<\/strong> po pojawieniu si\u0119 nowego rekordu w bazie danych MSSQL. Wskazano, \u017ce ca\u0142e przetwarzanie danych musi by\u0107 realizowane wewn\u0105trz bazy danych <strong>przy u\u017cyciu mechanizm\u00f3w takich jak triggery, procedury i funkcje.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Alternatywne rozwi\u0105zanie<\/strong><\/h3>\n\n\n\n<p>Z naszej perspektywy rozwi\u0105zanie zaproponowane przez klienta jawi\u0142o si\u0119 jako wyj\u0105tkowo skomplikowane i trudne do zarz\u0105dzania. W rezultacie podj\u0119li\u015bmy decyzj\u0119 o poszukiwaniu alternatywnego rozwi\u0105zania, kt\u00f3re umo\u017cliwi\u0142oby nam spe\u0142nienie wymaga\u0144 biznesowych w <strong>bardziej efektywny i prostszy w zarz\u0105dzaniu spos\u00f3b.<\/strong><\/p>\n\n\n\n<p>Nasze poszukiwania doprowadzi\u0142y nas do Service Brokera, kt\u00f3ry okaza\u0142 si\u0119 idealnym narz\u0119dziem do obs\u0142ugi takiej sytuacji. Dzi\u0119ki niemu mogli\u015bmy zautomatyzowa\u0107 przetwarzanie danych w spos\u00f3b niezawodny i efektywny, a jednocze\u015bnie zachowa\u0107 kontrol\u0119 nad naszym kodem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Przyk\u0142adowe uruchomienie komunikacji w paru prostych krokach<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Konfiguracja Service Brokera<\/strong><\/h3>\n\n\n\n<p>Na funkcjonalno\u015b\u0107 ServiceBrokera sk\u0142ada si\u0119 cz\u0119\u015b\u0107 bazodanowa (nadawcza) oraz cz\u0119\u015b\u0107 programowa (odbiorcza), kt\u00f3rej zadaniem jest przetworzenie przychodz\u0105cego zdarzenia o zmianie.<\/p>\n\n\n\n<p>W bazie danych TestDB utworzona zosta\u0142a tabela TestTable o strukturze pokazanej poni\u017cej:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/11\/Obraz1.png\"><img decoding=\"async\" width=\"390\" height=\"73\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/11\/Obraz1.png\" alt=\"Tabela TestTable w Service Brookerze\" class=\"wp-image-25374\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/11\/Obraz1.png 390w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/11\/Obraz1-300x56.png 300w\" sizes=\"(max-width: 390px) 100vw, 390px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 1 Tabela TestTable w Service Brookerze<\/figcaption><\/figure>\n\n\n\n<p>W pierwszym korku nale\u017cy uruchomi\u0107 funkcjonalno\u015b\u0107 Service Broker-a na danej bazie:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nALTER DATABASE TestDB SET ENABLE_BROKER;\n<\/pre><\/div>\n\n\n<p>Nast\u0119pnie nale\u017cy utworzy\u0107 kolejk\u0119 i us\u0142ug\u0119 Service Brokera:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\n-- Tworzenie kolejki\nCREATE QUEUE MyQueue;\n\n-- Tworzenie us\u0142ugi\nCREATE SERVICE MyService\nON QUEUE MyQueue (&#x5B;DEFAULT]);\n<\/pre><\/div>\n\n\n<p>Ostatnim krokiem po stronie nadawcy jest wygenerowanie zdarzenia informuj\u0105cego o zmianie na bazie. W naszym przypadku zdarzenie ma wyst\u0105pi\u0107 po dodaniu wiersza do tabeli. W tym celu nale\u017cy u\u017cy\u0107 polecenia SEND, aby wys\u0142a\u0107 wiadomo\u015b\u0107 do kolejki. Najlepiej zrealizowa\u0107 to triggerem:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nCREATE OR ALTER TRIGGER insertNewData  ON dbo.TestTable\n   AFTER insert  \nAS   \nBEGIN  \n    declare @newId int  \n\tdeclare @dialog_handle UNIQUEIDENTIFIER\n    SET NOCOUNT ON;  \n    SELECT @newId = Id from inserted  \n\t\n\tDECLARE @message_body NVARCHAR(MAX);\n\tSET @message_body = &#039;New data id: &#039; + cast( @newId as varchar(10)); -- Mo\u017cesz dostosowa\u0107 dane do przetworzenia\n\n\tset @dialog_handle = NEWID()\n\tBEGIN DIALOG CONVERSATION @dialog_handle\n\tFROM SERVICE MyService\n\tTO SERVICE &#039;MyService&#039;\n\tON CONTRACT &#x5B;DEFAULT]\n\tWITH ENCRYPTION = OFF;\n\n\tSEND ON CONVERSATION @dialog_handle MESSAGE TYPE &#x5B;DEFAULT] (@message_body);\n\n   END CONVERSATION @dialog_handle\nEND  \nGO\n<\/pre><\/div>\n\n\n<p>W powy\u017cszym triggerze wyr\u00f3\u017cniamy 3 kluczowe polecenia:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>BEGIN DIALOG CONVERSATION \u2013 rozpoczyna nowy dialog, kt\u00f3ry jest jednostk\u0105 komunikacji mi\u0119dzy dwiema us\u0142ugami lub aplikacjami. To polecenie jest u\u017cywane do rozpocz\u0119cia dialogu przed wys\u0142aniem wiadomo\u015bci.<\/li>\n\n\n\n<li>SEND ON CONVERSATION \u2013 s\u0142u\u017cy do wysy\u0142ania wiadomo\u015bci w ramach dialogu do docelowej us\u0142ugi.<\/li>\n\n\n\n<li>END CONVERSATION \u2013 zamyka dialog, co oznacza zako\u0144czenie komunikacji mi\u0119dzy us\u0142ugami.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Cz\u0119\u015b\u0107 programowa (odbiorcza) zaimplementowana w .NET<\/strong><\/h3>\n\n\n\n<p>W pierwszej kolejno\u015bci nale\u017cy nawi\u0105za\u0107 po\u0142\u0105czenie z baz\u0105 danych. Najpro\u015bciej zrobi\u0107 to poprzez zaimportowanie biblioteki System.Data.SqlClient.<\/p>\n\n\n\n<p>Poni\u017cej znajduje si\u0119 przyk\u0142adowy kod, kt\u00f3ry b\u0119dzie monitorowa\u0107 kolejk\u0119 i reagowa\u0107 na nowe wiadomo\u015bci:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nusing System;\nusing System.Data.SqlClient;\n\nclass Program\n{\n    static void Main()\n    {\n        string connectionString = @&quot;data source=localhost;initial catalog=TestDB;persist security info=True;Integrated Security=SSPI;&quot;;\n        using (SqlConnection connection = new SqlConnection(connectionString))\n        {\n            connection.Open();\n            using (SqlCommand command = new SqlCommand(&quot;WAITFOR (RECEIVE TOP(1) CAST(message_body AS NVARCHAR(MAX)) FROM MyQueue)&quot;, connection))\n            {\n                command.CommandTimeout = 0; \/\/ Czekaj na wiadomo\u015b\u0107 bez limitu czasu\n                while (true)\n                {\n                    using (SqlDataReader reader = command.ExecuteReader())\n                    {\n                        if (reader.Read() &amp;&amp; !reader.IsDBNull(0))\n                        {\n                            \/\/ Tutaj mo\u017cna przetwarza\u0107 otrzyman\u0105 wiadomo\u015b\u0107\n                            string messageBody = reader.GetString(0);\n                            Console.WriteLine(&quot;Received message: &quot; + messageBody);\n\n                            \/\/ Wywo\u0142aj asynchroniczne dzia\u0142anie lub inne operacje\n                            \/\/ Przyk\u0142ad: CallAsyncOperation(messageBody);\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n<\/pre><\/div>\n\n\n<p>Powy\u017cszy kod nie wymaga obszernego komentarza, jednak\u017ce nale\u017cy <strong>zwr\u00f3ci\u0107 uwag\u0119 na dwa aspekty<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>kolejk\u0119 MyQueue odpytujemy poleceniem WAITFOR,<\/li>\n\n\n\n<li>Pprogram zatrzymuje swoje dzia\u0142anie na poleceniu command.ExecuteReader() i oczekuje, a\u017c nowa wiadomo\u015b\u0107 pojawi si\u0119 w kolejce. Dzi\u0119ki zastawaniu while(true) po przetworzeniu komunikatu z kolejki program b\u0119dzie oczekiwa\u0107 na kolejny.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>ServiceBrokerListener \u2013 gotowe rozwi\u0105zania w .NET<\/strong><\/h2>\n\n\n\n<p>Podczas poszukiwa\u0144 gotowego rozwi\u0105zania do wykorzystania w projekcie natrafili\u015bmy na <strong>bibliotek\u0119 o nazwie ServiceBrokerListener<\/strong>, kt\u00f3ra upraszcza proces obs\u0142ugi Service Brokera, zapewniaj\u0105c gotowe mechanizmy do tworzenia kolejek, dodawania us\u0142ug i kontrakt\u00f3w, a tak\u017ce instaluje niezb\u0119dne triggery na monitorowanych tabelach w bazie danych.<\/p>\n\n\n\n<p>Niezwykle praktycznym elementem ServiceBrokerListener jest obs\u0142uga b\u0142\u0119d\u00f3w, co czyni go jeszcze bardziej wszechstronnym narz\u0119dziem. <strong>Z naszego do\u015bwiadczenia<\/strong> wynika, \u017ce najwygodniej jest korzysta\u0107 z tej biblioteki, jednak\u017ce tworz\u0105c w\u0142asn\u0105 solucj\u0119 i projekt, a nast\u0119pnie generuj\u0105c niestandardow\u0105 DLL na podstawie kodu \u017ar\u00f3d\u0142owego biblioteki. Dzi\u0119ki temu mamy <strong>pe\u0142n\u0105 kontrol\u0119 nad bibliotek\u0105<\/strong> i mo\u017cemy dostosowa\u0107 j\u0105 do naszych potrzeb.<\/p>\n\n\n\n<p>Jak ju\u017c wspomnia\u0142em, biblioteka ServiceBrokerListener podczas inicjalizacji tworzy wszystkie komponenty potrzebne do komunikacji (triggery, kolejki, kontrakty etc.). Kontroluje r\u00f3wnie\u017c proces destrukcji tych komponent\u00f3w. <strong>W trakcie prac nad zadaniem<\/strong> z wykorzystaniem biblioteki zaobserwowali\u015bmy, \u017ce w przypadku wyst\u0105pienia nieoczekiwanego wyj\u0105tku w aplikacji i jej nag\u0142ego zamkni\u0119cia komponenty utworzone na bazie nie s\u0105 zniszczone. Je\u015bli trigger dodawany na pocz\u0105tku dzia\u0142ania aplikacji nie zostanie usuni\u0119ty, operacja MERGE na danej tabeli staje si\u0119 niemo\u017cliwa.<\/p>\n\n\n\n<p>Biblioteka ServiceBrokerListener wraz z kodem \u017ar\u00f3d\u0142owym <a href=\"https:\/\/github.com\/dyatchenko\/ServiceBrokerListener\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >jest dost\u0119pna na platformie GitHub<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Podsumowanie<\/strong><\/h2>\n\n\n\n<p>W artykule opisa\u0142em tylko jedno z wielu mo\u017cliwych zastosowa\u0144 Service Brokera. Mo\u017ce on by\u0107 u\u017cywany r\u00f3wnie\u017c do innych zada\u0144, takich jak:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Przetwarzanie zada\u0144 asynchronicznych \u2013 Service Broker umo\u017cliwia asynchroniczn\u0105 komunikacj\u0119 mi\u0119dzy r\u00f3\u017cnymi us\u0142ugami lub aplikacjami w bazie danych. Jest cz\u0119sto u\u017cywany do przetwarzania zada\u0144 asynchronicznych, takich jak przetwarzanie zam\u00f3wie\u0144, generowanie raport\u00f3w lub obs\u0142uga zdarze\u0144 systemowych.<\/li>\n\n\n\n<li>Synchronizacja danych \u2013 Service Broker mo\u017ce by\u0107 wykorzystywany do synchronizacji danych mi\u0119dzy r\u00f3\u017cnymi bazami danych, np., mo\u017cna go u\u017cy\u0107 do replikacji danych mi\u0119dzy lokalnymi i zdalnymi serwerami.<\/li>\n\n\n\n<li>Komunikacja mi\u0119dzy mikrous\u0142ugami \u2013 w architekturze mikrous\u0142ugowej (Microservices) Service Broker mo\u017ce by\u0107 u\u017cywany do komunikacji mi\u0119dzy r\u00f3\u017cnymi mikrous\u0142ugami, umo\u017cliwiaj\u0105c im wsp\u00f3\u0142prac\u0119 i wymian\u0119 informacji.<\/li>\n\n\n\n<li>Monitorowanie i zarz\u0105dzanie zadaniami \u2013 dzi\u0119ki Service Broker mo\u017cna wysy\u0142a\u0107 do kolejki wiadomo\u015bci, kt\u00f3re zawieraj\u0105 informacje o zadaniach do wykonania, a nast\u0119pnie przetwarza\u0107 te zadania asynchronicznie.<\/li>\n<\/ul>\n\n\n\n<p>Z powy\u017cszych powod\u00f3w uwa\u017cam, \u017ce narz\u0119dzie jest warte lepszego poznania i wykorzystania.<\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;25373&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;11&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;4.7&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;4.7\\\/5 ( votes: 11)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;SQL Trigger, kt\u00f3ry wywo\u0142uje metod\u0119 w .NET \u2013 Service Broker&quot;,&quot;width&quot;:&quot;130.8&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 130.8px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            4.7\/5 ( votes: 11)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Mechanizm Service Broker w systemie zarz\u0105dzania baz\u0105 danych Microsoft SQL Server (MS SQL) stanowi zaawansowane narz\u0119dzie umo\u017cliwiaj\u0105ce asynchroniczn\u0105 komunikacj\u0119 mi\u0119dzy &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/sql-trigger-ktory-wywoluje-metode-w-net-service-broker\/\">Continued<\/a><\/p>\n","protected":false},"author":581,"featured_media":25383,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[2427,1829,1546,272,1007],"class_list":["post-25373","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-digital","tag-service-broker","tag-przeglad-narzedzi","tag-net","tag-sql"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/11\/SQL-Trigger-ktory-wywoluje-metode-w-.NET-\u2013-Service-Broker.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/25373"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/581"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=25373"}],"version-history":[{"count":3,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/25373\/revisions"}],"predecessor-version":[{"id":25382,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/25373\/revisions\/25382"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/25383"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=25373"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=25373"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=25373"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}