none
xsdファイルでデータベースを繋げようとするとmulti-part identifier could not be boundのメッセージが出てしまいます。 RRS feed

  • 質問

  • こんにちは、

     

    ASP.NETでxsdファイルを使い、医薬品製品データベースをデザインしています。

     

    一製品と原料名との関係はmany to manyなので、中間に仲介テーブルをつくxsdファイルの製品名テーブルの中に原料名をいれようとしているのですが、multi-part identifier could not be boundエラーが出てしまいます。

     

    医薬品テーブルはMedicalProd-child table, Primary Key: MedicalProd_ID

    仲介テーブルはPharmProd-parent table, Primary Key: PharmProd_ID, Foreign Key: MedicalProd_ID, PharmName_ID

    原料テーブルはPharmName-child table, Primary Key: PharmName_ID

     

    繋ぐところのSQLは以下の通りです。

     

    (SELECT pharmName FROM PharmName

    WHERE MedicalProd.MedicalProd_ID=PharmProd.MedicalProd_ID

    AND

    PharmProd.PharmName_ID=PharmName.PharmName_ID) as phmName

     

    いろいろと情報を探してみましたが、テーブルが3つにわたっている例が無く、困っております。

    なにか、見落としていることがあるのか、考え違いをしているのか或いはシンタックスを間違えているのか、ご指摘いただけると大変助かります。

     

    どうぞよろしくお願い致します。

     

    Mimmi

     

     

     

    2009年1月3日 20:23

回答

  •  mimmiarne さんからの引用

    Type 'MedicalProductsTableAdapters.MedicalProdTableAdapter' already defines a member called 'GetMedicalProd' with the same parameter types

    ちょっと頭を冷やしてからやりなおして見ますので結果の報告は今しばらくお待ち下さい。申し訳ないです。

     

    考えている途中で余計なインプットはしないほうが良いかもしれませ
    んが、ちょっと一言。

     

    エラーメッセージによれば、すでにどこかで MimmiArne さんが
    GetMedicalProd という名前のメソッドを作っていて、それと今回

    作成したメソッドと名前がダブっているようです。

     

    先のメッセージで「各TableAdapterにはメソッドを作成するところが
    あるのですが、MedicalProductTableAdapterのGetMedicalProd()の
    ところで以下のSQLを使って・・・」と書いてありました。それが残
    っているのでは?

     

    そうであれば、それはとりあえずそのまま置いといて、今回新たに作
    成するメソッドの名前を GetMedicalProd とは別の名前にしてやれば
    解決するはずです。(ただし、Multi-part Identifier could not be
    bound エラーの問題がまだ残っているなら、それを解決しなければな
    りませんが)

     

    なお、名前を変えた場合は、先のレスの手順 (4) の ObjectDataSorce
    の SelectMethod プロパティの設定を、その、変えた方の名前にする
    必要がありますので、お忘れなく。

    2009年1月13日 13:48

