sopy7 Ответов: 1

Эффективный способ циклического перебора данных


В c# я написал код для первого извлечения данных из базы данных, циклического перебора их и создания инструкции insert для них же. Ниже приведен код C#...

StringBuilder strSql = new StringBuilder();
            strSql.Append("ATTACH 'D:\\Application\\Demo Applications\\Windows\\WindowsFormsApplication_SQLite\\Database\\Source\\TestDB.db' AS SourceDB;");
            strSql.Append("ATTACH 'D:\\Application\\Demo Applications\\Windows\\WindowsFormsApplication_SQLite\\Database\\Destination\\TestDB.db' AS DestDB;");
            
            using (SQLiteConnection con = new SQLiteConnection(SourceconnectionString))
            {
                con.Open();

                using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM dbSchema", con))
                {
                    using (SQLiteDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read()) // Reading Rows
                        {
                            strSql.Append("INSERT INTO DestDB.");
                            strSql.Append(rdr["TableName"].ToString());
                            strSql.Append(" (");
                            strSql.Append(rdr["Columns"].ToString());
                            strSql.Append(") ");
                            strSql.Append("SELECT ");
                            strSql.Append(rdr["Columns"].ToString());
                            strSql.Append(" FROM SourceDB.");
                            strSql.Append(rdr["TableName"].ToString());
                            strSql.Append(";");
                            var tableName = rdr["TableName"].ToString();
                            var Columns = rdr["Columns"].ToString();
                        }
                    }
                }
            }

            using (SQLiteConnection conn = new SQLiteConnection(DestinationConnectionString))
            {
                conn.Open();
                using (SQLiteCommand cmd = new SQLiteCommand(conn))
                {
                    cmd.CommandText = strSql.ToString();
                    int i = cmd.ExecuteNonQuery();
                    if (i > 0)
                    {
                        MessageBox.Show("Data dumped successfully ...!!!");
                    }
                }
            }


Приведенный выше код просто отлично работает. Он делает именно то, что нужно.

Но мне интересно, есть ли более элегантный и эффективный способ добиться того же.

Что я уже пробовал:

StringBuilder strSql = new StringBuilder();
            strSql.Append("ATTACH 'D:\\Application\\Demo Applications\\Windows\\WindowsFormsApplication_SQLite\\Database\\Source\\TestDB.db' AS SourceDB;");
            strSql.Append("ATTACH 'D:\\Application\\Demo Applications\\Windows\\WindowsFormsApplication_SQLite\\Database\\Destination\\TestDB.db' AS DestDB;");
            
            using (SQLiteConnection con = new SQLiteConnection(SourceconnectionString))
            {
                con.Open();

                using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM dbSchema", con))
                {
                    using (SQLiteDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read()) // Reading Rows
                        {
                            strSql.Append("INSERT INTO DestDB.");
                            strSql.Append(rdr["TableName"].ToString());
                            strSql.Append(" (");
                            strSql.Append(rdr["Columns"].ToString());
                            strSql.Append(") ");
                            strSql.Append("SELECT ");
                            strSql.Append(rdr["Columns"].ToString());
                            strSql.Append(" FROM SourceDB.");
                            strSql.Append(rdr["TableName"].ToString());
                            strSql.Append(";");
                            var tableName = rdr["TableName"].ToString();
                            var Columns = rdr["Columns"].ToString();
                        }
                    }
                }
            }

            using (SQLiteConnection conn = new SQLiteConnection(DestinationConnectionString))
            {
                conn.Open();
                using (SQLiteCommand cmd = new SQLiteCommand(conn))
                {
                    cmd.CommandText = strSql.ToString();
                    int i = cmd.ExecuteNonQuery();
                    if (i > 0)
                    {
                        MessageBox.Show("Data dumped successfully ...!!!");
                    }
                }
            }

1 Ответов

Рейтинг:
6

#realJSOP

Ну, это сопряжено с опасностью, потому что а) вы полагаетесь на то, что данные в rdr всегда будут там, и б) вы не используете параметризованные запросы. Я бы сделал что-то вроде этого (внимание-это непроверенный код, так что я, возможно, что-то неправильно понял):

using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM dbSchema", con))
{
    using (SQLiteDataReader rdr = cmd.ExecuteReader())
    {
        while (rdr.Read()) // Reading Rows
        {
            string tablename;
            int columns;
            try
            {
                tablename = rdr.GetString("TableName");
                columns   = rdr.GetInt32("Columns");

                string newQuery = "INSERT INTO DestDB.@tablename (Columns) Values(@columns);";
                string newQuery2 = "SELECT [Columns] FROM SourceDB.@tablename";

                SQLiteCommand cmd = new SQLiteCommand(newQuery, con);
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.Add(new SqlParameter("@tablename", tablename));
                cmd.Parameters.Add(new SqlParameter("@columns", columns));
                cmd.ExceuteNonQuery();

                cmd.CommandText = newQuery2;
                using (SqliteDataReader rdr2 = cmd.ExecuteReader())
                {
                    while (rdr.Read())
                    {
                        // ... do something ...
                    }
                }
            }
            catch (Exception ex)
            {
               // inspect for problems here (couldn't retrieve tablename 
               // or columns info, other db stuff)
            }
        }
    }
}


FWIW, вам не нужно повторно запрашивать базу данных, чтобы узнать, были ли данные добавлены в таблицу. Все, что вам нужно сделать, это посмотреть, равно ли количество измененных строк 1 (возвращаемое значение из ExecuteNonQuery).