- PR -

構造体の配列の受け渡し

投稿者投稿内容
HarryHawk
会議室デビュー日: 2002/11/13
投稿数: 7
投稿日時: 2002-11-13 18:56
はじめまして!初の投稿になります。

VB.NETを使ったASP.NETのWebサービスを開発しています。
OracleのTABLEをSQL文にて検索して、結果を構造体で返すことを目的としています。
DataReaderを使って1レコードを返すことには成功していますが、複数レコードの
受け渡しがうまくいきません。

受け渡す構造体を配列にすれば済むかと思いましたが、なかなか進みません。
以下に、1レコードの受け渡しソースを記載します。
助言をお願い致します。
============================================================================
<WebMethod()> Public Function GetDitail(ByVal Param1 As String) As DataBean
Dim outBean As New DataBean()
Dim dr As OleDb.OleDbDataReader
Try
OleDbCommand1.Parameters("RANK").Value = Param1
OleDbConnection1.Open()
dr = OleDbCommand1.ExecuteReader()
While dr.Read()
outBean.NO = Convert.ToString(dr("NO"))
outBean.CODE = Convert.ToString(dr("CODE"))
outBean.NAME = Convert.ToString(dr("NAME"))
outBean.PRICE = dr("PRICE")
outBean.QUANTITY = dr("QUANTITY")
outBean.RANK = Convert.ToString(dr("RANK"))
End While
OleDbConnection1.Close()
Return outBean
Catch e As Exception
Debug.WriteLine(e.Message)
Throw
End Try
End Function
============================================================================
BBC
常連さん
会議室デビュー日: 2002/03/15
投稿数: 37
お住まい・勤務地: 東京
投稿日時: 2002-11-13 19:32
こんばんは。

>以下に、1レコードの受け渡しソースを記載します。
VBは門外漢なので、それ自体のアドバイスではありませんが・・・。
配列として取得したいのであれば、たとえ汚いソースでも、そちらを貼り付けるべきかと思いますが、どうでしょう?

「受け渡しがうまくいかない」との事ですが、
・取得したデータに問題がある(全く同じデータが取得数分出力される等)
・そもそもなんらかの例外が発生してエラーになる(配列に値を入れられない等)
と、考えられるバグを推測する他なくなります。
まんまる
会議室デビュー日: 2002/11/14
投稿数: 2
投稿日時: 2002-11-14 11:54
VB.NETはよくわからないので、誠に申し訳ないのですが、
C#なら次のようにします、ということで、参考になりましたら・・・
===========================================================
[WebMethod]
public Person[] GetPersons()
{
SqlConnection con = new SqlConnection(conStr);
con.Open();
SqlCommand command = new SqlCommand(selectSql2, con);
SqlDataReader reader = command.ExecuteReader();
ArrayList array = new ArrayList();
Person person = null;
while (reader.Read())
{
person = new Person();
person.ID = reader.GetInt32(0);
person.Name = reader.GetString(1);
person.Age = reader.GetInt32(2);
array.Add(person);
}

reader.Close();
con.Close();

return (Person[])array.ToArray(typeof(Person));
}
==========================
一旦ArrayListにインスタンスを格納した後で配列に変換しています。
ArrayListを直接返さないのはSOAPに展開した際に型がanyTypeとなる
ためです。

ではでは
HarryHawk
会議室デビュー日: 2002/11/13
投稿数: 7
投稿日時: 2002-11-14 14:58
BBCさん、まんまるさん コメントありがとうございます。

試行錯誤を繰り返していますが、今だ解決できていません。
以下に現在のソースを記載します。「インデックスが配列の境界外です」とのエラーで止まってます。
============================================================================
<WebMethod()> Public Function GetDitail(ByVal Param1 As String) As DataBean()
 Dim outBean() As DataBean = New DataBean() {}
 Dim dr As OleDb.OleDbDataReader
 Dim i As Integer
 Try
  OleDbCommand1.Parameters("RANK").Value = Param1
  OleDbConnection1.Open()
  dr = OleDbCommand1.ExecuteReader()
  i = 0
  While dr.Read()
   outBean(i).NO = Convert.ToString(dr("NO"))
   outBean(i).CODE = Convert.ToString(dr("CODE"))
   outBean(i).NAME = Convert.ToString(dr("NAME"))
   outBean(i).PRICE = dr("PRICE")
   outBean(i).QUANTITY = dr("QUANTITY")
   outBean(i).RANK = Convert.ToString(dr("RANK"))
   i = i + 1
  End While
  OleDbConnection1.Close()
  Return outBean
 Catch e As Exception
  Debug.WriteLine(e.Message)
  Throw
 End Try