すべての返信

  • 具体的なことは何も分からない回答者が、問題を再現できる程度の最低限の情報を

    開示できないでしょうか?

     

    そうしていただけると、お役に立てるかもしれません(立てないかもしれませんが、その

    時はご容赦ください)。

    2009年1月5日 14:43
  • SurferOnWwwさん、

     

    昨年は大変お世話になりました。

    またまた説明が欠けていたのですね、申し訳ありません。

     

    以下のTutorialを使って医薬品データベースを構築しています。

     

    http://www.asp.net/Learn/data-access/tutorial-01-cs.aspx

     

    以下はこのTutorial に使われている Figure31なのですが、XSDファイルにいくつかのTable Adapterが載せられています。

    http://static.asp.net/asp.net/images/dataaccess/01fig31cs.png

     

    この要領で医薬品データのTable Adapterをいくつか作ってXSDファイルにAddしているのですが、私の持っているデータによってはMany to Manyの関係を持つものが何セットが発生してしまいます。このスレッドで挙げた例はその中でも一番重要なのですが、その関係は以下の通りです。

     

    一医薬品は複数の原料を擁し、一原料は複数の医薬品に含まれている。

     

    そこで医薬品TableAdapter (MedicalProdTableAdapter) と原料TableAdapter (PharmNameTableAdapter)の間に仲介するTableAdapter(PharmProductTableAdapter)をつくり、このTableAdapterを介して医薬品テーブルと原料テーブルを繋げようとしているのです。

     

    テーブルの主な内訳(医薬品テーブルはかなりフィールドが多いのですがこの問題に関すると思われるのは以下のみです)

     

    医薬品テーブル(MedicalProdTableAdapter)

    MedicalProd_ID                 PrimaryKey

    MedicalProdName

    MedicalProdTradeName

     

    仲介テーブル (PharmProdTableAdapter)

    PharmProd_ID                   PrimaryKey

    MedicalProd_ID                   ForeignKey

    PharmName_ID                   ForeignKey

     

    原料テーブル (PharmNameTableAdapter)

    PharmName_ID                 PrimaryKey

    PharmName

     

    各TableAdapterにはメソッドを作成するところがあるのですが、MedicalProductTableAdapterのGetMedicalProd()のところで以下のSQLを使ってPharmNameTableAdapterからPharmNameをMedicalProdTableAdapterに追加しようとするとMulti-part Identifier could not be boundエラーがでてしまうのです。

     

    Code Snippet

    SELECT MedicalProd_ID, MedicalProdName, MedicalProdTradeName,

    (SELECT PharmName FROM PharmName

    WHERE MedicalProd.MedicalProd_ID=PharmProd.MedicalProd_ID

    AND

    PharmProd.PharmName_ID=PharmName.PharmName_ID) as phmName

    FROM MedicalProd

     

     

    このエラー名をキーワードにしていろいろとネットで探してみたのですが、どうもわからず、困っております。ちょっとしたヒントでも、提案でも、なにか根本的な考え違いに気づかれたらその点をご指摘いただけるだけでも本当に助かります。どうぞよろしくお願い致します。まだ説明が不明瞭であればどうぞお知らせ下さい。自分ではどこが欠けているのか残念ながらよくわかりませんので。

     

    Mimmi

    2009年1月6日 16:09
  • TableAdapter とか xds ファイルとかの問題ではなく、SELECT ク
    エリの書き方(たぶん、WHERE 句の条件で PharmName が特定

    できないところ)が問題ではないかと思います。

     

    実際に検証していませんので、それが「Multi-part Identifier
    could not be bound エラー」が出ている原因かどうか確信はない
    ですが・・・

     

    GetMedicalProd メソッドで何を取得したいのか教えていただけま
    せんか? その上で、クエリがその目的に適っているかを検討し
    た方がよさそうに思います。

     

    もし、GetMedicalProd メソッドで、薬の ID、名前等のデータと、
    その薬に使われているすべての PharmName を、一つの DataTable
    に入れて取得したいのだとすると、それは少なくとも提示されて
    いた SELECT クエリでは無理です。

     

    チュートリアルの Figure 30 のように、新しい Column として
    phmName を追加してあるとしても、追加したのは一つだけですか
    ら、そこに複数のデータを入れるには工夫が必要で、根本的にや
    り方を考え直す必要がありそうです。

    2009年1月7日 13:03
  • SurferOnWWWさん、

     

    問題をご指摘いただき本当にありがとうございます。

    SELECTクエリがおそらく原因であるということですね。指摘される通りですね、複数のデータを入れるにはいろいろとインフラも変えなくてはいけなくてはいけないのでしょうね。短絡的に考えすぎていました。

     

    GetMedicalProdメソッドで取得したかったものは以下のものです。

     

    MedicalProd_ID     医薬品識別番号         単数

    MedicalProdName     医薬品名           単数

    MedicalProdTradeName  英文医薬品名          単数

    PharmName       医薬品識別番号に該当する原料名 複数  

     

    その他、ここでは関係ないので書きませんでしたが製造元、製造元英文名、参考資料等 (いずれも単数)です。これらはMany to Manyの関係ではないのでFigure30の要領により、追加が可能で、正常にデータベースに表示されます(その節も本当にお世話になりました)。さらに服用法、分量等は1to Manyになる筈ですが、これに関してはまだ始めていません。

     

    今までは初歩的なSQLしか使ったことしかないのですが、こういったケースを扱えるSQLもきっとある筈ですね。探してみます。

     

    夜遅くまで問題を検討してくださり本当にありがとうございます。

     

    Mimmi

     

     

     

     

    2009年1月7日 16:18
  •  mimmiarne さんからの引用

    SELECTクエリがおそらく原因であるということですね。指摘される通りですね、複数のデータを入れるにはいろいろとインフラも変えなくてはいけなくてはいけないのでしょうね。短絡的に考えすぎていました。

    # とりあえずphmNameのエイリアスの付いた箇所のクエリは通らないと思います

    先ずmimmiarneさんが期待されている結果を教えてください。

     

     mimmiarne さんからの引用

    GetMedicalProdメソッドで取得したかったものは以下のものです。

     

    MedicalProd_ID     医薬品識別番号         単数

    MedicalProdName     医薬品名           単数

    MedicalProdTradeName  英文医薬品名          単数

    PharmName       医薬品識別番号に該当する原料名 複数  

    1つ(単数行)のMedicalProd_IDに対して複数行のPharmNameが存在する可能性がある訳ですが

    それをどの様な形の表で取得したいのでしょうか?

     

    例1

    医薬品識別番号 医薬品名 医薬品識別番号に該当する原料名
    00001 医薬品1 原料1 原料2 原料3
    00002 医薬品2 原料1 原料2

     

    例2

    医薬品識別番号 医薬品名 医薬品識別番号に該当する原料名
    00001 医薬品1 原料1
    00001 医薬品1 原料2
    00001 医薬品1 原料3
    00002 医薬品2 原料1
    00002 医薬品2 原料2

    2009年1月7日 19:27
  • Karashimaさま、

     

    丁寧に表まで作っていただき本当にありがとうございます。

    明朝、関連するデータベースがどのような構造になっているのか確認してみます。

    このコンピュータからはアクセスできないので。

     

    こんなにすぐに返答いただきながらすぐに確認がとれず申し訳ないです。

     

    Mimmi

     

     

     

     

     

    2009年1月7日 22:01
  •  mimmiarne さんからの引用

    明朝、関連するデータベースがどのような構造になっているのか確認してみます。

    # テーブル定義は先に説明して頂いた通りなのでしょうから

    確認したいのは

    mimmiarneさんがクエリの結果としてどの様なを望んでいるのかという事です。

    2009年1月8日 2:47
  • Karashimaさま、

     

    私の書き方が悪くて申し訳ありませんでした。他のデータベースはどのような表になっているのか確認するという意味だったのですが、確認したところ原料に関してはKarashimaさまに書いていただいた例の1番でした。

     

    (ただし医薬品の分量、型が違っている場合では例の2番に則っています。)

     

    このデータベースは私が当初、考えていたものよりはかなり複雑なようです(私レベルにとっては)。いろいろと盲点を指摘して下さりありがとうございます。データベースの論理だけは以前、勉強したのですが、実際にどのように表示するかになるといろいろ考えなければいけないことがたくさんありますね。

     

    Mimmi

     

     

     

     

    2009年1月8日 9:55
  • phmName の中には PharmName 以外にも PharmName_ID 他の情報も入れるのでは

    ないのですか? であれば、phmName には DataTable を格納しなければなりません。

    その前提で、以下の手順を提案します。PharmName だけでよいということであれば、も

    う少し簡単にできますが、基本的には以下の手順と同様です。

     

    (1) MedicalProducts.xsd ファイルを作成し、そこにツールボックスから TableAdapter
        をドラッグ&ドロップし、「TableAdapter 構成ウィザード」を利用して MedicalProd の

        DataSet + TableAdapter を作成。クエリは下記のようにします。

     

        SELECT   MedicalProd_ID, MedicalProdName, MedicalProdTradeName
        FROM     MedicalProd

     

        その後、デザイナ画面のテーブルを右クリックして、[追加]→[列]で phmName
        列を追加。

     

    (2) 同じ xsd の画面にツールボックスからもう一つ TableAdapter をドラッグ&ドロッ
        プし、クエリビルダで PharmName テーブルと PhermProd テーブルの二つを追加。
      クエリは下記のようにします。

     

        SELECT   PharmName.PharmName_ID, PharmName.PharmName
        FROM     PharmName INNER JOIN
                   PharmProd ON PharmName.PharmName_ID = PharmProd.PharmName_ID
        WHERE    (PharmProd.MedicalProd_ID = @MedicalProd_ID)

     

    (3) GetMedicalProd() を partial class に実装。以下のような感じです。

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.ComponentModel;
    using System.IO;

    namespace MedicalProductsTableAdapters
    {
        public partial class MedicalProdTableAdapter
        {
            [DataObjectMethod(DataObjectMethodType.Select, true)]
            public MedicalProducts.MedicalProdDataTable GetMedicalProd()
            {
                MedicalProducts.MedicalProdDataTable medicalTable = this.GetData();
                PharmNameTableAdapter adapter = new PharmNameTableAdapter();

                foreach (MedicalProducts.MedicalProdRow row in medicalTable.Rows)
                {
                    MedicalProducts.PharmNameDataTable pharmTable = adapter.GetData(row.MedicalProd_ID);
                    StringWriter writer = new StringWriter();
                    pharmTable.WriteXml(writer);
                    row.phmName = writer.ToString();
                }

                return medicalTable;
            }
        }
    }

     

     

    (4) データを表示する Web フォーム(aspx ファイル)を作成。ObjectDataSource と
        GridView を利用した例は下記の通りです。phmName の xml データは GridView の
        RowDataBound イベントで適宜書き換えます。この例では、xml データを DataTable
        に戻して、GridView の中にもう一つ GridView を作って表示しています。

     





    Code Snippet




    <%@ Page Language="C#" %>
    <%@ Import Namespace="System.IO" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <script runat="server">

        protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                string xmlPharmTable = Server.HtmlDecode(e.Row.Cells[3].Text);
                StringReader reader = new StringReader(xmlPharmTable);
                MedicalProducts.PharmNameDataTable pharmTable = new MedicalProducts.PharmNameDataTable();
                pharmTable.ReadXml(reader);
                GridView gridView = new GridView();
                gridView.DataSource = pharmTable;
                e.Row.Cells[3].Controls.Clear();
                e.Row.Cells[3].Controls.Add(gridView);
                gridView.DataBind();
            }
        }
    </script>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:ObjectDataSource ID="ObjectDataSource1"
                runat="server"
                OldValuesParameterFormatString="original_{0}"
                SelectMethod="GetMedicalProd"
                TypeName="MedicalProductsTableAdapters.MedicalProdTableAdapter">
            </asp:ObjectDataSource>
            <asp:GridView ID="GridView1"
                runat="server"
                AutoGenerateColumns="False"
                DataKeyNames="MedicalProd_ID"
                DataSourceID="ObjectDataSource1" onrowdatabound="GridView1_RowDataBound">
                <Columns>
                    <asp:BoundField DataField="MedicalProd_ID" HeaderText="MedicalProd_ID"
                        ReadOnly="True" SortExpression="MedicalProd_ID" />
                    <asp:BoundField DataField="MedicalProdName" HeaderText="MedicalProdName"
                        SortExpression="MedicalProdName" />
                    <asp:BoundField DataField="MedicalProdTradeName"
                        HeaderText="MedicalProdTradeName" SortExpression="MedicalProdTradeName" />
                    <asp:BoundField DataField="phmName" HeaderText="phmName"
                        SortExpression="phmName" />
                </Columns>
            </asp:GridView>
        </div>
        </form>
    </body>
    </html>

     

     

     

    2009年1月8日 15:20
  • SurferOnWwwさん、

     

    これを考えてくださるのには随分時間が掛かったのではなかろうかと思います。本当にありがとうございます。

    早速試してみました。

     

    >phmName の中には PharmName 以外にも PharmName_ID 他の情報も入れるのではないのですか?

     

    はい、あと2、3、重要な情報項目が出てきました。

     

    ご提案いただいたプロセスの(1)は出来ました。

    (2)のTableAdapterも出来ましたが、途中「この場合はDelete,Insert,Editはサポートされない」という警告が出ました。一つのTableAdapterで複数のテーブルを扱えるとは知りませんでした。大変、参考になりました。

     

    また、質問なのですが、以下のクエリで出来たTableAdapterはPharmNameTableAdapterであり、MedicalProdTableAdapterとの間に同一のPrimaryKey, ForeignKeyが無いため、この場合Fig31 http://static.asp.net/asp.net/images/dataaccess/01fig31cs.png

    のようなRelationの線を追加することが出来ないのですが、何か工夫はあるのでしょうか?

     

    Code Snippet

    SELECT   PharmName.PharmName_ID, PharmName.PharmName
        FROM     PharmName INNER JOIN
                   PharmProd ON PharmName.PharmName_ID = PharmProd.PharmName_ID
        WHERE    (PharmProd.MedicalProd_ID = @MedicalProd_ID)

     

     

    (3)は多少アレンジさせていただいてMedicalProd.BLLファイルに追加させていただきましたがまだ多少エラーが出ます。明日、StringWriterのReferenceを追加して再度トライします。全てが機能したら、いただいた(4)を試します。

     

    ところでSurferOnWwwさんはASPでプログラムを作られるときはやはりxsdファイル、TableAdapter等を使われるのですか?

     

    零下12度の僻地で凍えながらやっているので皆様からのアドバイスは本当に心温まります。

     

    Mimmi

     

     

    2009年1月8日 22:41
  • > 途中「この場合はDelete,Insert,Editはサポートされない」という警告が出ました。

     

    さすがに複数のテーブルを Delete, Insert, Update するような機能はないよ
    うです。表示するだけなら、その警告は気にする必要はありません。その機能
    が必要ということですと、話がかなりややこしくなってきますが、必要なので
    しょうか?

     

    > また、質問なのですが、以下のクエリで出来たTableAdapterはPharmNameTableAdapterで
    > あり、MedicalProdTableAdapterとの間に同一のPrimaryKey, ForeignKeyが無いため、
    > この場合Fig31 http://static.asp.net/asp.net/images/dataaccess/01fig31cs.png
    > のようなRelationの線を追加することが出来ないのですが、何か工夫はあるのでしょうか?

     

    自分が検証に使ったテーブルは ForeignKey の設定はしていません、各テーブルの
    Xxxxxx_ID を PrimaryKey に設定したのみです。クエリビルダーで PharmName テ
    ーブルと PhermProd テーブルの二つを追加するだけで以下のクエリが自動生成さ
    れ、PharmName_ID が線でつながって表示されるはずです。

     

    SELECT
    FROM     PharmName INNER JOIN
                PharmProd ON PharmName.PharmName_ID = PharmProd.PharmName_ID

     

    これにクエリビルダで SELECT する項目と WHERE の条件を加えただけです。

     

    > ASPでプログラムを作られるときはやはりxsdファイル、TableAdapter等を使われるのですか?

     

    自分のレベルではそれらの助けなしではできないので、可能な限り使っています。

    2009年1月9日 15:35
  • 金曜日まで返答ありがとうございます。非常に助かります。

     

    >さすがに複数のテーブルを Delete, Insert, Update するような機能はないよ
    うです。表示するだけなら、その警告は気にする必要はありません。その機能
    が必要ということですと、話がかなりややこしくなってきますが、必要なので
    しょうか?

     

    このシステムを使い200,000品の医薬品をボタン一つで製造元名、医薬品型名、原料名等も同時にInsertしなければならず、またUpdate、およびDeleteの必要もかなり頻繁にあるのでその機能はかなり必要になるのですが、もしこのxsdとTableAdapterの方法が使えないとなると根本的にやり直さなければならないわけですよね。xsdとTableAdapterの組み合わせで複数テーブルを同時に Delete, Insert, Update するような機能は皆無なのでしょうか?それともややこしい方法を使えばこの組み合わせでも可能なのでしょうか。こういうケースって結構あるような気がするのですけど。

     

    >自分のレベルではそれらの助けなしではできないので、可能な限り使っています。

     

    SurferOnWwwさんのレベルでも限界があるなんてASPとは当初思ったより難しいのですね。

     

    データ表示に関して組んでいただいたコード、未だに成功していないのですが、なんとかこの週末には結果を出したいと思っています。いつも本当にありがとうございます。

     

    Mimmi

    2009年1月10日 18:11
  •  mimmiarne さんからの引用

    このシステムを使い200,000品の医薬品をボタン一つで製造元名、医薬品型名、原料名等も同時にInsertしなければならず、またUpdate、およびDeleteの必要もかなり頻繁にあるのでその機能はかなり必要になるのですが、もしこのxsdとTableAdapterの方法が使えないとなると根本的にやり直さなければならないわけですよね。xsdとTableAdapterの組み合わせで複数テーブルを同時に Delete, Insert, Update するような機能は皆無なのでしょうか?それともややこしい方法を使えばこの組み合わせでも可能なのでしょうか。こういうケースって結構あるような気がするのですけど。

     

    xsd ファイル作成のデザイナで、ウィザードベースで作成される Insert,
    Update, Delete の機能は、チュートリアルの Step 4 に述べられている
    通りですが、これは一つのテーブルしか対象としていないです。

     

    複数のテーブルを更新する際、特に問題となるのは途中で更新が失敗した
    時の対応です。例えば、MedicalProd テーブルと PharmName テーブルの
    2つを更新する場合、MedicalProd の更新が成功した後、PharmName の更
    新に失敗しすると、テーブル間のデータに矛盾が出ることがあると思いま
    す。その場合、更新前の状態に巻き戻してやる(トランザクション制御)
    必要がありますが、そのためのコードはウィザードベースでは作成できな
    いです。

     

    しかしながら、今回 GetMedicalProd() を partial class に実装したよ
    うに自力でコードを書けば(それが「ややこしい方法」という訳です)、
    できないことはほとんどないはずで、トランザクション制御を含めて複
    数のテーブルを同時に更新することは可能です。

     

    したがって、今回のやり方を根本的にやり直す必要はないと思います。

     

    2つのテーブルを更新する話は、以前、以下のスレッドで話題になった
    ことがありますので、時間があれば見てください。

     

    2つのテーブルを一括更新する方法を教えてください
    http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=3871518&SiteID=7

    2009年1月11日 4:50
  • 先の回答で、質問の意味を一つ勘違いして回答していたようです。遅すぎたかもしれません
    が、以下の通り回答を修正します。

     

    > また、質問なのですが、以下のクエリで出来たTableAdapterはPharmNameTableAdapterで
    > あり、MedicalProdTableAdapterとの間に同一のPrimaryKey, ForeignKeyが無いため、
    > この場合Fig31 http://static.asp.net/asp.net/images/dataaccess/01fig31cs.png
    > のようなRelationの線を追加することが出来ないのですが、何か工夫はあるのでしょうか?

     

    質問は、MedicalProd テーブルと PharmName テーブルのフィールドに同じ項目がなく FK
    の設定ができない(xsd ファイルをデザイナ画面で見たとき、Relationの線を追加するこ
    とが出来ない)のに、MedicalProd_ID を抽出条件として PharmName テーブルから該当す
    る PharmName を抽出/取得する工夫は何かということですね。

     

    それは先にアップした GetMedicalProd() メソッドのコードで、以下の部分です。

     

    Code Snippet

    MedicalProducts.MedicalProdDataTable medicalTable = this.GetData();
    PharmNameTableAdapter adapter = new PharmNameTableAdapter();

    foreach (MedicalProducts.MedicalProdRow row in medicalTable.Rows)
    {
        MedicalProducts.PharmNameDataTable pharmTable = adapter.GetData(row.MedicalProd_ID);
        ・・・中略・・・
    }

     

     

    まず、this.GetData() で MedicalProd テーブルのデータを取得して DataTable を作り
    り、foreach でループを回して、一行ずつその DataTable から MedicalProd_ID を取得
    して、adapter.GetData(row.MedicalProd_ID) で以下のクエリをかけているわけです。

     

    Code Snippet

    SELECT   PharmName.PharmName_ID, PharmName.PharmName
        FROM     PharmName INNER JOIN
                   PharmProd ON PharmName.PharmName_ID = PharmProd.PharmName_ID
        WHERE    (PharmProd.MedicalProd_ID = @MedicalProd_ID)

     

     

    2009年1月11日 6:09
  • こんにちは、

     

    根本的に直さなくてよいということで安心しました。ありがとうございます。道は険しそうですが…(納期は一月末ですし)

     

    すみませんがエラーが抜けないので自分がSurferOnWwwさんの提案を正しく理解しているのか確認させていただいてよろしいですか?

     

    http://www.asp.net/Learn/data-access/tutorial-02-vb.aspxの例に倣ってBLLを作っているのですが、以下のコードは私の場合、MedicalProdBLLに実装すると理解したのですが、合っていますか? これに関してはエラーフリーになりました。

     

    Code Snippet

    MedicalProducts.MedicalProdDataTable medicalTable = this.GetData();
    PharmNameTableAdapter adapter = new PharmNameTableAdapter();

    foreach (MedicalProducts.MedicalProdRow row in medicalTable.Rows)
    {
        MedicalProducts.PharmNameDataTable pharmTable = adapter.GetData(row.MedicalProd_ID);
        ・・・中略・・・
    }

     

     

     

    PharmNameBLLも作ったのですが、しかしそこに赤線の部分を追加すると

    "The name 'MedicinalProd_ID' does not exist in the current context" のエラーが出てしまいます、いろいろと代えてみたりもしたのですが私はこの辺で何か作業を見落としているか勘違いしているのでしょうか?

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.ComponentModel;

    [System.ComponentModel.DataObject]

    public class PharmNameBLL

    {

    private PharmNameTableAdapter_PharmNameAdapter=null;

    protected PharmNameTableAdapter Adapter

    {

    get

    {

    if(_PharmNameAdapter==null)

    _PharmNameAdapter=new PharmFormTableAdapter();

     

    return_PharmNameAdapter;

    }

    }

     

    [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]

    {

    return Adapter.GetPharmName(@MedicinalProd_ID)

    }

    }

     

     

     

    本当に何度もすみません、でもせっかく素晴らしい指針を提示していただいたので絶対に最後まで成功させたいのであと一息だけおつきあいいただけると嬉しいです。

     

    Mimmi

    2009年1月11日 15:20
  •  mimmiarne さんからの引用

    このシステムを使い200,000品の医薬品をボタン一つで製造元名、医薬品型名、原料名等も同時にInsertしなければならず、またUpdate、およびDeleteの必要もかなり頻繁にあるのでその機能はかなり必要になるのですが、もしこのxsdとTableAdapterの方法が使えないとなると根本的にやり直さなければならないわけですよね。xsdとTableAdapterの組み合わせで複数テーブルを同時に Delete, Insert, Update するような機能は皆無なのでしょうか?それともややこしい方法を使えばこの組み合わせでも可能なのでしょうか。こういうケースって結構あるような気がするのですけど。


    1つのTableAdapterで
    複数テーブルを同時に更新する必要はないのではないでしょうか。

    2009年1月11日 19:45
  • karashimaさんこんにちは、

     

    一つのTableAdapterでなくても複数テーブルを更新できれば良いのですが、Display段階でこれだけつまずいているのでまだ更新方法に関しては具体的に考えている段階ではないのですが、この問題が無事、解決したら、SurferOnWwwさんにいただいたLinkやBatch Updating、Batch Insertに関するTutorialを実践してみようと思っております。

     

    karashimaさんは複数テーブルは複数のTableAdapterで更新されているのですか?

     

    Mimmi

     

     

     

    2009年1月11日 20:53
  •  mimmiarne さんからの引用

    一つのTableAdapterでなくても複数テーブルを更新できれば良いのですが、Display段階でこれだけつまずいているのでまだ更新方法に関しては具体的に考えている段階ではないのですが、この問題が無事、解決したら、SurferOnWwwさんにいただいたLinkやBatch Updating、Batch Insertに関するTutorialを実践してみようと思っております。

     

    karashimaさんは複数テーブルは複数のTableAdapterで更新されているのですか?

    # 普段、型付けされたデータセットを使用していないので、問題に気付いてないだけかもしれませんが

     

    医薬品、原料のテーブルの登録処理も要件に含まれているという前提で書きますが

    各TableAdapterに必要なのは下記の処理だと思います。

    TableAdapter 対象のテーブル 必要な更新処理
    MedicalProdTableAdapter MedicalProd 追加・更新・削除
    PharmNameTableAdapter PharmName 追加・更新・削除
    PharmProdTableAdapter PharmProd 追加・削除

     

    登録画面は大きく分けて2つ
    ・医薬品(MedicalProd)登録画面
    ・原料(PharmName)登録画面
     医薬品と原料の関連付け(PharmProd)に関しては
     今回の場合、医薬品登録画面に組み込むという形になるという事ですね。
     # (医薬品に必要な原料の)追加登録には他にも選択画面等が必要ですが。

     

    現在、mimmiarneさんが作成されているのが、医薬品登録画面(医薬品と原料の関連付けも含む)ですよね。

    医薬品情報に関連付けられている原料情報の追加・削除が

    医薬品情報が実際にデータベースに書き込まれるまでは画面表示上だけであるという仕様であったとしても

    医薬品情報が実際にデータベースに書き込まれるタイミングで

    PharmProdTableAdapterの各メソッド(追加・削除)を呼べばよいだけではないでしょうか?

     

    # そこまで厳密にやる必要がなければ、もう少し簡単だと思います。

     

    今、思い付いているのは

    PharmProdTableAdapterに

    MedicalProd_IDをパラメータにした2つクエリ

      ・(PharmNameテーブルを結合した)「複数行を返す SELECT」クエリ

      ・「DELETE」クエリ

    を追加、他はほぼデフォルトのまま。

    というデータセットを作成した前提で話しています。

    2009年1月11日 22:09
  • > http://www.asp.net/Learn/data-access/tutorial-02-vb.aspxの例に倣ってBLLを
    > 作っているのですが、以下のコードは私の場合、MedicalProdBLLに実装すると理解
    > したのですが、合っていますか? これに関してはエラーフリーになりました。

     

    違います。「エラーフリーになりました」というのが不思議ですが、MedicalProdBLL
    クラスではありません。

     

    MedicalProdBLL クラスファイルとは別に、App_Code に新たにクラスファイルを追加し、
    xsd ファイルから自動生成される MedicalProdTableAdapter クラスを拡張する形で
    public partial class MedicalProdTableAdapter として実装してください。

     

    クラス名 MedicalProdTableAdapter は、mimmiarne さんが作った DB のテーブル名が、
    質問にあったとおり MedicalProd であるというのが前提ですので注意してください。

     

    私のレスの手順 (3) のコードをそのままコピー&ペーストして、namesapce 名、クラ
    ス名、メソッド名を mimmiarne さんが作った xsd ファイル名や DB のテーブル名に
    あわせて修正すれば使えるはずです。(xsd ファイル名が MedicalProducts、DB のテ
    ーブル名が MedicalProd, PharmName、メソッド名がデフォルト (GatData) であれば、
    修正不要のはずです)

     

    チュートリアルでは Business Logic Layer をすべて XxxxxBLL クラスにまとめるた
    めに、GetData 等のメソッドも XxxxxBLL クラスにラップしていますが、それは便宜
    上そうしているだけで、must ではないです。

     

    必要であれば、partial class MedicalProdTableAdapter に作ったメソッド(サンプ
    ルでは GetMedicalProd)を MedicalProdBLL クラスに実装できます。ただ、私のレ
    スの手順 (4) のコードように、とりあえず表示できることを試すだけなら全く必要
    ないです。

     

    > PharmNameBLLも作ったのですが、しかしそこに赤線の部分を追加すると
    > "The name 'MedicinalProd_ID' does not exist in the current context" のエラ
    > ーが出てしまいます、いろいろと代えてみたりもしたのですが私はこの辺で何か作業
    > を見落としているか勘違いしているのでしょうか?

     

    PharmNameBLL は作る必要はありません。(将来、コードを拡張して、Business Logic
    Layer をすべて XxxxxBLL クラスにまとめたいというときに作ればいいです)

     

    とは言え、一応アップされた PharmNameBLL クラスのコードを直して、コメントして
    おきます。

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.ComponentModel;

    // 名前空間が必要
    namespace MedicalProductsTableAdapters
    {
        [System.ComponentModel.DataObject]
        public class PharmNameBLL
        {
            // クラス名と変数がつながってしまっていた(空白が必要)
            private PharmNameTableAdapter _PharmNameAdapter = null;
            protected PharmNameTableAdapter Adapter
            {
                get
                {
                    if(_PharmNameAdapter==null)
                        // コンストラクタの名前が間違っていた
                        _PharmNameAdapter = new PharmNameTableAdapter();
                    // キーワードと変数がつながってしまっていた(空白が必要)
                    return _PharmNameAdapter;
                }
            }

            [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]
            // メソッドの宣言(以下の一行)がなかった
            public MedicalProducts.PharmNameDataTable GetPharmNameByMedicalProductId(int MedicalProd_ID)
            {
                // デフォルトでは GetData になるはず。加えて ; がなかった
                return Adapter.GetData(MedicalProd_ID);
            }
        }
    }

     

     

    2009年1月12日 2:09
  •  mimmiarne さんからの引用

    ・・・Display段階でこれだけつまずいているのでまだ更新方法に関しては具体的に考えている段階ではないのですが、この問題が無事、解決したら、・・・

     

    余計なお世話かもしれませんが、どのような画面でどのように更新をかけるかの概略

    を考えて、最初の表示画面を考えておいたほうがいいと思います。

     

    問題が解決して無事表示できるようになったとしても、更新を考えたときにそれが使え

    ず、時間の無駄になる可能性がありますので。

    2009年1月12日 2:31
  • karashimaさま、

     

    返信をありがとうございました。

    そうですね、改めて考慮してみたら全て更新する必要はないようですね。提案をいただいてから考え直しましたがインターフェイスをつくる段階で、そうですね、PharmProdに関しては特に更新をする必要はないかもしれないですね。医薬品と原料の組み合わせが将来的に変わる可能性もありますが、今の段階で複雑なことに挑戦してプログラムが動かなくても困りますしね。

    ボタン一つで全て変更、と発注先に言われたことにこだわりすぎていたかもしれません。

     

    インターフェイスを作る段階でプロセスを二段階に分けて考えてみようかと思っています。

    考えが及ぶばなかった点に気が付かせていただいてありがとうございます。20個以上のテーブルに囲まれてジャングルに入っているような状態ですが、ちょっと灯りが見えてきたような感じです。

     

    MimmiArne

     

     

     

    2009年1月13日 9:41
  • SurferOnWwwさん、

     

    すみません、全て新しく作り直し、いただいたコードの通りに命名しコピーペーストをしたのですが今度はXSDで下記のエラーが出てしまいました。

     

    Type 'MedicalProductsTableAdapters.MedicalProdTableAdapter' already defines a member called 'GetMedicalProd' with the same parameter types

    ちょっと頭を冷やしてからやりなおして見ますので結果の報告は今しばらくお待ち下さい。申し訳ないです。

     

    MimmiArne

     

     

    2009年1月13日 9:48
  •  mimmiarne さんからの引用

    Type 'MedicalProductsTableAdapters.MedicalProdTableAdapter' already defines a member called 'GetMedicalProd' with the same parameter types

    ちょっと頭を冷やしてからやりなおして見ますので結果の報告は今しばらくお待ち下さい。申し訳ないです。

     

    考えている途中で余計なインプットはしないほうが良いかもしれませ
    んが、ちょっと一言。

     

    エラーメッセージによれば、すでにどこかで MimmiArne さんが
    GetMedicalProd という名前のメソッドを作っていて、それと今回

    作成したメソッドと名前がダブっているようです。

     

    先のメッセージで「各TableAdapterにはメソッドを作成するところが
    あるのですが、MedicalProductTableAdapterのGetMedicalProd()の
    ところで以下のSQLを使って・・・」と書いてありました。それが残
    っているのでは?

     

    そうであれば、それはとりあえずそのまま置いといて、今回新たに作
    成するメソッドの名前を GetMedicalProd とは別の名前にしてやれば
    解決するはずです。(ただし、Multi-part Identifier could not be
    bound エラーの問題がまだ残っているなら、それを解決しなければな
    りませんが)

     

    なお、名前を変えた場合は、先のレスの手順 (4) の ObjectDataSorce
    の SelectMethod プロパティの設定を、その、変えた方の名前にする
    必要がありますので、お忘れなく。

    2009年1月13日 13:48
  • ありがとうございます。決して余計なインプットではありません。ガス欠で倒れ掛かっているバイクにガスを入れてくださった気分です。

     

    新しくDatabaseを作り直してまっさらな状態でテーブルとTableAdapterを作ってトライしました。

     

    今日、また再度、新しいデータベースを作ってTableAdapterを作ったらGetData()のTableAdapterはなんとInsert、Updateも生成されました。

     

    しかし、前回のエラーはいろいろを名前を変えてみてもあいかわらず出てきてしまいます。あと一息だというのに本当にわけがわかりません。そういうわけなのでObjectDataSource1も指定できません。ちなみにApp Codeに実装したPartialClass名もGetProduct.cs、GetProduct().cs, GetProduct2.cs, GetProduct2().csとか変えてみましたが。そのcsファイルと default.aspにGetProductと指定してあるところもGetProduct2に変えたのですが、

                   

    Type 'MedicalProductsTableAdapters.MedicalProdTableAdapter' already defines a member called 'GetMedicalProd' with the same parameter types

     

    のGetMedicalProdの部分がGetMedicalProd2に変わるだけで、エラーは同じです。あれほど素晴らしい解決策を提示していただいたのにいまだに実現させられないとは情けないです。

     

    MimmiArne

     

    2009年1月14日 10:10
  • 話が前後しますが大事な方から。

     

    > ちなみにApp Codeに実装したPartialClass名もGetProduct.cs、
    > GetProduct().cs, GetProduct2.cs, GetProduct2().csとか変えてみま
    > したが。そのcsファイルと default.aspにGetProductと指定してあると
    > ころもGetProduct2に変えたのですが、

     

    ひょっとして、ファイル名を変えていませんか? そうではなくて、メソ
    ッド名を変えるのですが。以下の部分です。ファイル名は何でもかまいま
    せん。

     

    Code Snippet

    namespace MedicalProductsTableAdapters
    {
        public partial class MedicalProdTableAdapter
        {
            [DataObjectMethod(DataObjectMethodType.Select, true)]
            public MedicalProducts.MedicalProdDataTable GetMedicalProd()  // ←これ
            {
                MedicalProducts.MedicalProdDataTable medicalTable = this.GetData();
                ・・・中略・・・
                return medicalTable;
            }
        }
    }

     

     

    > 今日、また再度、新しいデータベースを作ってTableAdapterを作った
    > らGetData()のTableAdapterはなんとInsert、Updateも生成されました。

     

    PharmName テーブルのみを更新するメソッドは自動生成されますが、もう
    一つの方の PharmProd テーブルを更新できるようにはなってないはずです。
    2つ以上のテーブルを更新できるコードは自動生成されないのです。

    2009年1月14日 13:18
  • んにちは、

     

    なんどもすみません。csファイルのメソッド名もいろいろ変えて、その度、もちろんaspxのメソッド名のところもを変えましたが駄目だったので、いろいろとやってみたわけです。時々思ってもいなかったようなことがエラーを発生させたりしますので(私の場合)

     

     

    App_Codeの中にはGetMedicinalProd.cs (いただいたコード)とMedicalProducts.xsdを入れました。もう一つのGridViewのファイルの方はDefault.aspxに入れました。

     

    MedicalProducts.xsdの中にはMedicalProdTableAdapterとPharmNameTableAdapterを入れ、

     

    MedicalProdTableAdapterのメソッドのSQLは

    SELECT     MedicalProd.*
    FROM         MedicalProd

     

    でメソッド名はFill, GetMedicalProd() 

    こちらもGetMedicalProd2()とかに変えてみたりいろいろやってみましたが。

     

    PharmNameTableAdapterのメソッドのSQLはいただいた

     

     SELECT PharmName.PharmName_ID, PharmName.PharmName
    FROM PharmName INNER JOIN
    PharmProd ON PharmName.PharmName_ID=PharmProd.PharmName_ID
    WHERE (
    PharmProd.MedicalProd_ID=@MedicalProd_ID)

     

    でメソッド名はFill, GetData()です。

     

    これが私の理解なのですが、出来るはずのないコードが生成されたり、本当に不可解です。

     

    嬉しいニュースがなかなか報告できなくてすみません。

     

    MimmiArne

     

    2009年1月14日 15:59
  •  mimmiarne さんからの引用

    MedicalProdTableAdapterのメソッドのSQLは

    SELECT     MedicalProd.*
    FROM         MedicalProd

     

    でメソッド名はFill, GetMedicalProd() 

    こちらもGetMedicalProd2()とかに変えてみたりいろいろやってみましたが。


    # 斜め読みしているので、的外れな事言っていたらすみません。

    こちらもデフォルトの「Fill, GetData()」でよいのではないでしょうか?

    以前にSurferOnWwwさんがアップされたコードの

    MedicalProdTableAdapterクラスのGetMedicalProdメソッドの中で

    下記の様に呼ばれているようなので。

     

    MedicalProducts.MedicalProdDataTable medicalTable = this.GetData();

    2009年1月14日 17:30
  • karashimaさま、

     

    的外れどころではなく、大当たりでした。

    突然、美しいGridViewが表示されました。

    感激の一瞬でした。

     

    こんどはkarashimaさんの例にあった例2のGridViewの方をトライしなければいけませんがきっとこのスレッドでいただいたコードをのGridViewに関する部分をアレンジして再利用すればいいと思いますので、すんなり行くような気がします(楽観的すぎるかもしれませんが)。そうすればなんとか納期までに間に合うような気もしてきました。これが無事納入出来たらADO、およびCシャープをきちんと勉強する予定です。

     

    お二方、本当に長い間見捨てないで下さりありがとうございました。

    プログラミング方面でお礼ができるようになることは今の段階では難しいかもしれませんが、ストックホルムにいらした際は是非声を掛けて下さいませ。精一杯ご案内させていただきます。

     

    MimmiArne

     

    2009年1月15日 12:35
  • MimmiArne さん>

    うまくいったようで、よかったです。

    デフォルトのメソッド名 GetData を GetMedicalProd に変えた
    のは想定外でした。チュートリアルと同じようにしたのですね。
    気がつきませんでした。


    karashima さん>

    フォローを有難うございました。

    2009年1月15日 13:12