0

最新の編集!!!

お願いします...私はこのコードの多くの順列を経験してきました。データベース(SQLサーバー)から特定の関連レコードを取得してXMLにエクスポートし(これはうまくいくようです!)、そのデータベースの切断されたコピーにそれらを取得し、それらをそのデータベースにインポートして、プライマリでマージしようとしていますキー (キーが存在する場合は更新し、存在しない場合は挿入します)。

データベースには多くのテーブルがあり、変更されたエンティティの特定のリストに関連するすべてのテーブルが必要です。すべてのテーブル構造を失ったため、結合を使用して大規模で複雑なクエリを実行して、エクスポート DataSet に入力したいすべての列を取得できないことに早い段階で気付きました。また、Visual Studio 2005 の DataSet デザイナーに型指定されたデータセットを作成してもらいましたが、これを行う必要があるかどうかはわかりません。すべきでない場合は教えてください。

データをxmlにエクスポートするために私がやっていることは次のとおりです。



public void exportData(string filename, List sxOrgs) {

    MyGeneratedDataSet ds = new MyGeneratedDataSet();
    SqlDataAdapter adapter = new SqlDataAdapter();
    String query;
    String orgList = "(";
    //create the string query list of sxOrgs

    foreach (String sx in sxOrgs)
    {
        orgList += "'" + sx + "', ";
    }

    orgList = orgList.Remove(orgList.Length - 2);
    orgList += ")";

    try
        {

        //tblOrganization
        query = "select * from tblOrganization where tblOrganization.sxOrganization in " 
             + orgList;
        adapter.SelectCommand = new SqlCommand(query, Connectivity.Connection());
        adapter.Fill(ds.tblOrganization);

        //tblCategory
        query = "select * from tblCategory where sxCategory in " +
            "(select sxCategory from lnkOrganizationCategory " +
            "where lnkOrganizationCategory.sxOrganization in " +
            orgList + ")";
        adapter.SelectCommand = new SqlCommand(query, Connectivity.Connection());
        adapter.Fill(ds.tblCategory);

        //lnkOrganizationCategory
        query = "select * from lnkOrganizationCategory where sxOrganization in " + orgList;
            adapter.SelectCommand = new SqlCommand(query, Connectivity.Connection());
            adapter.Fill(ds.lnkOrganizationCategory);

        //tblContact
        query = "select * from tblContact where sxContact in " +
            "(select sxContact from lnkOrganizationContact " +
            "where lnkOrganizationContact.sxOrganization in " +
            orgList + ")";
        adapter.SelectCommand = new SqlCommand(query, Connectivity.Connection());
        adapter.Fill(ds.tblContact);

        //lnkOrganizationContact
        query = "select * from lnkOrganizationContact where lnkOrganizationContact.sxOrganization in " + orgList;
        adapter.SelectCommand = new SqlCommand(query, Connectivity.Connection());
        adapter.Fill(ds.lnkOrganizationContact);
    } catch(Exception ex) {
        Debug.WriteLine(ex.Message);
    }

    ds.WriteXml(filename, XmlWriteMode.IgnoreSchema);
}

ご覧のとおり、私は同じ TableAdapeter を何度も再利用しています。最後に記述された XML は、各テーブルのタグがあり、その中に各フィールドのタグがあります。必要であり、それをマージして戻すことができます。インポートコードは次のとおりです。



