Как я структурирую консольное приложение C# для эффективного использования ресурсов базы данных IDisposable?

Вы не можете использовать forEach для этого (по крайней мере, не без доступа к внешней переменной) - если вы хотите использовать метод массива, используйте вместо этого reduce и передавайте текущий Promise в качестве аккумулятора каждый время:

var array1 = ['a', 'b', 'c'];
array1.reduce((a, str) => (
  a.then(promise)
    .then(() => {
      console.log(str);
    })
), Promise.resolve());

function promise() {
  return new Promise((resolve, reject) => {
    console.log('test');
    resolve()
  })
}

Или, если вы хотите сделать код проще для чтения, используйте await внутри [115 ] цикл:

var array1 = ['a', 'b', 'c'];
(async () => {
  for (const str of array1) {
    await promise();
    console.log(str);
  }
})();


function promise() {
  return new Promise((resolve, reject) => {
    console.log('test');
    resolve()
  })
}

5
задан danieltalsky 6 May 2009 в 15:14
поделиться

5 ответов

Я думаю, что лучшее решение - извлечь основную логику из класса Program. Класс Program - это своего рода стартер для основной работы. И предоставление оболочек для SqlConnections действительно не очень хорошая идея, потому что они уже являются управляемыми ресурсами, и их упаковка избыточна. Таким образом, мое решение выглядит так:

class ProgramCore : IDisposable
{
    internal ProgramCore(string sourceConnectionString, string destinationConnectionString)
    {
        setUpConnections(sourceConnectionString, destinationConnectionString);
    }

    internal void Execute()
    {
        // do whatever you want
        doDatabaseWork();
        // do whatever you want
    }

    public void Dispose()
    {
        if (_sourceConnection != null)
            _sourceConnection.Dispose();
        if (_destinationConnection != null)
            _destinationConnection.Dispose();
    }

    private void setUpConnections(string sourceConnectionString, string destinationConnectionString)
    {
        _sourceConnection = new SQLiteConnection(sourceConnectionString);
        _destinationConnection = new SQLiteConnection(destinationConnectionString);
    }

    private void doDatabaseWork()
    {
        // use the connections here
    }

    private SQLiteConnection _sourceConnection;
    private SQLiteConnection _destinationConnection;
}

class Program
{
    static void Main(string[] args)
    {
        // get connection strings from command line arguments
        string sourceConnectionString = GetConnectionString(args);
        string destinationConnectionString = GetConnectionString(args);

        using (ProgramCore core = new ProgramCore(sourceConnectionString, destinationConnectionString))
        {
            core.Execute();
        }
    }

    static string GetConnectionString(string[] args)
    {
        // provide parsing here
    }
}
2
ответ дан 13 December 2019 в 05:41
поделиться

Как насчет написания класса, реализующего IDisposable.

Внутри конструктора класса вы можете создать экземпляры соединений с БД.

Затем внутри вашего IDisposable.Dispose Method вы записываете свой разрыв код для закрытия ваших соединений с БД.

Вот пример кода, чтобы продемонстрировать, что я имею в виду:

public class DBWrapper : IDisposable
{
    public SqlConnection Connection1 { get; set; }
    public SqlConnection Connection2 { get; set; }

    public DBWrapper()
    {
        Connection1 = new SqlConnection();
        Connection1.Open();
        Connection2 = new SqlConnection();
        Connection2.Open();
    }
    public void DoWork()
    {
        // Make your DB Calls here
    }

    public void Dispose()
    {
        if (Connection1 != null)
        {
            Connection1.Dispose();
        }
        if (Connection2 != null)
        {
            Connection2.Dispose();
        }
    }
}

А затем из вашего основного метода вашего класса Program:

class Program
{
    static void Main(string[] args)
    {
        using (DBWrapper wrapper = new DBWrapper())
        {
            wrapper.DoWork();
        }
    }
}
6
ответ дан 13 December 2019 в 05:41
поделиться

Ответ Скотта - один из способов сделать это. Вы также можете подумать об использовании try {} finally вместо этого?

static void Main(string[] args)
{
    Program shell = new Program();

    // get connection strings from command line arguments
    string sourceConnectionString = shell.getConnectionString(args);
    string destinationConnectionString = shell.getConnectionString(args);

    // call non-static methods that use
    shell.setUpConnections(sourceConnectionString, destinationConnectionString);
    try
    {
      shell.doDatabaseWork();
    }
    finally
    {
      if(sourceConnection != null)
        sourceConnection.Dispose();
      if(destinationConnection != null)
        destinationConnection.Dispose();
    }
}
2
ответ дан 13 December 2019 в 05:41
поделиться

Лично я думаю, что вы слишком много думаете об этом, а примеры кода в этой теме слишком сложны, imho. Я понятия не имею, почему люди реализуют IDisposable в своем классе Program, поскольку он удаляется при выходе.

Я не могу придумать ни одной причины, чтобы не использовать или почему вы не можете использовать оператор using () {}.

Вы хотите открыть соединение и удерживать его? Зачем? Все реальные соединения находятся за кулисами в пуле соединений .net, поэтому создание новых объектов Connection не представляет большого труда. Просто открывайте и закрывайте их, когда они вам нужны, и пул соединений обрабатывает все это за кулисами.

Я отредактировал свой пример, чтобы обернуть его в класс, чтобы вы также могли получить свою инкапсуляцию.

class Program 
{
    static void Main(string[] args)
    {
        DBWorker worker = new DBWorker();
        worker.DoDatabaseWork();
    }
}

public class DBWorker 
{

    private void DoDatabaseWork()
    {
        using (SQLiteConnection sourceDB = new SQLiteConnection( GetConnectionString() ))
        {
            sourceDB.Open();
            using (SQLiteConnection destDB = new SQLiteConnection( GetConnectionString() ))
            {
                destDB.Open();
            }
        }
    }

}
2
ответ дан 13 December 2019 в 05:41
поделиться

Хм, я вижу, что никто не упоминал о том, как это сделать. Необязательно, чтобы переменные, которые используются в , используя , были объявлены локально.


class Program 
{
    SQLiteConnection sourceConnection;
    SQLiteConnection destinationConnection;

    static void Main(string[] args)
    {
        Program shell = new Program();

        // get connection strings from command line arguments
        string sourceConnectionString = shell.getConnectionString(args);
        string destinationConnectionString = shell.getConnectionString(args);

        using (sourceConnection = new SQLiteConnection(sourceConnectionString))
        using (destinationConnection = new SQLiteConnection(destinationConnectionString))
        {
            shell.doDatabaseWork();
        }
    }

    private void doDatabaseWork()
    {
        // use the connections here
    }
}
0
ответ дан 13 December 2019 в 05:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: