Nowa instancja czy zamiana parametrów, jakie podejście?

0

Witam,
Piszę prostą aplikację Windows Forms, która łączy się z bazą lokalną Mysql i ogólnie ma służyć do wypełniania tabeli w bazie, ewentualnie jakieś inne jeszcze funkcje. Mam jedną metodę, która służy właśnie do dodawania danych, w której tworzę obiekt MySqlCommand oraz łączę go do bazy i nadaję wartości parametrom. No i teraz moje pytanie, czy poprawnie jest za każdym razem wywołania tej funkcji tworzyć nowy obiekt, łączyć do bazy i nadawać wartości parametrom, czy w konstruktorze raz stworzyć ten obiekt, połączyć do bazy, a w tej metodzie(lub przyszłych innych) zmieniać tylko wartości parametrów tej instancji?

2

Im krótszy czas życia obiektu tym łatwiej nim zarządzać. Przynajmniej nic nie podkusi Cię, żeby to jedno, jedyne połączenie trzymać gdzieś na boku w staticu (tfu). Poza tym connection.Open() nie jest tak kosztowne jak mogłoby się wydawać (https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/connection-pooling?redirectedfrom=MSDN).

Dobrze, że zastanawiasz się nad takimi kwestiami, ale zawsze miej z tyłu głowy, że to może być premature optimization i ewentualny zysk z nietworzenia połączeń czy wielu obiektów jest nie wart zachodu, a tylko wprowadza skomplikowanie.

1

ale zawsze to jest takie samo zapytanie tylko rożne parametry czy różne zapytania?

1

@Saalin: wczytałem się w pytanie kilkakrotnie. Mam wrażenie że nie trafiłeś w istotę. Kolega pyta nie o Connection, a o parametryczne Command

@witeks44: wielokrotne używanie parametrycznego Command (MySqlCommand po nim dziedziczy / implementuje) jest jak najbardziej OK.
W WinFormsach nie masz problemu wydajności, żaden człowiek nie pisze tak szybko, ale wzór jest dobry (z preparowaniem i wielokrotnym użyciem)
Na "nie" by było tylko wtedy, gdyby był bardzo pokrętny sposób zrobienia tego (np rzeczony 'static' czy coś podobnego).

Szkoda, że nie dajesz kodu, to się zawsze lepiej omawia.

0

Tak, w sumie mogłem dodać

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private DbManagment _databaseConnection;

        public Form1()
        {
            if (ConnectToDataBase())
                InitializeComponent();
            else
            {
                Console.ReadKey();
                Environment.Exit(1);
            }

            UpdateGridTable();
        }

        private void UpdateGridTable()
        {
            dataGridView1.DataSource = _databaseConnection.InsertDataToTable();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Console.WriteLine(@"Clicked");

            string insertName = textBox1.Text;
            string insertSurname = textBox2.Text;
            if (!string.IsNullOrWhiteSpace(insertName) && !string.IsNullOrWhiteSpace(insertSurname))
            {
                Console.WriteLine(insertName + @"  " + insertSurname);
                _databaseConnection.AddRecordToDatabase(insertName, insertSurname);
                UpdateGridTable();
            }
            else
            {
                Console.WriteLine(@"Empty Data");
            }

            textBox1.Text = null;
            textBox2.Text = null;
        }

        private bool ConnectToDataBase()
        {
            _databaseConnection = new DbManagment();
            return _databaseConnection.SuccesConnection;
        }

        private void Form1_FormClosing(object sender, EventArgs e)
        {
            _databaseConnection.CloseDatabase();
            Console.WriteLine(@"Closing...");
        }
    }
}

DBManagement.cs

namespace WindowsFormsApp1
{
    public class DbManagment
    {
        private string _server = "localhost";
        private string _database = "persondb";
        private string _uid = "root";
        private string _password = "xxxx";
        private string _port = "1234";
        private bool _succesConnection;

        public bool SuccesConnection
        {
            get => _succesConnection;
        }
        
        private MySqlConnection _con;
        private MySqlCommand _cmd;
        
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AllocConsole();

