C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: データベースからのデータ読込


(過去ログ 139 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■81800 / inTopicNo.1)  データベースからのデータ読込
  
□投稿者/ 夜叉丸 (11回)-(2016/11/15(Tue) 14:41:20)

分類:[C#] 

以下のエラーメッセージが表示されます。
「制約を有効にできませんでした、行に入力できるのは・・・」

調べてみると EnforceConstraints を使うとありますが
使い方がわかりません。

データセットは MAINDataSet と SUBDataSet があり、
以下のようなデータベースのデータがあり

MAINDataSet.dbo.Main (キーは NAME です。)
NAME NUM
A 1
B 2

SUBDataSet.dbo.Sub (キーは SUBNAME です。)
NAME SUBNAME
A a1
A a2
B b1
B b2

Main のデータにSub を JOIN して以下のデータを取得します。
NAME NUM SUBNAME
A 1 a1
A 1 a2
B 2 b1
B 2 b2


キーはNAMEしかないのでエラーが出るのはわかったのですが

どうすればこのデータをとってくることができますか?
引用返信 編集キー/
■81802 / inTopicNo.2)  Re[1]: データベースからのデータ読込
□投稿者/ 魔界の仮面弁士 (945回)-(2016/11/15(Tue) 14:59:16)
No81800 (夜叉丸 さん) に返信
> データセットは MAINDataSet と SUBDataSet があり、

一つの DataSet 内に、Main テーブルと Sub テーブルがあるのではなく、
Main テーブル用の DataSet (MAINDataSet)と
Sub テーブル用の DataSet (SUBDataSet) があるということでしょうか。


どういうコードを書いているのか分かりませんが、
「JOIN した結果を格納する DataTable」の列定義が
どのように設定されているのかを、まずは確認してみてください。
引用返信 編集キー/
■81803 / inTopicNo.3)  Re[1]: データベースからのデータ読込
□投稿者/ 魔界の仮面弁士 (946回)-(2016/11/15(Tue) 15:14:37)
No81800 (夜叉丸 さん) に返信
> Main のデータにSub を JOIN して以下のデータを取得します。

サーバー側に再問い合わせしたり、LINQ を使ってみるなど、
やり方はいろいろと考えられますが、現時点で
Main / Sub のデータを既に DataSet に読み込んでいるならば、
一つの DataSet 上に DataRelation を貼っておき、
Sub 側に「親テーブルの NUM 列」を式列として追加するのが
手っ取り早い気がします。



// 一つの DataSet 内に二つのDataTable
var ds = new DataSet();
var tblM = ds.Tables.Add("dbo.Main");
var tblS = ds.Tables.Add("dbo.Sub");

// このあたりはテーブル定義なので、
// 型付きDataSet を使うのならば意識しなくてOK
tblM.PrimaryKey = new DataColumn[] { tblM.Columns.Add("NAME") };
tblM.Columns.Add("NUM", typeof(decimal));

tblS.Columns.Add("NAME");
tblS.PrimaryKey = new DataColumn[] { tblS.Columns.Add("SUBNAME") };

// とりあえず実験用データの登録
tblM.Rows.Add("A", 1m);
tblM.Rows.Add("B", 2m);
tblM.AcceptChanges();
tblS.Rows.Add("A", "a1");
tblS.Rows.Add("A", "a2");
tblS.Rows.Add("B", "b1");
tblS.Rows.Add("B", "b2");
tblS.AcceptChanges();

// ここから本題
// JOIN 操作のために式列(Expression Column)を利用してみます
ds.Relations.Add("Main_Sub", tblM.Columns["NAME"], tblS.Columns["NAME"]);
tblS.Columns.Add("NUM", tblM.Columns["NUM"].DataType, "Parent.NUM");


これで、tblS 上に、NAME, SUBNAME, NUM の 3 列が構成されます。
(DataRelation は、型付き DataSet 上であらかじめ構築しておくこともできます)
引用返信 編集キー/
■81804 / inTopicNo.4)  Re[2]: データベースからのデータ読込
□投稿者/ 夜叉丸 (13回)-(2016/11/15(Tue) 15:37:12)
魔界の仮面弁士さんありがとうございます。

少し難しくて理解できないのですが、

VisualStudioを使用しています。
データソースを使用して、サーバーにあるデータベースのデータのDataSetを作りました。

プロジェクトに以下のファイルが追加されます。
1.MAINDataSet.xsd 他が追加されます。
2.SUBDataSet.xsd 他が追加されます。

MainDataSet.xsd のデザイン編集で
クエリの追加を行って以下のコードを記入します。

SELECT A1.NAME, A1.NUM, A2.SUBNAME
FROM MAINDataSet AS A1
LEFT OUTER JOIN AS A2
ON A1.NAME = A2.NAME

DataTable を返す にて GetMainSubName にして登録


public class GetMain
{
static MAINDataSetAdapters.MainTableAdapter adpt = new MAINDataSetAdapters.MainTableAdapter();

pubic static MainDataSet.MainDataTable GetMainSubName()
{
return(adpt.GetMainSubName());
}
}

この GetMain.GetMainSubName()を呼び出すとエラーになります。

以下のように Main の NAME を変更すればデータは読み出すことは
できるとは思いますが、本意ではありません。

SELECT A1.NAME + ',' + A2.SUBNAME AS NAME, A1.NUM, A2.SUBNAME
FROM MAINDataSet AS A1
LEFT OUTER JOIN AS A2
ON A1.NAME = A2.NAME

