Вы не можете использовать 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()
})
}
Я думаю, что лучшее решение - извлечь основную логику из класса 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
}
}
Как насчет написания класса, реализующего 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();
}
}
}
Ответ Скотта - один из способов сделать это. Вы также можете подумать об использовании 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();
}
}
Лично я думаю, что вы слишком много думаете об этом, а примеры кода в этой теме слишком сложны, 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();
}
}
}
}
Хм, я вижу, что никто не упоминал о том, как это сделать. Необязательно, чтобы переменные, которые используются в , используя
, были объявлены локально.
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
}
}