OOP, modelli e macro in mql5, sottigliezze e usi - pagina 28

 
Maxim Kuznetsov:

Ricordo che in SQLite, i tipi di campo sono opzionali e non ci si deve preoccupare di specificare e fondere i tipi. È "Lite" per una ragione.

si può dividere una lunga query in 3-4-5 query :-)

BEGIN TRANSACTION

INSERT INTO myTable VALUES (...); --- тут можно получить PrimaryKey

UPDATE myTable .... ; --- обновить по Primary

UPDATE myTable ...  ; --- ещё...

COMMIT ; --- это если все запросы удачны.. иначе ROLLBACK

è dalla vecchia memoria, quindi dovreste controllare nell'aiuto

Mi piacerebbe avere un codice di query riproducibile, ci vorrà molto tempo per google, ho lavorato con un database occasionalmente - ho un problema, l'ho cercato su google, l'ho risolto - ma mi piacerebbe vedere una query di database fallita

 
Vladimir Simakov:

Il tuo particolare problema dovrebbe essere risolto così:

string MakeRequest(string md5txt){
   static ENUM_STATISTICS intIndex[]={STAT_CONPROFITMAX_TRADES,
                                      STAT_MAX_CONPROFIT_TRADES,
                                      STAT_CONLOSSMAX_TRADES,
                                      STAT_MAX_CONLOSS_TRADES,
                                      STAT_DEALS,
                                      STAT_TRADES,
                                      STAT_PROFIT_TRADES,
                                      STAT_LOSS_TRADES,
                                      STAT_SHORT_TRADES,
                                      STAT_LONG_TRADES,
                                      STAT_PROFIT_SHORTTRADES,
                                      STAT_PROFIT_LONGTRADES,
                                      STAT_PROFITTRADES_AVGCON,
                                      STAT_LOSSTRADES_AVGCON};
   string ret="INSERT INTO \"TesterStatistics\" + StringFormat(" set md5= %d ,md5txt),
   for (int i=0,ii=0;i<=STAT_LOSSTRADES_AVGCON;++i){
      ret+=",";
      if (i==intIndex[ii]){
         ret+=StringFormat("%s = %d,",EnumToString((ENUM_STATISTICS)i),(int)TesterStatistics((ENUM_STATISTICS)i) ));
         ++ii;}
      else ret+=StringFormat("%s =%G",EnumToString((ENUM_STATISTICS),i),TesterStatistics((ENUM_STATISTICS)i));}
   return ret;}
   
DatabaseExecute(handleDB, MakeRequest("md5txt"));

una piccola correzione, con più parentesi da fissare :-)
l'idea principale non è quella di usare UPDATE x VALUES (), ma UPDATE x SET name1=value1,name2=value2. Per far sì che la query funzioni correttamente se la struttura del database viene cambiata e non dipenda dall'ordine dei campi

 

c'è approssimativamente il seguente codice (leggo campi di testo dal database e voglio convertire in enum)

class MyClass
{
public:
   enum A            {Aq, Aw, Ae, Ar, At, Ay};
   enum B            {Bq, Bw, Be};
   enum C            {Cq, Cw, Ce, Cr};

