<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.technet.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>BizTalk and around : Oracle</title><link>http://blogs.technet.com/stanko/archive/tags/Oracle/default.aspx</link><description>Tags: Oracle</description><dc:language>ru</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>WCF адаптер для очередей Oracle AQ</title><link>http://blogs.technet.com/stanko/archive/2008/11/20/wcf-oracle-aq.aspx</link><pubDate>Thu, 20 Nov 2008 14:05:53 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3156902</guid><dc:creator>yaroslav</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.technet.com/stanko/comments/3156902.aspx</comments><wfw:commentRss>http://blogs.technet.com/stanko/commentrss.aspx?PostID=3156902</wfw:commentRss><description>&lt;p&gt;Продолжая &lt;a href="http://blogs.technet.com/stanko/archive/2008/11/18/biztalk-wcf-lob-adapter-sdk.aspx"&gt;предыдущий пост&lt;/a&gt;, поделюсь опытом разработки транзакционного WCF адаптера для очередей Oracle Advanced Queuing (AQ). &lt;/p&gt; &lt;p&gt;&lt;b&gt;Предыстория&lt;/b&gt;  &lt;p&gt;Перед нами (&lt;a href="http://www.microsoft.com/services/microsoftservices/default.mspx"&gt;MCS&lt;/a&gt;) возникла задача показать возможность интеграции информационных систем построенных на Oracle с помощью BizTalk. В силу многих причин было принято решение не использовать хранимые процедуры и не подключаться к таблицам напрямую, а передавать данные в виде отдельных сообщений через очереди Oracle. Одним из требований была возможность гарантированной доставки, чтобы данные не удалялись из источника пока не попадут в следующее надежное хранилище, но и не попадали в следующие хранилище пока не удалятся из источника. Проще говоря, передача данных должна осуществляться в рамках транзакции.  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/stanko/WindowsLiveWriter/WCFOracleAQ_C633/clip_image002_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="129" alt="clip_image002" src="http://blogs.technet.com/blogfiles/stanko/WindowsLiveWriter/WCFOracleAQ_C633/clip_image002_thumb.jpg" width="646" border="0"&gt;&lt;/a&gt;  &lt;p&gt;Для решения этой задачи нужно было найти существующий или разработать собственный адаптер, который бы умел подсоединяться к AQ и забирать данные внутри транзакции объединяющей источник данных (в данном случае AQ) и BizTalk MessageBox. На момент выбора адаптера для Oracle AQ у партнеров Microsoft уже существовали адаптеры умеющие работать с Oracle AQ, но все они имели некоторые ограничения, например отсутствие поддержки транзакций. Поэтому было принято решение разработать свой адаптер с помощью &lt;a href="http://www.microsoft.com/biztalk/technologies/wcflobadaptersdk.mspx"&gt;WCF LOB Adapter SDK&lt;/a&gt;.  &lt;p&gt;&lt;b&gt;Разработка адаптера&lt;/b&gt;  &lt;p&gt;Для решения задачи взаимодействия с AQ было рассмотрено множество вариантов, вот некоторые из них:  &lt;ul&gt; &lt;li&gt;JMS – нужен адаптер для JMS, подтверждение возможности транзакционной передачи получено не было.  &lt;li&gt;SOAP – дополнительное звено и необходимость развертывания веб-сервера на стороне базы данных. Транзакционность тоже под большим вопросом.  &lt;li&gt;PL\SQL через ODP.NET – нужна установка Oracle Client и ODP.NET. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;В итоге единственным приемлемым вариантом удовлетворявшим большинству требований оказался PL\SQL, который предоставляет простые команды для работы с очередями AQ, а ODP.NET предоставляет прозрачный интерфейс для работы с .NET транзакциями.  &lt;p&gt;После выбора способа взаимодействия дальнейшая реализация WCF адаптера заняла минимальное кол-во времени, включая поддержку транзакций и выгрузку метаданных для использования в BizTalk решении. Это говорит не столько об опытности Microsoft Consulting Services :), сколько о простоте инструментария WCF LOB Adapter SDK. Так что если перед вами стоит задача подключения к одной из унаследованных систем, или системе для которой ни у Microsoft ни у партнеров нет адаптера, вы можете написать его самостоятельно, это не так сложно как может показаться.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3156902" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/stanko/archive/tags/WCF/default.aspx">WCF</category><category domain="http://blogs.technet.com/stanko/archive/tags/Oracle/default.aspx">Oracle</category><category domain="http://blogs.technet.com/stanko/archive/tags/BizTalk/default.aspx">BizTalk</category><category domain="http://blogs.technet.com/stanko/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.technet.com/stanko/archive/tags/AQ/default.aspx">AQ</category></item><item><title>Поддержка транзакций в WCF Oracle adapter</title><link>http://blogs.technet.com/stanko/archive/2008/05/08/oracle.aspx</link><pubDate>Thu, 08 May 2008 11:21:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3052095</guid><dc:creator>stas</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.technet.com/stanko/comments/3052095.aspx</comments><wfw:commentRss>http://blogs.technet.com/stanko/commentrss.aspx?PostID=3052095</wfw:commentRss><description>&lt;P&gt;Недавно мне прислали вопрос о том, как обновить две таблицы в БД Oracle в одной транзакции, отправив два соответствующих сообщения из BizTalk через WCF Oracle адаптер. &lt;/P&gt;
&lt;P&gt;Казалось бы, интутитивно, заключение двух Send форм в Atomic transaction scope должно привести к желаемому результату. Однако, такие транзакции выполняются на уровне MessageBox.&lt;/P&gt;
&lt;P&gt;Как всегда, решение имеет несколько вариантов. Стандартные варианты в таких случаях - иметь хранимую процедуру, выполняющую обновление двух таблиц и вызывать ее через адаптер, либо воспользовать Expression формой, где через средства .NET выполнить обновление в транзакции.&lt;/P&gt;
&lt;P&gt;С новым же WCF Oracle адаптером, у вас появилась возможность поддержки транзакций для серии отдельных сообщений. По &lt;A href="http://blogs.msdn.com/adapters/archive/2007/10/24/enablebiztalklayeredchannel-property-in-oracledb-adapter.aspx" mce_href="http://blogs.msdn.com/adapters/archive/2007/10/24/enablebiztalklayeredchannel-property-in-oracledb-adapter.aspx"&gt;этой ссылке&lt;/A&gt; можно прочитать про эту возможность. Далее я опишу, как это сделать своими словами. &lt;/P&gt;
&lt;P&gt;Итак, у вас есть набор сообщений для Oracle, которые вы хотите отправить в единой транзакции. Первое, что нужно сделать это установить у таких сообщений следующие свойства:&lt;/P&gt;
&lt;LI&gt;http://schemas.microsoft.com/BizTalk/2003/system-properties#SPID&lt;/LI&gt;
&lt;P&gt;Это стандартное свойство, которое устанавливается адаптером в идентификатор исходящего порта (в нашем случае Oracle порта). Все сообщения в транзакции должны иметь единое значение этого свойства. Т.е. все такие сообщения должны отправляться через единый исходящий порт (возможно с различными операциями на каждое действие). &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI&gt;http://schemas.microsoft.com/BizTalk/2003/system-properties#InterchangeID&lt;/LI&gt;
&lt;P&gt;InterchangeID так же стандартное свойство и оно позволяет отнести сообщения с единым значением InterchangeID к единой сессии передачи сообщений (например, при дебатчинге входящего сообщения, все получившиеся сообщения имеют одинаковое значение InterchangeID). Итак, вам придется установить это свойство в оркестровке для серии транзакционных сообщений в единое значение - это может быть просто сгенерированный Guid или взятый InterchangeID из входящего сообщения.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI&gt;http://Microsoft.LobServices.OracleDB/2007/03/OracleDBSendContextProperties#TransactionState&lt;/LI&gt;
&lt;P&gt;Третье свойство определено в сборке Microsoft.Adapters.OracleDB.BiztalkPropertySchema.dll, которая идет в поставке с BizTalk Adapter Pack (находится в папке bin, где установлен пакет). Добавьте эту сборку, как ресурс через административную консоль BizTalk (например, в стандартное приложение BizTalk Application 1). В ваш проект же добавьте на нее ссылку (через Add Reference).&lt;/P&gt;
&lt;P&gt;TransactionState - это очень важное свойство, т.к. оно регулирует действия над транзакцией, и может принимать следующие значения:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;BEGIN - сообщение, которое может быть либо данными или контрольным (об этом ниже) сообщением, иницирует транзакцию.&lt;/LI&gt;
&lt;LI&gt;REUSE - сообщение включается в транзакцию.&lt;/LI&gt;
&lt;LI&gt;COMMIT - контрольное сообщение подтверждает транзакцию.&lt;/LI&gt;
&lt;LI&gt;ABORT - контрольное сообщение откатывает транзакцию.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Контрольное сообщение имеет следующий вид: &amp;lt;Oracle_Transaction xmlns="http://Microsoft.LobServices.OracleDB/2007/03/Oracle_Transaction"&amp;gt;&amp;lt;/Oracle_Transaction&amp;gt;. Операция отправляющая контрольное сообщение в адаптер должна мэпиться на SOAP action "http://Microsoft.LobServices.OracleDB/2007/03/Oracle_Transaction".&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Схема контрольного сообщения (дабы не создавать его руками) находится в папке Schemas, где установлен BizTalk Adapter Pack.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Это все о свойствах. &lt;/P&gt;
&lt;P&gt;Сам WCF-custom адаптер с байндингом oracleDBBinding должен иметь свойство enableBizTalkCompatibilityMode установленным в true (по умолчанию, это так).&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Небольшой пример. Я получаю входящее сообщение, создаю два исходящих, каждое из которых обновляет различные таблицы Oracle и затем завершаю транзакцию.&lt;/P&gt;
&lt;P&gt;Моя оркестровка выглядит так:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/stanko/WindowsLiveWriter/Oracle_9A95/Ora1_2.jpg" mce_href="http://blogs.technet.com/blogfiles/stanko/WindowsLiveWriter/Oracle_9A95/Ora1_2.jpg"&gt;&lt;IMG style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=244 alt=Ora1 src="http://blogs.technet.com/blogfiles/stanko/WindowsLiveWriter/Oracle_9A95/Ora1_thumb.jpg" width=220 border=0 mce_src="http://blogs.technet.com/blogfiles/stanko/WindowsLiveWriter/Oracle_9A95/Ora1_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;В форме MessageAssignment происходит самое интересное: я устанавливаю свойства всей серии Oracle сообщений:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;doc = new System.Xml.XmlDocument();&lt;BR&gt;doc.LoadXml("&amp;lt;ns0:Oracle_Transaction xmlns:ns0='http://Microsoft.LobServices.OracleDB/2007/03/Oracle_Transaction'&amp;gt;&amp;lt;/ns0:Oracle_Transaction&amp;gt;"); 
&lt;P&gt;mCommit = doc; 
&lt;P&gt;mInsertProduct(Microsoft.Adapters.OracleDB.BiztalkPropertySchema.TransactionState) = "BEGIN";&lt;BR&gt;mInsertProduct(BTS.InterchangeID) = mInbound(BTS.InterchangeID);&lt;BR&gt;mInsertPO(Microsoft.Adapters.OracleDB.BiztalkPropertySchema.TransactionState) = "REUSE";&lt;BR&gt;mInsertPO(BTS.InterchangeID) = mInbound(BTS.InterchangeID);&lt;BR&gt;mCommit(Microsoft.Adapters.OracleDB.BiztalkPropertySchema.TransactionState) = "COMMIT";&lt;BR&gt;mCommit(BTS.InterchangeID) = mInbound(BTS.InterchangeID); 
&lt;P&gt;Последовательность отправки сообщений: mInsertProduct, mInsertPO, mCommit. 
&lt;P&gt;Порт Oracle в консоли администратора имеет следующие настройки WCF-Custom для SOAP Action Header: 
&lt;P&gt;&amp;lt;BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;Operation Name="InsertProduct" Action="http://Microsoft.LobServices.OracleDB/2007/03/SUPPLIER/Table/PRODUCT/Insert" /&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;Operation Name="InsertPO" Action="http://Microsoft.LobServices.OracleDB/2007/03/SUPPLIER/Table/PURCHASEORDER/Insert" /&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;Operation Name="ControlTransaction" Action="http://Microsoft.LobServices.OracleDB/2007/03/Oracle_Transaction" /&amp;gt;&lt;BR&gt;&amp;lt;/BtsActionMapping&amp;gt; 
&lt;P&gt;Вот пожалуй и все. Теперь вставка в две разные таблицы будет производится в единой транзакции. 
&lt;P&gt;Стас&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3052095" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/stanko/archive/tags/WCF/default.aspx">WCF</category><category domain="http://blogs.technet.com/stanko/archive/tags/Oracle/default.aspx">Oracle</category><category domain="http://blogs.technet.com/stanko/archive/tags/BizTalk/default.aspx">BizTalk</category></item></channel></rss>