0

最新编辑!!!

请...我已经经历了这段代码的许多排列。我正在尝试从数据库(SQL 服务器)中获取某些相关记录并导出到 XML(这似乎可行!),并将它们带到该数据库的断开连接的副本,然后将它们导入该数据库,按主合并它们密钥(如果密钥存在则更新,如果不存在则插入)。

数据库中有很多表,我想要所有与某个已更改实体列表相关的表。我很早就发现我无法使用连接进行大型复杂查询来获取我想要填充导出数据集的所有列,因为我丢失了所有表结构。我还让 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 为空。视觉设计师告诉我,它创建了它,尽管如果我要做的就是创建它,当然,我会这样做,但我现在已经重写了很多次(而且还有比这更多的表) ,我仍然不明白发生了什么。我该怎么做?!

太感谢了!约书亚


这段代码几乎可以工作。它现在不再失败,但是,我最终得到了所有重复的行,而不是通过主键比较进行更新!

4

3 回答 3

2

你在做什么听起来是对的。我不确定您的确切问题是什么,但这里是流程的细分:

  1. 将新数据加载到 DataSet中(就像您所做的那样)
  2. 将当前数据从数据库中获取到 DataSet中(就像你所做的那样)
  3. 调用 CurrentData.Merge(NewData) (就像你做的那样)
  4. 将 CurrentData 保存回数据库(我没有看到这部分)

当您执行第 4 步时,表适配器会查看 中的每个表DataSet并找出哪些行已更改。它知道,因为每个DataRow中的每个都DataTableDataRowState设置为AddedModified或者Deleted作为您调用的结果Merge()。然后,表适配器在底层数据库中执行请求的更改并将 设置DataRowState为(当然UnchangedDataRow除了 的情况Deleted)。此过程完成后,基础数据库中应该包含 NewData 数据集包含的所有更改。

于 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

在某些时候需要调用更新:

adapter.Update(currentData, "table1")

一般来说,直接在 sql 中合并 2 个表可能更容易,但您的应用程序可能需要处理 xml 文件。

使用合并/更新的例子:

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

在 t-sql 中,您可以使用 MERGE 在一个语句中执行此操作:

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

调整它以适应您希望更改/更新行时的条件

于 2010-01-13T18:41:51.950 回答