EnforceConstraints を使えばよいらしいですが
どのようにすればよいのでしょうか?
引用返信 編集キー/
■81805 / inTopicNo.5)  Re[3]: データベースからのデータ読込
□投稿者/ 魔界の仮面弁士 (947回)-(2016/11/15(Tue) 16:03:49)
No81804 (夜叉丸 さん) に返信
> MainDataSet.xsd のデザイン編集で
> クエリの追加を行って以下のコードを記入します。

Main 側に追加しているのだとしたら、まずそこが間違っています。

Main テーブルは NAME をキーとしており、
現時点で 2 行のデータが入る事が期待されますよね。


しかし作成した GetMainSubName のクエリーは、
SUBNAME をキー(あるいは PrimaryKey なし)とした、
4 行のデータであるはずです。

でもそれは Main ではなく、むしろ Sub のテーブルの構造ですよね?


ですからデザイン時に行う作業としては、以下のいずれかにしてみてください。

(案1) JOIN 結果の格納先は、Main でも Sub でもなく、
  別の DataTable として TableAdapter を構成する。

(案2) Sub テーブル側に、GetMainSubName のクエリーを追加する。


サーバー側に問い合わせを行うのなら、通常は案 1 で良いと思います。
Main や Sub は 2 列構成ですが、JOIN 結果は 3 列構成なので、
今回のケースではこれが妥当かと思います。

もしも案2 を選択するのであれば、Sub の DataTable に、デザイン時に
SUBNAME な列も追加しておけば OK です。(デザイン時に SUBNAME 列を
追加していなかったとしても、インデクサ指定で扱うことができます)

ただし、JOIN 結果のために SUBNAME 列を追加しておいた場合、
既定の GetData/Fill で取得したデータ(SUBNAME 列の無い SELECT SQL)では、
SUBNAME 列に入る値が無いため、その列の値は NULL 値として処理されます。


なお、編集結果をデータベース側に復元する事を考えているのであれば、
先の回答のように、リレーション構成にしてクライアント側で連結させるか、
あるいは、案2 を用いて、Sub の DataTable 側で処理すれば OK です。




> EnforceConstraints を使えばよいらしいですが

そもそも EnforceConstraints は既定で有効になっています。

EnforceConstraints が true な状態では、

・PrimaryKey な列に、同じデータが重複登録された場合
・MaxLength を超える長さのデータが登録された場合
・AllowDBNull = false な列が NULL 値の状態であった場合
・DataRelation に違反するようなデータ構成になった場合

などの不整合が検出され、エラー(というか例外)として通知されますが、
EnforceConstraints を切ってしまうと、そういった違反データを
DataTable に登録できてしまうことになりますよ。
引用返信 編集キー/
■81806 / inTopicNo.6)  Re[4]: データベースからのデータ読込
□投稿者/ 夜叉丸 (14回)-(2016/11/15(Tue) 16:18:29)
No81805 (魔界の仮面弁士 さん) に返信
>別の DataTable として TableAdapter を構成する。

これはあらかじめSQLServerManagementStudioで
Name と SubName をキーにしたテーブルを作っておくということでしょうか?
それとも SQLコード内で新たに NAME, SUBName をキーにしたテーブルを
作成してデータを返すことが可能なのでしょうか?



ちなみにいろいろ調べて、Get を Fill に変更して以下のようにするとデータを
取得することができましたが、これはやってはいけないことなのでしょうか?

pubic static MainDataSet.MainDataTable FillMainSubName()
{
 MainDataSet Main_DataSet = new Main_DataSet
 Main_DataSet.EnforceConstraints = false;
 adpt.FillMainSubName(Main_DataSet.MAIN);
 return(Main_DataSet.MAIN);
}
引用返信 編集キー/
■81808 / inTopicNo.7)  Re[5]: データベースからのデータ読込
□投稿者/ 魔界の仮面弁士 (948回)-(2016/11/15(Tue) 18:21:33)
No81806 (夜叉丸 さん) に返信
> これはあらかじめSQLServerManagementStudioで
> Name と SubName をキーにしたテーブルを作っておくということでしょうか?

SQL Server 側に、ビューやテーブルを用意しておく必要はありません。
C# 側の DataSet のみを編集すれば OK です。

ドロップ生成された型付き DataSet を編集してみてください。
デザイナ画面の余白部分(水色縞)を右クリックして、TableAdapter を作成し、
そこに JOIN クエリーを追加することで生成できます。
そのテーブルに、PrimaryKey の設定を施すかどうかは任意です。


> ちなみにいろいろ調べて、Get を Fill に変更して以下のようにするとデータを
> 取得することができましたが、これはやってはいけないことなのでしょうか?

一切の制約が無視されますので、あまりお奨めはしません。
データ加工などのために、一時的に制約をオフにする事はありますが、
基本的には制約を有効にしたままで運用されるべきものかと。

逆に、その制約が不要だというのなら、あらかじめデザイン時に
PrimaryKey 設定や列サイズなどといった不要な制約を、
最初から *.xsd のデザイン時に外しておけば良いわけで。

引用返信 編集キー/
■81820 / inTopicNo.8)  Re[6]: データベースからのデータ読込
□投稿者/ 夜叉丸 (15回)-(2016/11/16(Wed) 13:16:31)
No81808 (魔界の仮面弁士 さん) に返信

> デザイナ画面の余白部分(水色縞)を右クリックして、TableAdapter を作成し、
> そこに JOIN クエリーを追加することで生成できます。
> そのテーブルに、PrimaryKey の設定を施すかどうかは任意です。

テーブルの追加できるんですね。はじめて知りました。
これだと自由にテーブルが作れそうです。
どうも、ありがとうございました。


解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -