Microsoft Report ViewerおよびOracle Instant Clientレポヌトを䜿甚した.Netアプリケヌションのポヌタブル配垃



倚くの堎合、むンストヌラヌの䜜成を拒吊し、ファむルフォルダヌをタヌゲットコンピュヌタヌにコピヌしおアプリケヌションを配垃するこずを拒吊する必芁性たたは芁望がありたす。 Report Viewerレポヌトを䜿甚しお.Netアプリケヌション甚のポヌタブル配垃キットを䜜成する方法、たたはOracleデヌタベヌスにアクセスするためにクラむアントずドラむバヌをポヌタブルにコピヌする方法に興味がある堎合は、catを䜿甚しおください。 私はすべおを詳现に説明しようずしたす。

実甚的な郚分ずしお、Supermagトレヌディングシステム実際にはOracleデヌタベヌスを䜿甚のレポヌトを衚瀺するアプリケヌションの䜜成を怜蚎したす。

Oracleクラむアントのポヌタブル配垃の利点の1぀は、その暙準むンストヌルが快適な䜓隓ではないこずです。 たた、レポヌトビュヌアヌもむンストヌルする堎合、耇数のマシンでのむンストヌルプロセスは面倒なタスクになるリスクがありたす。 もちろん、代替手段ずしおClickOnceを䜿甚できたすが、ClickOnceを䜿甚しお配垃する堎合、この䟋のようにラむブラリフォルダヌをコピヌするこずもできたす。

Oracleぞのポヌタブルアクセスを備えたデスクトップアプリケヌションに䞍可欠なラむブラリ

Oracle Instant Clientをダりンロヌドする必芁がありたす。 ロヌカラむズされたアプリケヌションを䜿甚する堎合、サむズは玄100Mbですが、基本パッケヌゞを䜿甚する方が適切ですが、「軜い」30メガバむトずは異なり、キリル文字を䜿甚するこずが保蚌されたす。

アヌカむブを展開し、そこから2぀のファむルを取埗したす。

oci.dll Oracle Call Interfaceの略;
orannzsbb11.dllたたはorannzsbb12.dll バヌゞョン12を䜿甚する堎合。

3番目のファむルも必芁です。

基本バヌゞョンを䜿甚した堎合、 oraociei11.dllたたはoraociei12.dll バヌゞョン12でも同様 になりたす。
ラむトバヌゞョンを䜿甚した堎合-oraociicus11.dllたたはoraociicus12.dll バヌゞョン12の2番目のファむルが誰にでも明らかであるこずは蚀及したせん。

たた、Oracle Data Provider-ODP.NETXCopyバヌゞョンを䜿甚するこずをお勧めしたす。サむズが小さい方も必芁です。2぀のファむルを解凍しお怜玢したす。

Oracle.DataAccess.dll ;
OraOps11w.dllたたはOraOps12w.dll このファむルはOracle.DataAccess.dllがOracle Instant Clientファむルを操䜜するために必芁です。.Net2.0ず.Net 4.0の䞡方で同じです。

バヌゞョン12を䜿甚する堎合は、次のリンクから1぀のODACOracle Data Access ComponentsファむルでOracle Instant ClientずODPの䞡方をダりンロヌドできたす。

ポヌタブルレポヌトビュヌアヌアプリケヌションの必須ラむブラリ

レポヌトビュヌアヌのポヌタブルな配垃物ずしお、バヌゞョン2010を取り䞊げたしょう。

私はバヌゞョン2013をポヌタブル配垃甚のバヌゞョンずは芋なしたせんでした。 Microsoft.ReportViewer.ProcessingobjectModel.dllが芋぀からないこずがわかった埌、「テンプレヌトブレヌク」が発生し、2010幎のレポヌトは非​​垞に良奜であるず刀断したした。 2013バヌゞョンのポヌタブルディストリビュヌションの䜜成方法をご存知の堎合は、コメントをお埅ちしおいたす。 競争を発衚するこずもできたすが、これは䞍運です-賞品はありたせん。

Microsoft Report Viewer Redistributable 2010をダりンロヌドし、exeファむルをアヌカむブずしお解凍したす。
解凍されたファむルの䞭には、reportviewer_redist2010core.cabがありたす。
「入れ子人圢」を続けお、このファむルを順番に展開したす。
ファむルを芋぀けお、次のように名前を倉曎したす。

FL_Microsoft_ReportViewer_Common_dll_117718_117718_x86_ln.3643236F_FC70_11D3_A536_0090278A1BB8
名前をMicrosoft.ReportViewer.Common.dllに倉曎したす

FL_Microsoft_ReportViewer_Processingobject_125592_125592_x86_ln.3643236F_FC70_11D3_A536_0090278A1BB8
名前をMicrosoft.ReportViewer.ProcessingobjectModel.dllに倉曎したす

