потерял с DataSets и слияния в C # - PullRequest
0 голосов
/ 13 января 2010

НОВОЕ РЕДАКТИРОВАНИЕ !!!

ПОЖАЛУЙСТА ... Я прошел через многие перестановки этого кода. Я пытаюсь взять некоторые определенные связанные записи из базы данных (сервер 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 в конце функции импорта показывает, что UpdateCommand объекта tblOrganizationTableAdapter имеет значение null. Визуальный дизайнер сказал мне, что он создал это для, хотя, если все, что мне нужно сделать, это создать, конечно, я сделаю это, но я переписывал это так много раз (и таблиц намного больше, чем это) и я до сих пор не понимаю, что происходит. Как я должен это делать?!

СПАСИБО ТАК МНОГО! Joshua


Этот код почти работает. Теперь это больше не дает сбоя, однако я получаю все дублирующиеся строки вместо обновления с помощью сравнения первичного ключа!

Ответы [ 3 ]

2 голосов
/ 14 января 2010

То, что вы делаете, звучит правильно. Я не уверен, в чем именно заключается ваша проблема, но вот разбивка потока:

  1. Загрузка новых данных в набор данных (как вы сделали)
  2. Получить текущие данные из базы данных в DataSet (как вы сделали)
  3. Вызов CurrentData.Merge (NewData) (как вы сделали)
  4. Сохранить CurrentData обратно в базу данных (я не вижу эту часть)

Когда вы выполняете шаг # 4, адаптеры таблиц просматривают каждую таблицу в DataSet и выясняют, какие строки изменились. Он знает, потому что каждый DataRow в каждом DataTable будет иметь DataRowState, установленный на Added, Modified или Deleted в результате вашего вызова на Merge(). Затем адаптер таблицы выполняет запрошенное изменение в базовой базе данных и устанавливает DataRowState в Unchanged для DataRow (за исключением, конечно, Deleted). Когда этот процесс завершится, базовая база данных должна иметь все изменения, содержащиеся в наборе данных NewData.

1 голос
/ 13 января 2010

Ли:

  • Загрузите ваш набор данных из строк XML.
  • Убедитесь, что флаг RowState правильный для каждой строки:
    • без изменений, модифицированных, добавленных или удаленных
  • Не вызывайте AcceptChanges (), он устанавливает для каждой строки значение «Без изменений» и удаляет строки, отмеченные как «Deleted ()» Это делается внутренне ...

Код:

using (SqlDataAdapter dap = new SqlDataAdapater(myConnection, "SELECT * FROM MyTable"))
    dap.Update(myDataTable)
0 голосов
/ 13 января 2010

обновление должно быть вызвано в какой-то момент:

adapter.Update(currentData, "table1")

в целом, возможно, проще объединить 2 таблицы непосредственно в SQL, но вашему приложению может потребоваться обработка XML-файлов.

примеры использования Merge / Update:

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

в t-sql вы можете сделать это одним оператором с помощью MERGE:

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

настроить его в соответствии с условиями, когда вы хотите, чтобы строка была изменена / обновлена ​​

...