//reads data from an xml file and merges it into existing db
public static void ImportData(string data)
{
    try
    {

    MyGeneratedDataSet newData = new MyGeneratedDataSet();

    StreamWriter sw = new StreamWriter("newdata.xml", false);
    Debug.WriteLine(data);
    sw.Write(data);
    sw.Close();
    XmlTextReader reader = new XmlTextReader(new MemoryStream(ASCIIEncoding.Default.GetBytes(data)));
    newData.ReadXml("newData.xml");

    MyGeneratedDataSet currentData = new MyGeneratedDataSet();

    //tblOrganization
    SqlDataAdapter tblOrganizationDataAdapter = new SqlDataAdapter("select * from tblOrganization", Connectivity.Connection());
    SqlCommandBuilder tblOrganizationCommandBuilder = new SqlCommandBuilder(tblOrganizationDataAdapter);
    tblOrganizationDataAdapter.Fill(currentData, "tblOrganization");

    //tblContact
    SqlDataAdapter tblContactDataAdapter = new SqlDataAdapter("select * from tblContact", Connectivity.Connection());
    SqlCommandBuilder tblContactCommandBuilder = new SqlCommandBuilder(tblContactDataAdapter);
    tblContactDataAdapter.Fill(currentData, "tblContact");

    //tblCategory
    SqlDataAdapter tblCategoryDataAdapter = new SqlDataAdapter("select * from tblCategory", Connectivity.Connection());
    SqlCommandBuilder tblCategoryCommandBuilder = new SqlCommandBuilder(tblCategoryDataAdapter);
    tblCategoryDataAdapter.Fill(currentData, "tblCategory");

    //lnkOrganizationCategory
    SqlDataAdapter lnkOrganizationCategoryDataAdapter = new SqlDataAdapter("select * from lnkOrganizationCategory", Connectivity.Connection());
    SqlCommandBuilder lnkOrganizationCategoryCommandBuilder = new SqlCommandBuilder(lnkOrganizationCategoryDataAdapter);
    lnkOrganizationCategoryDataAdapter.Fill(currentData, "lnkOrganizationCategory");

    //lnkOrganizationContact
    SqlDataAdapter lnkOrganizationContactDataAdapter = new SqlDataAdapter("select * from lnkOrganizationContact", Connectivity.Connection());
    SqlCommandBuilder lnkOrganizationContactCommandBuilder = new SqlCommandBuilder(lnkOrganizationContactDataAdapter);
    lnkOrganizationContactDataAdapter.Fill(currentData, "lnkOrganizationContact");

    Debug.WriteLine(tblOrganizationDataAdapter.SelectCommand.CommandText);
    Debug.WriteLine(tblOrganizationDataAdapter.UpdateCommand.CommandText);

    currentData.Merge(newData);

    tblOrganizationDataAdapter.Update(currentData);
    tblContactDataAdapter.Update(currentData);
    tblCategoryDataAdapter.Update(currentData);
    lnkOrganizationCategoryDataAdapter.Update(currentData);
    lnkOrganizationContactDataAdapter.Update(currentData);


    } catch (Exception ex) {
        Debug.WriteLine(ex.Message);
    }

}

現時点では、インポート関数の末尾近くにある Debug.WriteLine は、tblOrganizationTableAdapter の UpdateCommand が null であることを示しています。ビジュアルデザイナーは、それを作成するために作成したと言っていましたが、作成するだけでよい場合は、確かに作成しますが、これを何度も書き直しました (そして、これよりも多くのテーブルがあります)。 、そして私はまだ何が起こっているのか理解していません。これをどのように行う必要がありますか?!

どうもありがとうございます!ジョシュア


このコードはほとんど機能します。もう失敗することはなくなりましたが、主キーの比較を介して更新するのではなく、すべての行が重複してしまいます!

4

3 に答える 3

2

あなたがしていることは正しいように聞こえます。正確な問題が何であるかはわかりませんが、フローの内訳は次のとおりです。

  1. 新しいデータを DataSet にロードします (行ったように)
  2. データベースから現在のデータを DataSet に取得します(これまでに行ったように)
  3. CurrentData.Merge(NewData) を呼び出します (行ったように)
  4. CurrentData をデータベースに保存します(この部分は表示されません)。

ステップ 4 を実行すると、テーブル アダプタは の各テーブルをDataSet調べて、変更された行を見つけます。DataRowそれぞれDataTableが にDataRowState設定されているためAddedModifiedまたはDeletedへの呼び出しの結果として、それは知っていますMerge()。次に、テーブル アダプターは基になるデータベースで要求された変更を実行し、 を に設定します(DataRowStateもちろんの場合は除きます)。このプロセスが完了すると、基になるデータベースには、NewData データセットに含まれていたすべての変更が含まれているはずです。UnchangedDataRowDeleted

于 2010-01-13T22:26:53.337 に答える
1

何とか:

  • xml 行からデータセットを読み込みます。
  • 各行の RowState フラグが正しいことを確認します。
    • 未変更、変更、追加、または削除
  • AcceptChanges() を呼び出さないでください。すべての行の行状態を Unchanged に設定し、Deleted() とマークされた行を削除します。これは内部で行われます...

コード:

using (SqlDataAdapter dap = new SqlDataAdapater(myConnection, "SELECT * FROM MyTable"))
    dap.Update(myDataTable)
于 2010-01-13T18:58:45.147 に答える
0

ある時点でupdateを呼び出す必要があります。

adapter.Update(currentData, "table1")

一般に、SQLで2つのテーブルを直接マージする方がおそらく簡単ですが、アプリでxmlファイルを処理する必要がある場合があります。

マージ/更新の使用例:

http://msdn.microsoft.com/en-us/library/aa325628%28VS.71%29.aspx

t-sqlでは、MERGEを使用して1つのステートメントでこれを行うことができます。

http://technet.microsoft.com/en-us/library/bb510625.aspx

行を変更/更新する場合は、条件に合わせて調整してください

于 2010-01-13T18:41:51.950 に答える