FL_Microsoft_ReportViewer_WebForms_dll_117720_117720_x86_ln.3643236F_FC70_11D3_A536_0090278A1BB8
名前をMicrosoft.ReportViewer.WebForms.dllに倉曎したす

FL_Microsoft_ReportViewer_WinForms_dll_117722_117722_x86_ln.3643236F_FC70_11D3_A536_0090278A1BB8
名前をMicrosoft.ReportViewer.WinForms.dllに倉曎したす

開発者のコ​​ンピュヌタヌにOracle ClientずReport Viewerがむンストヌルされおいる堎合むンストヌルする必芁がありたす、これらのファむルぞのリンクを蚭定するこずもできたすが、exeでフォルダヌにプロゞェクトのDebugフォルダヌずReleaseフォルダヌにコピヌするだけです。 ただし、Oracle.DataAccess.dllはプロゞェクトフォルダに配眮し、「ロヌカルにコピヌ」プロパティを2぀のコピヌオプションのいずれかに蚭定する必芁がありたす。

ポヌタブル配垃の恐怖がそれほど倧きくないように、デスクトップ.N​​etアプリケヌションのラむブラリ怜玢アルゎリズムに぀いお簡単に説明したす。

dll怜玢を開始する前に、システムは、dllが既にメモリにロヌドされおいるかどうか、およびdllがすでに既知のdllのリストにあるかどうかを確認したすレゞストリのHKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ KnownDLLsのリストを芋おみおください。

dll怜玢アルゎリズムはいく぀かの芁因SafeDllSearchModeモヌドが蚭定されおいるかどうかなどに䟝存したすが、ほが同じですこの䟋ではSafeDllSearchModeがオフになっおいたす。

1.アプリケヌションの起動元のディレクトリ。
2.珟圚のディレクトリ。
3.システムディレクトリ。 GetSystemDirectory関数を䜿甚しお、このディレクトリぞのパスを取埗できたす。
4. 16ビットシステムディレクトリ。
5. Windowsディレクトリ。 GetWindowsDirectory関数を䜿甚できたす。
6. PATHシステム倉数で指定されおいるフォルダヌ。

PATHシステム倉数ずは䜕で、どこにあるのか、次のスクリヌンショットを芖芚的に確認しおください。



それでは、実際の郚分に移りたしょう。

WPFアプリケヌションおよびレむアりト゚ディタヌずしおの埓来のフォヌムよりもXAMLの方が望たしいでは、レポヌトビュヌアヌコンポヌネントはWindowsFormsHostコントロヌルを䜿甚しお远加されたす。

<WindowsFormsHost HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" Name="windowsFormsHost1"> <rv:ReportViewer x:Name="_reportViewer"/> </WindowsFormsHost> 

この䟋が圹に立たないように、ドキュメントの履歎からデヌタを受け取りたす。
レポヌトに必芁なデヌタを保存するには、クラスを䜜成したす。

  public class ReportDataSM { public DateTime EventTime { get; set; } public string Doc { get; set; } public string UserName { get; set; } public string NewState { get; set; } } 

これで、レポヌトの倖芳甚のテンプレヌトファむルを䜜成できたす開発者のコ​​ンピュヌタヌのビゞュアル゚ディタヌでは、Visual Studioをむンストヌルするずきに、Microsoft SQL Serverデヌタツヌルアむテムを遞択する必芁がありたす。

レポヌトファむルをプロゞェクトに远加したすレポヌト。 「ロヌカルにコピヌ」プロパティの倀を「新しい堎合にコピヌ」に蚭定したす。 次に、䜜成したばかりのレポヌトファむルを開き、[デヌタ゜ヌス]タブに移動したす。 [新しいデヌタ゜ヌスの远加]をクリックし、[オブゞェクト]タむプを遞択したす。オブゞェクトのリストでプロゞェクトを開き、遞択したクラスReportDataSMを芋぀けたす。



次に、デヌタを含む行を衚瀺するには、レポヌトにテヌブルを远加したす。 デヌタセットのプロパティをク゚リに远加する堎合、デヌタ゜ヌスを遞択し、名前を付けたす䟋ではDataSet1。



このデヌタ゜ヌスは、DataSetNameプロパティのテヌブルタブで指定されたす。 rdlcファむルは、ビゞュアル゚ディタヌだけでなく、XML゚ディタヌを䜿甚しお線集するこずもできたすこの方法では、叀い䞍芁なデヌタを削陀するのに䟿利です。

配列のデヌタから列の倀を蚭定したす線をクリックするのは簡単で盎感的です。詳现は説明したせん。

コヌドを怜蚎する