        public DbManagment()
        {
            AllocConsole();
            Console.WriteLine(@"Server connecting...");
            string connectionString = "datasource=" + _server + ";" + "database=" + _database + ";" + "port=" + _port +
                                      ";" + "username=" + _uid + ";" + "password=" + _password;

            _succesConnection = OpenDatabase(connectionString);
        }

        private bool OpenDatabase(string connString)
        {
            _con = new MySqlConnection(connString);
            try
            {
                _con.Open();
            }
            catch (MySqlException ex)
            {
                Console.WriteLine(ex.Code);
                switch (ex.Code)
                {
                    case 0:
                        Console.WriteLine(@"Cannot connect to server.  Contact administrator");
                        break;

                    case 1045:
                        Console.WriteLine(@"Invalid username/password, please try again");
                        break;
                }

                return false;
            }

            return true;
        }

        public void CloseDatabase()
        {
            _con.Close();
        }

        public void AddRecordToDatabase(string name, string surname)
        {
            _cmd = new MySqlCommand();
            _cmd.Connection = _con;
            _cmd.CommandText = "INSERT INTO person(First_name,Surname) VALUES(@name,@surname)";
            _cmd.Prepare();
            _cmd.Parameters.AddWithValue("@name", name);
            _cmd.Parameters.AddWithValue("@surname", surname);
            _cmd.ExecuteNonQuery();
        }

        public DataTable InsertDataToTable()
        {
            _cmd = new MySqlCommand("SELECT * FROM person", _con);
            _cmd.CommandType = CommandType.Text;
            MySqlDataAdapter sda = new MySqlDataAdapter(_cmd);
            DataTable dt = new DataTable();
            sda.Fill(dt);
            return dt;
        }
    }
}
2
// Tworzenie (jednorazowo)
            _cmd = new MySqlCommand();
            _cmd.Connection = _con;
            _cmd.CommandText = "INSERT INTO person(First_name,Surname) VALUES(@name,@surname)";
            _cmd.Parameters.Add("@name", SqlDbType.String /* tu chyba długość można/tzreba*/  );
            _cmd.Parameters.Add("@surname", SqlDbType.String /* tu chyba długość można/tzreba*/ );
            _cmd.Prepare();

// użycie, wielokrotnie
            _cmd.Parameters["@name"]  = name;
            _cmd.Parameters["@surname"] = surname;
            _cmd.ExecuteNonQuery();

Oczywiście na zapas powiem, korzystanie z tego samego Connekszyna wymaga, aby za kolejnym razem jego stan był "czysty", np żadnej otwartej transakcji (a transakcji by się używało przy jakiś "piętrowych" insertach) itd. Tu nam ta wiedza nie jest potrzebna

1
witeks44 napisał(a):

>         private void button1_Click(object sender, EventArgs e)
>         {
>             Console.WriteLine(@"Clicked");
> 
>             string insertName = textBox1.Text;
>             string insertSurname = textBox2.Text;
>             if (!string.IsNullOrWhiteSpace(insertName) && !string.IsNullOrWhiteSpace(insertSurname))
>             {
>                 Console.WriteLine(insertName + @"  " + insertSurname);
>                 _databaseConnection.AddRecordToDatabase(insertName, insertSurname);
>                 UpdateGridTable();

>         public DataTable InsertDataToTable()
>         {
>             _cmd = new MySqlCommand("SELECT * FROM person", _con);
>             _cmd.CommandType = CommandType.Text;
>             MySqlDataAdapter sda = new MySqlDataAdapter(_cmd);
>             DataTable dt = new DataTable();
>             sda.Fill(dt);
>             return dt;

Zauważ że obiekt DataTable też wyrzucasz przy każdym dodaniu rekordu. Pytanie ile razy będzie wykonywany ten OnClick

1

no właśnie czy musisz? jeśli tylko dana aplikacja korzysta z bazy, czyli nikt inny nie mógł dodać innych wierszy w międzyczasie możesz po wykonaniu inserta do bazy dodac tez go recznie do obiektu DataTable. u Jeżeli ta tabela w bazie jest zmieniana,m nawet przez inną instancję tej samej aplikacji to pewnie trzeba ja zsynchronizować. Nie ma VS pod ręka wiec niestety nie napisze jak powinien wygladac taki kod

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