1

Имеется код (он рабочий), но хотел бы узнать, можно его как-то упростить? Особенно интересует, можно как-нибудь уменьшить кол-во строк? Просто из-за использования using, блоков исключения и т.д код растягивается, теряется читабельность.

Пожалуйста, ответьте как можно понятнее для новичка :)

public partial class CreateAds : Form
{
    public MainForm otherForm;
    string pathBase = Path.Combine(Application.StartupPath, "ads.db");

    public CreateAds(MainForm form1)
    {
        InitializeComponent();
        otherForm = form1;

        btCreate.Click += (sender, e) => {
            if (!File.Exists(pathBase)) 
            {
                SQLiteConnection.CreateFile(pathBase);
                using (SQLiteConnection con = new SQLiteConnection(string.Format("Data Source={0};", pathBase))) 
                {
                    using (SQLiteCommand cmd = new SQLiteCommand("CREATE TABLE `base` (ID integer primary key, Name varchar, DateCreate varchar, DateEnd varchar, Mesto tinyint(5));", con)) 
                    {
                        try 
                        {
                            con.Open();
                            cmd.ExecuteNonQuery();
                        }
                        catch (Exception ex) 
                        {
                            MessageBox.Show(ex.Message);
                        }
                        finally 
                        {
                            con.Close();
                        }
                    }
                }
            }

            using (SQLiteConnection con = new SQLiteConnection(string.Format("Data Source={0};", pathBase)))
            {
                try
                {
                    con.Open();

                    string query = string.Format("INSERT INTO 'base' ('Name', 'DateCreate', 'DateEnd', 'Mesto') VALUES ('{0}', '{1}', '{2}', '{3}');", tbName.Text, tbDateCreate.Text, tbDateEnd.Text, tbMesto.Value);

                    using (SQLiteCommand cmd = new SQLiteCommand(query, con))
                    {
                        cmd.ExecuteNonQuery();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    con.Close();
                }
            }
            otherForm.dgv.Rows.Add(tbName.Text, tbDateCreate.Text, tbDateEnd.Text, tbMesto.Value, "Удалить");
        };
    }
}

public static async Task InsertBase(string Names, string DateCreates, string DateEnds, decimal Mestos)
        {
            string pathBase = Path.Combine(Application.StartupPath, "ads.db");
        using (SQLiteConnection con = new SQLiteConnection(string.Format("Data Source={0};", pathBase)))
        {
            await con.OpenAsync();

            string query = string.Format("INSERT INTO 'base' ('Name', 'DateCreate', 'DateEnd', 'Mesto') VALUES ('{0}', '{1}', '{2}', '{3}');", Names, DateCreates, DateEnds, Mestos);

            using (SQLiteCommand cmd = new SQLiteCommand(query, con))
            {
                await cmd.ExecuteNonQueryAsync();
            }
        }
    }</code></pre>
andreycha
  • 25,167
  • 4
  • 46
  • 82
  • 1
    Лямбду делают <= ~7 строк, а если невозможно, то тогда делают метод, который вызывают из лямбды. И почему нельзя было сразу метод подписать на событие? Зачем городить такое? А про асинхронность вы слышали? – Bulson Feb 09 '17 at 18:06
  • 1
    Using не закрывает соединение ? – Vadim Prokopchuk Feb 09 '17 at 18:06
  • @Bulson, не думал что так много строк выйдет. Про асинхронность слышал.. можете конкретно указать что не так? – Максим Feb 09 '17 at 18:09
  • 1
    @VadimProkopchuk, т.е, вы имеете ввиду, соединение автоматически закрывается при выходе из блока using? – Максим Feb 09 '17 at 18:12
  • Судя по коду у вас приложение WinForms. Соединение с БД будет блокировать UI-поток. Лучше делать асинхронно такие операции – Vadim Prokopchuk Feb 09 '17 at 18:13
  • @Максим да, но я не уверен будет ли оно закрыто при exception – Vadim Prokopchuk Feb 09 '17 at 18:13
  • 3
    Использование using предполагает, что руками прописывать Close не нужно, т.к. класс реализует IDisposable – Bulson Feb 09 '17 at 18:17

1 Answers1

1

SQLiteConnection con следует сделать private полем класса, да и откровенно говоря, работу с БД нужно выносить в отдельный класс Repository, совсем выносить, подальше от UI.

SQLite - локальная БД, соединение в принципе можно держать открытым на протяжении всего времени работы программы. Программа запустилась, соединение установили, при закрытии программы закрываем соединение.

Создайте интерфейс со всеми требуемыми методами: create, read, update, delete и используйте его как тип для поля через которое будете работать с классом Repository.

Методы в Repository нужно сделать асинхронными, для этого создаете обычные синхронные методы, проверяете как работают (тестируете), а потом делаете так:

//предположим у нас есть синхронный метод
public bool DeleteEntity(int id) {...}

//делаем ему асинхронного брата
public Task<bool> DeleteEntityAsync(int id)
{
     return Task.Run<bool>(() =>
     {
         return DeleteEntity(id);
     });
}

Тогда в нужном месте мы сможем вызвать его так

bool result = await _repository.DeleteEntityAsync(123);
Bulson
  • 9,411
  • Спасибо! А мой код сильно плох по сравнению с вашим? (Я прикрепил его в первый пост) – Максим Feb 09 '17 at 18:59
  • 1
    Не нужно создавать "асинхронных братьев". – andreycha Feb 09 '17 at 20:42
  • @andreycha там речь про API, и про то, что надо дать пользователям этого API самим определять, как запускать синхронные методы. Здесь совсем другой случай. Не надо впадать в мракобесие, кто-то чего-то там порекомендовал, может и вполне разумное, в данном конкретном случае, но не надо слепо следовать данной рекомендации, и становится этаким адептом, проводником истины в последней инстанции. – Bulson Feb 09 '17 at 20:55
  • 1
    Публичные методы репозитория и есть его API. А UI (или другой слой) -- клиент этого API. Поэтому позвольте клиенту самому решать, как запускать метод. – andreycha Feb 09 '17 at 21:12
  • 1
    @andreycha, спасибо, что обратили мое внимание на данную проблему. Но вот в данном конкретном случае, парень пишет небольшую программу, и сам знает, что у него синхронное, а что является всего лишь асинхронной оберткой. Поэтому я не пойму в чем проблема? То ли он это синхронный метод обернет в UI в Task.Run(), то ли он это сделает заранее в репозитории, и добавит тем самым лаконичности в код UI. Ну, что тут криминального!? – Bulson Feb 09 '17 at 21:19
  • 1
    Парень пишет небольшую программу и сам знает, где у него обращение к БД, а где к интерфейсу, зачем ему репозиторий? ;) Правила сначала лучше выучить, выполнять, а только потом учиться нарушать. – andreycha Feb 09 '17 at 23:58
  • Если я правильно понял принципы работы async/await, то в представленном коде они, собственно, бесполезны? – Leonid Mar 07 '17 at 08:40