Dopisanie do bazy w internecie danych z bazy na lokalnym PC

0

Witam,
Celem jest dopisanie w internetowej bazie MSSql przez program desktopowy jednorazowo od kilkudziesięciu do tysiąca rekordów z bazy na lokalnym PC.
Przedstawiony kod działa.
Wątpliwości dotyczą umieszczenia try{} i ogólnie poprawności przedstawionego zapisu.
Uprzejmie proszę o uwagi.

connDB="...conectionstring do bazy lokalnej na PC...";
connW="...conectionstring do bazy w internecie...";
DateTime data=DateTime.Now; // jakas data
try
{
    // 1 przygotowanie połączenia z bazą w internecie
    SqlConnection conn2 = new SqlConnection();
    conn2.ConnectionString = connW;
    SqlCommand cmd2 = new SqlCommand();
    cmd2.Connection = conn2;
    cmd2.CommandType = CommandType.Text;
    cmd2.CommandText = "INSERT INTO Osoby (Nazwisko, Wiek) VALUES (@Nazwisko, @Wiek)";
    cmd2.Parameters.Add("@Nazwisko", SqlDbType.VarChar);
    cmd2.Parameters.Add("@Wiek", SqlDbType.Int);

    // 2 zapytanie z lokalnej bazy na PC
    SqlConnection conn = new SqlConnection();
    conn.ConnectionString = connDB;
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = conn;
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = "SELECT Nazwisko, Wiek FROM Wykaz WHERE Data>=@data";
    cmd.Parameters.AddWithValue("@data", data);
    conn.Open();
    SqlDataReader dr = cmd.ExecuteReader();
    if (dr.HasRows)
    {
        while (dr.Read())
        {
            // aktualizacja danych w bazie w internecie
            conn2.Open();
            cmd2.Parameters.["@Nazwisko"].Value = Convert.ToDateTime(dr[0]);
            cmd2.Parameters.["@Wiek"].Value = Convert.ToString(dr[1]);
            cmd2.ExecuteNonQuery();
            conn2.Close();
        }
    }
    conn.Close();
}
catch (Exception ex)
{
    MessageBox.Show("Błąd: " + ex.ToString());
}

1

Ja to bym najpierw odczytał dane z jednej bazy, a potem zapisał do drugiej, zamiast trzymać jednocześnie otwarte połączenia do dwóch baz.

A po co w ogóle do tego C# mieszać, nie prościej przepchać z poziomu bazy do linked servera?

0

Witam,

A gdyby jednak tak po bożemu wiem że nadużywany jest wzorzec repozytorium ale zawsze to jakaś systematyka w działaniu.

namespace FourProgrammersCopy
{
    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;

    interface IRepository
    {
        void Create(KeyValuePair<string, int> item);

        IEnumerable<KeyValuePair<string, int>> List();
    }

    public class SourceRepository : IRepository
    {
        private readonly string connectionString;

        public SourceRepository(string connectionString)
        {
            this.connectionString = connectionString;
        }

        public IEnumerable<KeyValuePair<string, int>> List()
        {
            using (var connection = new SqlConnection(this.connectionString))
            {
                connection.Open();

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = "SELECT Nazwisko, Wiek FROM Wykaz WHERE Data>=@data";

                    command.Parameters.AddWithValue("@data", DateTime.Now);

                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            var key = reader.GetString(reader.GetOrdinal("Nazwisko"));
                            var value = reader.GetInt32(reader.GetOrdinal("Wiek"));

                            yield return new KeyValuePair<string, int>(key, value);
                        }
                    }
                }
            }
        }

        public void Create(KeyValuePair<string, int> item)
        {
            throw new NotImplementedException();
        }
    }

    public class DestinationRepository : IRepository
    {
        private readonly string connectionString;

        public DestinationRepository(string connectionString)
        {
            this.connectionString = connectionString;
        }

        public void Create(KeyValuePair<string, int> item)
        {
            using (var connection = new SqlConnection(this.connectionString))
            {
                connection.Open();

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = "INSERT INTO Osoby (Nazwisko, Wiek) VALUES (@Nazwisko, @Wiek)";

                    command.Parameters.AddWithValue("@Nazwisko", item.Key);
                    command.Parameters.AddWithValue("@Wiek", item.Value);

                    command.ExecuteNonQuery();
                }
            }
        }

        public IEnumerable<KeyValuePair<string, int>> List()
        {
            throw new NotImplementedException();
        }
    }

    static class Program
    {
        static void Main()
        {
            var source = new SourceRepository("...conectionstring do bazy lokalnej na PC...");
            var destination = new DestinationRepository("...conectionstring do bazy w internecie...");

            foreach (var item in source.List())
            {
                destination.Create(item);
            }
        }
    }
}