End Function
============================================================================
Datasetを使う方が良いのでしょうか?
Dee
常連さん
会議室デビュー日: 2002/03/05
投稿数: 28
投稿日時: 2002-11-14 15:23
DataBean(ちなみにBeanって言われるとJava系の言葉を連想しますね・・・)の定義が無いので細かくは言えませんが、配列でない変数について、outBean(i).NOという書き方はできないのではないかと。"インデックスが配列の境界外です"は、配列宣言されてない変数を配列のように使おうとしているからエラーが出てるのではないでしょうか。
DataBeanの配列を宣言する必要がありますね。
ここまではVB.NETの言語的なお話です。

まんまるさんのソースは、その後の注意点、SOAPに載せるのであればどうするか、という点の指摘、だと思います。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2002-11-14 17:11
こんにちは。

 WebServiceにするのであれば、DataSetを返す方がスマートでしょう。構造体のテーブルを作って、メンバを列、データを行にすればOKです。こちらだとシリアライズが実装済みなので、IE上で返ってきたデータの確認ができます。

 それから、せっかくnewしているのですが、配列数を指定していないので、自動拡張ではなく0の配列が作られていると思います。そこにものを入れようとしても、入れるところがないのでエラーになります。

 構造体(じゃなく、クラス化できないですか?)そのものではありませんが、ArrayListクラスを使えば、動的に領域が拡張でき、配列のように扱うことができます。
コード:

Dim ArrData As ArrayList = New ArrayList()
' 略
While dr.Read()
Dim out As DataBean = New DataBean
out.NO = dr.GetString("NO") ' ConvertしなくてもこれでStringが取り出せます
' 略
ArrData.Add(out) ' これで自動拡張配列に格納される
End While
' 略
Return CType(ArrData.ToArray(DataBean), DataBean()) ' ここ不安


こんなところかな?

[ メッセージ編集済み 編集者: Jitta 編集日時 2002-11-14 20:42 ]
HarryHawk
会議室デビュー日: 2002/11/13
投稿数: 7
投稿日時: 2002-11-20 19:05
Deeさん、Jittaさん コメント有難うございます。

いろいろ試した結果望む結果を得ることができました。
サーバ側は、問題なく動作していると思われるのですが、
クライアント(Excel2002 & VB.NET)の実装がうまくいっていません。(ToT)

現在のソースは、以下の通りです。
サーバコード
コード:
    <WebMethod()> Public Function GetDitail6(ByVal Param1 As String) As DataBean()
        Dim ArrList As ArrayList = New ArrayList()
        Dim dr As OleDb.OleDbDataReader
        Dim i As Integer
        Try
            OleDbCommand1.Parameters("RANK").Value = Param1
            OleDbConnection1.Open()
            dr = OleDbCommand1.ExecuteReader()
            While dr.Read()
                Dim outBean As DataBean = New DataBean()
                outBean.NO = Convert.ToString(dr("NO"))
                outBean.CODE = Convert.ToString(dr("CODE"))
                outBean.NAME = Convert.ToString(dr("NAME"))
                outBean.PRICE = dr("PRICE")
                outBean.QUANTITY = dr("QUANTITY")
                outBean.RANK = Convert.ToString(dr("RANK"))
                ArrList.Add(outBean)
            End While
            OleDbConnection1.Close()

            Dim soapBean(ArrList.Count) As DataBean

            For i = 0 To ArrList.Count - 1
                soapBean(i) = ArrList.Item(i)
            Next i
            Debug.WriteLine("i =" & i)
            Return soapBean
        Catch e As Exception
            Debug.WriteLine(e.Message)
            Throw
        End Try
    End Function



クライアントコード(VB.NET)
コード:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim Param As String
        Dim ws As TestWeb.Service1
        Dim outBean() As TestWeb.DataBean = New TestWeb.DataBean() {}
        Dim i As Integer
        Param = TextBox1.Text
        Try
            outBean = ws.GetDitail6(Param)
            i = outBean.Length
        Catch mes As NullReferenceException
            Debug.WriteLine("mes : " & mes.Message)
            Throw
        End Try
        MsgBox(outBean(0).NO)
    End Sub



クライアントのエラーは、「オブジェクト参照がオブジェクト インスタンスに設定されていません。」というものです。
アドバイスがありましたら、お願い致します。



karajan
ベテラン
会議室デビュー日: 2002/07/05
投稿数: 89
投稿日時: 2002-11-21 14:36
はじめまして。

VB.NETでも同じだと思うのですが、

ws = new TestWeb.Service1();

って、必要じゃないでしょうか?

スキルアップ/キャリアアップ(JOB@IT)