   static bool       txtToEnumA(const string txt, A &result);
   static bool       txtToEnumB(const string txt, B &result);
   static bool       txtToEnumC(const string txt, C &result);
};
//+------------------------------------------------------------------+
static bool MyClass::txtToEnumA(const string txt, A &result)
{
   for(int i = 0; i <= (int)A::Ay; i++)
   {
      if(StringCompare(EnumToString((A)i), txt) == 0)
      {
         result = (MyClass::A)i;
         return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
static bool MyClass::txtToEnumB(const string txt, B &result)
{
   for(int i = 0; i <= (int)B::Be; i++)
   {
      if(StringCompare(EnumToString((B)i), txt) == 0)
      {
         result = (MyClass::B)i;
         return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
static bool MyClass::txtToEnumC(const string txt, C &result)
{
   for(int i = 0; i <= (int)C::Cr; i++)
   {
      if(StringCompare(EnumToString((A)i), txt) == 0)
      {
         result = (MyClass::C)i;
         return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
void OnStart()
{
   MyClass::A a;
   MyClass::B b;
   MyClass::C c;
   string txt[] = {"Aq", "Bw", "No"};

   if(MyClass::txtToEnumA(txt[0], a)) Print(txt[0], " in A = ", EnumToString(a));
   else Print("Error, ", txt[0], " not in A");

   if(MyClass::txtToEnumB(txt[1], b)) Print(txt[1], " in B = ", EnumToString(b));
   else Print("Error, ", txt[1], " not in B");

   if(MyClass::txtToEnumC(txt[2], c)) Print(txt[2], " in C = ", EnumToString(c));
   else Print("Error, ", txt[2], " not in C");
}
//+------------------------------------------------------------------+

2020.09.01 18:59:02.593 tst (EURUSD,M5) Aq in A = Aq

2020.09.01 18:59:02.593 tst (EURUSD,M5) Bw in B = Bw

2020.09.01 18:59:02.593 tst (EURUSD,M5) Error, No not in C

Tutto funziona, ma la domanda è di nuovo sul codice ottimale:

se c'è un modo per scrivere invece di txtToEnumA() , txtToEnumB(), txtToEnumC()

un metodo template ( template )

il problema è il diverso numero di elementi nell'enum

 

E se ci fosse un enum:

enum A            {Aq=10, Aw=9, Ae=8, Ar=7, At=6, Ay=5};

?

 
Dmitry Fedoseev:

E se ci fosse un enum:

?

la numerazione degli elementi enum non è una domanda, non è chiaro cosa farebbe questo

Ho solo 4 enumerazioni, non numerate

il problema è che potrei voler aggiungere nuovi elementi all'enumerazione - nel mio codice, aggiungerò nuovi elementi a NON quelli più esterni - il codice funzionerà - non mi piace la macchinosità di questo codice


ma non stiamo parlando di un codice universale per tutte le occasioni, abbiamo bisogno dei compiti attuali in un modello


SZY: non posso fare a meno dell'enumerazione - è conveniente, posso ugualmente leggere i dati sia nel sorgente che nel database, e nel database forse voglio correggere alcuni campi manualmente.... in generale, tutto mi va bene

 
Igor Makanu:

numerare gli elementi dell'enumerazione non è un problema, non è chiaro cosa farà questo

Ho solo 4 enumerazioni, non numerate

il problema è che potrei voler aggiungere nuovi elementi alle liste - nel mio codice, aggiungerò nuovi elementi a NON quelli più esterni - il codice funzionerà - non mi piace la pesantezza del codice


ma non stiamo parlando di un codice universale per tutte le occasioni, abbiamo bisogno dei compiti attuali in un modello


SZY: non posso fare a meno dell'enumerazione - è conveniente, posso ugualmente leggere i dati sia nel sorgente che nel database, e nel database forse voglio correggere alcuni campi manualmente.... tutto mi va bene

fare un array globale e riempirlo con coppie { EnumToString(x) , x }

struct StringID {

   string str;

   int id;

};

StringID IDS[];

e i modelli non saranno necessari.
 
Maxim Kuznetsov:

fare un array globale e riempirlo con coppie { EnumToString(x) , x }

struct StringID {

   string str;

   int id;

};

StringID IDS[];

e non avrete bisogno di modelli.

Il tuo modo di farlo non è molto diverso dal mio - è anche macchinoso, e se ci saranno dei cambiamenti nel codice, dovrai modificare anche gli array.

 

ha risolto il mio desiderio in questo modo:

class MyClass
{
public:
   enum A            {Aq, Aw, Ae, Ar, At, Ay};
   enum B            {Bq, Bw, Be};
   enum C            {Cq, Cw, Ce, Cr};
   template<typename T>
   static bool       txtToEnum(const T LastElement, const string txt, T &result);
};
//+------------------------------------------------------------------+
template<typename T>
static bool MyClass::txtToEnum(const T LastElement, const string txt, T &result)
{
   for(int i = 0; i <= (int)LastElement; i++)
   {
      if(StringCompare(EnumToString((T)i), txt) == 0)
      {
         result = (T)i;
         return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
void OnStart()
{
   MyClass::A a;
   MyClass::B b;
   MyClass::C c;
   string txt[] = {"Aq", "Bw", "No"};

   if(MyClass::txtToEnum(MyClass::Ay, txt[0], a)) Print(txt[0], " in A = ", EnumToString(a));
   else Print("Error, ", txt[0], " not in A");

   if(MyClass::txtToEnum(MyClass::Be, txt[1], b)) Print(txt[1], " in B = ", EnumToString(b));
   else Print("Error, ", txt[1], " not in B");

   if(MyClass::txtToEnum(MyClass::Cr, txt[2], c)) Print(txt[2], " in C = ", EnumToString(c));
   else Print("Error, ", txt[2], " not in C");

}
//+------------------------------------------------------------------+

2020.09.01 22:08:47.417 tst (EURUSD,M5) Aq in A = Aq

2020.09.01 22:08:47.417 tst (EURUSD,M5) Bw in B = Bw

2020.09.01 22:08:47.417 tst (EURUSD,M5) Error, No not in C



Ho bisogno di più definizioni per non inserire LastElement, ma nel complesso questo codice è più compatto

 
Quanto ci vuole per scrivere ogni genere di cose