Отправка изменений из нескольких таблиц в отключенном наборе данных в SQLServer - PullRequest
0 голосов
/ 21 декабря 2009

У нас есть стороннее приложение, которое принимает вызовы с использованием механизма RPC XML для вызова хранимых процедур.

Мы отправляем сжатый ZIP-архив набор данных, содержащий несколько таблиц с пакетом обновления / удаления / вставки, используя этот механизм. С другой стороны, программа CLR распаковывает данные и получает набор данных.

Затем выполняется следующий код:

    using (var conn = new SqlConnection("context connection=true"))
    {
        if (conn.State == ConnectionState.Closed)
           conn.Open();

        try
        {
            foreach (DataTable table in ds.Tables)
            {
                string columnList = "";
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    if (i == 0)
                        columnList = table.Columns[0].ColumnName;
                    else
                        columnList += "," + table.Columns[i].ColumnName;
                }

                var da = new SqlDataAdapter("SELECT " + columnList + " FROM " + table.TableName, conn);

                var builder = new SqlCommandBuilder(da);
                builder.ConflictOption = ConflictOption.OverwriteChanges;

                da.RowUpdating += onUpdatingRow;
                da.Update(ds, table.TableName);

            }
        }

        catch (....)
        {
           .....
        }
    }

Вот обработчик события для события RowUpdating:

public static void onUpdatingRow(object sender, SqlRowUpdatingEventArgs e)
{
    if ((e.StatementType == StatementType.Update) && (e.Command == null))
    {
        e.Command = CreateUpdateCommand(e.Row, sender as SqlDataAdapter);
        e.Status = UpdateStatus.Continue;
    }
}

и метод CreateUpdateCommand:

private static SqlCommand CreateUpdateCommand(DataRow row, SqlDataAdapter da)
{
    string whereClause = "";
    string setClause = "";

    SqlConnection conn = da.SelectCommand.Connection;
    for (int i = 0; i < row.Table.Columns.Count; i++)
    {
        char quoted;

        if ((row.Table.Columns[i].DataType == Type.GetType("System.String")) ||
            (row.Table.Columns[i].DataType == Type.GetType("System.DateTime")))
            quoted = '\'';
        else
            quoted = ' ';

        string val = row[i].ToString();
        if (row.Table.Columns[i].DataType == Type.GetType("System.Boolean"))
            val = (bool)row[i] ? "1" : "0";

        bool isPrimaryKey = false;

        for (int j = 0; j < row.Table.PrimaryKey.Length; j++)
        {
            if (row.Table.PrimaryKey[j].ColumnName == row.Table.Columns[i].ColumnName)
            {
                if (whereClause != "")
                    whereClause += " AND ";
                if (row[i] == DBNull.Value)
                    whereClause += row.Table.Columns[i].ColumnName + "=NULL";
                else
                    whereClause += row.Table.Columns[i].ColumnName + "=" + quoted +
                                   val + quoted;
                isPrimaryKey = true;
                break;
            }
        }

        /* Only values for column that is not a primary key can be modified  */
        if (!isPrimaryKey)
        {
            if (setClause != "")
                setClause += ", ";

            if (row[i] == DBNull.Value)
                setClause += row.Table.Columns[i].ColumnName + "=NULL";
            else
                setClause += row.Table.Columns[i].ColumnName + "=" + quoted +
                             val + quoted;

        }
    }

    return new SqlCommand("UPDATE " + row.Table.TableName + " SET " + setClause + " WHERE " + whereClause, conn);
}

Тем не менее, это очень медленно, когда у нас много записей.

Есть ли способ оптимизировать этот или совсем другой способ отправки большого количества обновлений / удалений в несколько таблиц? Я бы очень хотел использовать TSQL для этого, но не могу найти способ отправить набор данных обычному sproc.

Дополнительные примечания:

  • Мы не можем получить прямой доступ к базе данных SQLServer.
  • Мы пытались без сжатия, и это было медленнее.

1 Ответ

0 голосов
/ 21 декабря 2009

Если вы используете SQL Server 2008, вам следует изучить MERGE

Смотрите здесь для получения дополнительной информации о MERGE

...