Pozdrawiam,

mr-owl

0

Dodałbym tu jeszcze fabrykę, proxy, ze dwa dekoratory i strategię, żeby było bardziej enterprise.

  1. To nie są żadne repozytoria, tylko DAO.
  2. Połowa metod w tym kodzie rzuca NotImplementedException, strasznie słaby design.
  3. KeyValuePair<T, U> jako DTO, prawdopodobnie gorzej się nie da.
0

somekind napisał(a)
Ja to bym najpierw odczytał dane z jednej bazy, a potem zapisał do drugiej, zamiast trzymać jednocześnie otwarte połączenia do dwóch baz.

  1. Wydaje się słuszne. Czyli najpierw odczytać tzn załadować np do tablicy?

A po co w ogóle do tego C# mieszać,
2. C# bo klient to sam sobie wysyła swoje dane do internetu

nie prościej przepchać z poziomu bazy do linked servera?
3. linked server? ojej nie wiem o co chodzi

2
  1. Tak, np. pobrać na raz całą listę do tablicy. Tylko się nie upieram, że to jest lepsze i niekoniecznie musi być.
  2. Klient nie powinien decydować o szczegółach implementacyjnych.
  3. W SQL Server możesz sobie podlinkować inny serwer i wykonywać na nim operacje SQL np. w kodzie procedury.

Gdybym miał za zadanie skopiować pewne dane z jednej bazy do drugiej, to użyłbym do tego mechanizmów udostępnionych przez bazy, a nie pisał aplikację, która tutaj jest tylko dodatkowym narzutem (czasowym na stworzenie i wydajnościowym podczas pracy).

0

Poniżej kod bez zazębiania się połączeń.
Przedstawiony kod działa.
Wątpliwości dotyczą umieszczenia try{} i ogólnie poprawności przedstawionego zapisu.
Uprzejmie proszę o uwagi.

  1. Czy dobry wybór datatable czy coś innego?
  2. Czy Dispose jest w dobrym miejscu?
  3. Proszę również o inne uwagi w celu uporządkowania kodu..
    P.S. Na razie pomijam procedurę w bazie SQL (która wydaje się najsłuszniejszym rozwiązaniem).
// 3b.1  dane z lokalnej bazy do dataTable
SqlConnection conn = new SqlConnection();
conn.ConnectionString = FunZ.connDB;
SqlCommand cmd = new SqlCommand();
DataTable dataTable = new DataTable();
try
{
	cmd.Connection = "...conectionstring do bazy lokalnej na PC...";
	cmd.CommandType = CommandType.Text;
	cmd.CommandText = "SELECT Nazwisko, Wiek FROM Wykaz WHERE Data>=@data";
	cmd.Parameters.AddWithValue("@data", data);
	conn.Open();
	SqlDataAdapter da = new SqlDataAdapter(cmd);
	da.Fill(dataTable);
	conn.Close();
	da.Dispose();                
}
catch (Exception ex)
{
	dataTable.Dispose();
	MessageBox.Show("1 Wyp.www: " + ex.ToString());
	return;
}

// 3b.2  przygotowanie połączenia z bazą w internecie
SqlConnection conn2 = new SqlConnection();
conn2.ConnectionString = "...conectionstring do bazy w internecie...";
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = conn2;
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = "INSERT INTO Osoby (Nazwisko, Wiek) VALUES (@Nazwisko, @Wiek)";
cmd2.Parameters.Add("@Nazwisko", SqlDbType.VarChar);
cmd2.Parameters.Add("@Wiek", SqlDbType.Int);

// 3b.3  dane do www
int ileRek=dataTable.Rows.Count;
try
{
	for (int i = 0; i < ileRek; i++)
	{
		conn2.Open();
		cmd2.Parameters["@Nazwisko"].Value = dataTable.Rows[i][0]; 
		cmd2.Parameters["@Wiek"].Value = dataTable.Rows[i][1]; 
		cmd2.ExecuteNonQuery();
		conn2.Close();
	}
}
catch (Exception ex)
{
	dataTable.Dispose();
	MessageBox.Show("2 Wyp.www: " + ex.ToString());
}
dataTable.Dispose();
MessageBox.Show("Dopisano: " + ileRek.ToString());

1 użytkowników online, w tym zalogowanych: 0, gości: 1