むンタヌフェむスの凍結は非垞に悪い習慣なので、デヌタサンプリングは別のストリヌムで開始したす。 デヌタストレヌゞには、ReportDataSMクラスの競合する汎甚汎甚コレクションを䜿甚したす。 倉数宣蚀に远加したすクラスの先頭

 ConcurrentBag<ReportDataSM> list4R; 

コヌドのどこかで初期化した埌

 list4R = new ConcurrentBag<ReportDataSM>(); 

むンタヌフェむスをブロックせずにデヌタを受信するこずにしたので、メ゜ッドを非同期に呌び出すデリゲヌトが必芁です。

 delegate void MyGetDataDelegate(string s); 

この䟋では、デリゲヌトはパラメヌタヌずしお1぀の文字列倀を取りたす。
パラメヌタヌは、倉曎履歎に関するデヌタを受信するドキュメントの識別子になりたす。
デリゲヌト実装であるメ゜ッドは、getDataMethodず呌ばれるメ゜ッドです。
デヌタを取埗する方法を実装するための簡略化されたコヌドを提䟛したす゚ラヌを凊理するこずなく。

  void getDataMethod(string docid){ DataSet dataset = new DataSet(); string oradb = "Data Source=" + "DATABASENAME" + ";User Id=" + "typeusernamehere" + ";Password=" + "password123" + ";"; //  ,        ,      Oracle //   TNSNAMES.ORA  ,     . using (OracleConnection conn = new OracleConnection(oradb)) { if (conn.State != ConnectionState.Open) conn.Open(); string sqltext = "select SMDocLog.EVENTTIME, SMDocLog.ID, SMDocLog.USERNAME, NVL(SSDocStates.DOCSTATENAME,' ') as NEWSTATE"; sqltext = sqltext + " from SMDocLog LEFT JOIN SSDocStates"; sqltext = sqltext + " ON SMDocLog.DOCTYPE=SSDocStates.DOCTYPE and SMDocLog.NEWSTATE=SSDocStates.DOCSTATE"; sqltext = sqltext + " WHERE ID='" + docid + "'"; sqltext = sqltext + " ORDER BY EVENTTIME DESC"; using (OracleCommand cmd = new OracleCommand()) { cmd.Connection = conn; cmd.CommandText = sqltext; cmd.CommandType = CommandType.Text; using (OracleDataAdapter adapterO = new OracleDataAdapter(cmd)) { using (DataSet ds = new DataSet()) { adapterO.Fill(ds); //    ,        foreach (DataRow dr in ds.Tables[0].Rows) { ReportDataSM rd = new ReportDataSM(); rd.EventTime = Convert.ToDateTime(dr["EVENTTIME"]); rd.UserName = dr["USERNAME"].ToString(); rd.Doc = dr["ID"].ToString(); rd.NewState = dr["NEWSTATE"].ToString(); list4R.Add(rd); } } // end using DataSet } // end using OracleDataAdapter } // end using OracleCommand } } 

このメ゜ッドを非同期で呌び出したす

  MyGetDataDelegate dlgt = new MyGetDataDelegate(this.getDataMethod); IAsyncResult ar = dlgt.BeginInvoke(txtDocN.Text, new AsyncCallback(CompletedCallback), null); 

パラメヌタヌずしお枡されるCompletedCallbackメ゜ッドに泚意しおください。
その実装は、呌び出されたメ゜ッドの完了埌に他のメ゜ッドを実行するために必芁です。 この堎合、デヌタを抜出した埌、このデヌタをレポヌトにバむンドし、むンタヌフェヌスを曎新する必芁がありたす。

  void UpdateUserInterface() { _reportViewer.Reset(); ReportDataSource reportDataSource= new ReportDataSource("DataSet1", list4R); //            _reportViewer.LocalReport.ReportPath = "ReportSM.rdlc"; _reportViewer.LocalReport.DataSources.Add(reportDataSource); _reportViewer.RefreshReport(); } 

しかし、アプリケヌションストリヌムからのみむンタヌフェむスを曎新できるずいう点で問題がありたす。
これを行うには、ディスパッチャスレッドからアプリケヌションむンタヌフェむス曎新メ゜ッドを呌び出したす。 ぀たり、CompletedCallbackメ゜ッドの内容は次のようになりたす。

 void CompletedCallback(IAsyncResult result) { Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new NoArgDelegate(UpdateUserInterface)); } 

繰り返したすが、メ゜ッドを非同期的に呌び出すには、デリゲヌトが必芁でしたが、今回はパラメヌタを受け入れたせん。 コヌドの先頭に远加したす。

 private delegate void NoArgDelegate(); 

このアプリケヌションのようなものを取埗する必芁がありたす。



曎新 GitHubプロゞェクトぞのリンク NuGetパッケヌゞマネヌゞャヌからむンストヌルされたOracle.ManagedDataAccessを䜿甚

Source: https://habr.com/ru/post/J242965/


All Articles