1c 8 darījumi no ārējiem avotiem. Vienreizējie klienti. Segmentēšana, lai iegūtu atkārtotus pirkumus. Preču izmaksas pasūtījumā

Neatkarīgi no izvēlētās darbības opcijas (fails vai klients-serveris), sistēma 1C:Enterprise nodrošina darbu ar datu bāzē saglabāto informāciju, izmantojot transakciju mehānismu.

Darījums- šī ir nedalāma datu manipulācijas darbību secība no ietekmes uz datu bāzi viedokļa. Tas darbojas pēc principa "viss vai neko" un pārvieto datubāzi no viena holistiskā stāvokļa uz citu holistisku stāvokli. Ja kāda iemesla dēļ kāda no transakcijas darbībām nav izpildāma vai notiek sistēmas darbības traucējumi, datu bāze atgriežas stāvoklī, kāds bija pirms darījuma sākuma (darījums tiek atvilkts).

Sistēma 1C:Enterprise netieši izsauc darījumus, veicot jebkādas darbības, kas saistītas ar datu bāzē saglabātās informācijas modificēšanu. Piemēram, visi notikumu apstrādātāji, kas atrodas objektu un ierakstu kopu moduļos, kas saistīti ar datu bāzes datu modifikāciju, tiek izsaukti transakcijā. Darījums nolasa arī šāda veida objektus: Planobena Objekts, Dokuments -lidmašīnas priekšmets, uzziņu grāmata, Planwid -Raksturu un plāna vārdu aprēķini, Plāns -Prettēma, Valdes procedūra, Objekts, Spiederi, Reģistra reģistrs, Reģistrs -Knock -Racing, Registachgontinarinapers, Reģistrācijas reģistrācija, Pārskatīšana , pārrēķināms.Rekordi. Šajā gadījumā pārvaldītajā bloķēšanas režīmā koplietojamā bloķēšana tiek instalēta pēc ierakstu kopu reģistra vērtības un neatkarīga informācijas reģistra ierakstu kopas atlases vērtībām.

Līdztekus tam izstrādātājs var izmantot nepārprotamu darbu ar darījumiem. Lai to izdarītu, izmantojiet globālās konteksta procedūras StartTransaction(), CommitTransaction() un CancelTransaction().

Izmantojot skaidru darījumu zvanu

Metode StartTransaction()ļauj atvērt darījumu. Visas izmaiņas datu bāzes informācijā, ko veic turpmākie paziņojumi, var pilnībā pieņemt vai pilnībā noraidīt. Lai pieņemtu visas veiktās izmaiņas, izmantojiet metodi CommitTransaction(). Lai atsauktu visas atvērtā darījumā veiktās izmaiņas, izmantojiet metodi Atcelt Darījumu(). Ja metodes zvanu skaits StartTransaction() pārsniedz metodes izsaukumu skaitu CommitTransaction() vai Atcelt Darījumu(), tad sistēma veiks netiešu metodes izsaukumu Atcelt Darījumu()šādos gadījumos:

● iebūvētās valodas izpildes beigās (notikumu apstrādātājs, ārējais savienojums, automatizācijas serveris);

● nododot vadību no servera klientam.

Ja metodes zvanu skaits CommitTransaction() vai Atcelt Darījumu() pārsniedz metodes izsaukumu skaitu StartTransaction(), tad, veicot nevajadzīgu metodes izsaukumu CommitTransaction() vai Atcelt Darījumu() izņēmums tiks izmests. Tādējādi shēma darbam ar darījumu vispārējs skats varētu izskatīties šādi:

Mēģinājums

StartTransaction();

// Izteikumu secība

CommitTransaction();

Izņēmums

Atcelt Darījumu();

EndAttempt;

Izmantojot šādu shēmu, jāatceras, ka ne visas kļūdas, kas rodas, strādājot ar datu bāzi, sistēma apstrādā vienādi. Kopumā visas datu bāzes kļūdas var iedalīt divās kategorijās:

● neatgūstams,

● atgūstams.

Neatkopjamas kļūdas- tās ir kļūdas, ja tās rodas, var tikt traucēta normāla sistēmas 1C:Enterprise darbība, piemēram, var tikt bojāti dati. Ja rodas neatgriezeniska kļūda, sistēmas 1C:Enterprise izpilde jebkurā gadījumā tiek pārtraukta. Ja darījuma izpildes laikā rodas neatgriezeniska kļūda, sistēma atceļ visas transakcijas ietvaros veiktās izmaiņas.

Atjaunojamās kļūdas- tās ir kļūdas, kas nerada nopietnus traucējumus sistēmas 1C:Enterprise darbībā. Ja rodas atkopjama kļūda, sistēmas turpmākā darbība var turpināties. Šajā gadījumā, protams, pati darbība, kas izraisīja kļūdu, tiek pārtraukta, un tiek izvirzīts izņēmums, kuru konstrukcija var pārtvert un apstrādāt

Mēģinājums... Izņēmums... BeigasMēģiniet.

Ligzdota darījuma zvans

Jau esošā darījuma ietvaros varat piekļūt procedūrām StartTransaction(), CommitTransaction() Un Atcelt Darījumu(). Piemēram, var izmantot šādu zvanu modeli:

StartTransaction();

StartTransaction();

CommitTransaction();

// Ligzdota darījuma izsaukums

StartTransaction();

CommitTransaction();

CommitTransaction();

Tomēr šāds izsaukums nenozīmē jauna darījuma sākšanu jau esošā darījuma ietvaros.

UZMANĪBU!Sistēma 1C:Enterprise neatbalsta ligzdotas transakcijas.Tas nozīmē, ka vienmēr ir spēkā tikai pats darījums. augstākais līmenis.

Visas jau atvērtā darījumā izsauktās transakcijas faktiski ir viena un tā paša darījuma daļa, nevis veido ligzdotu darījumu. Tādējādi, atsaucot izmaiņas, kas veiktas ligzdotajā darījumā, galu galā netiks atsauktas izmaiņas pašā ligzdotajā darījumā, bet drīzāk tiks atsauktas visas augstākā līmeņa darījuma izmaiņas. Tajā pašā laikā tiek ignorētas ligzdotā darījumā veiktās izmaiņas.

Darījumu ietekme uz programmatūras objektu darbību

Kopumā 1C:Enterprise sistēmas izmantotie programmatūras objekti ir absolūti caurspīdīgi datu bāzes darījumiem. Citiem vārdiem sakot, datu bāzes transakcijas var izsaukt izpildes laikā dažādas metodes programmatūras objekti, taču, piemēram, darbības, ko datubāze veic, atgriežot darījumu, parasti neietekmē atbilstošo programmatūra objektus.

No tā izriet, ka, atceļot datu bāzes transakcijas, izstrādātājam (ja nepieciešams) patstāvīgi jānodrošina adekvātas izmaiņas attiecīgās datu bāzes datos. programmatūra objektus. To var izdarīt, atkārtoti nolasot visus objekta datus vai mainot dažas programmas objekta detaļas.

Šim noteikumam ir izņēmumi. Sakarā ar 1C:Enterprise sistēmas programmatūras objektu ievērojamo lietojumprogrammu specifiku, dažos gadījumos datu bāzē veikto izmaiņu atcelšana joprojām var ietekmēt atbilstošo īpašību vērtības. programmatūra objektus. Tas notiek šādos gadījumos:

● kad darījums tiek atcelts, dokumenta grāmatošanas atribūts atjauno vērtību, kas bija pirms darījuma sākuma;

● ja objekts ir izveidots un ierakstīts darījumā, tad, transakciju atgriežot, atsauces vērtība tiek dzēsta;

● ja objekts ir izveidots ārpus darījuma un, ierakstot to darījumā, tika izmantots automātiski ģenerēts kods/numurs, tad darījuma atcelšanas gadījumā kods/numurs tiek notīrīts.

2017-08-12

Izveidojiet pielāgotas transakcijas OM objektu uzturēšanai.

Ievads

Domāju, ka daudzi funkcionālie SAP konsultanti ir saskārušies ar organizācijas vadības objektu uzturēšanas darījumu. Proti, darījums PP01

Izmantojot šo darījumu, lietotājs var administrēt organizācijas vadības infotipus tiem objektu tipiem, kas tiek izmantoti automatizētajos biznesa procesos. Ļoti bieži šis darījums tiek izmantots kā vienots ieejas punkts darbam ar visa veida organizācijas vadības objektiem, kas patiesībā nav pārāk laba prakse. Nu, vai ne pārāk ērti. Lai gan noteikti bieži. Tālāk es mēģināšu pastāstīt, kāda varētu būt alternatīva.

Tabula T77S0, grupa "TCODE"

Iestatot OM objektu objektus, jūs, iespējams, pieskarsieties iestatījumam, kas atrodas tālāk norādītajā ceļā SPRO:

IMG: Personāla vadība -> Organizācijas vadība -> Pamatiestatījumi -> Datu modeļa uzlabošana -> Objektu tipu uzturēšana

Šeit jūs izveidojat jaunus OM objektus, izdomājat tiem nosaukumus, atlasāt ikonas un definējat dažus iestatījumus... Šobrīd mūs interesē mezgls " Objekta tipa atslēga + darījums"

Jūsu priekšā tiks atvērta daļa no iestatīšanas skata T77S0 ar filtrētām grupu vērtībām

Ir vērts pievērst uzmanību grupai TCODE kurā, rūpīgi ieskatoties, var atrast to darījumu tehniskos nosaukumus, ar kuriem, visticamāk, nācies strādāt. Turklāt kolonnā Vērtība norāda objekta veidu, kuram paredzēts konkrētais darījums.

Kas šajos darījumos ir īpašs?

Izmantojot darījumus, kas paredzēti noteikta veida objektu uzturēšanai, jums vairs nav jāatlasa tieši šie objektu veidi, kas pēc noklusējuma ir pieejami darījumā. PP01. Tas ir, uzsākot, piemēram, darījumu PO09, jūs nekavējoties sākat strādāt ar tādiem objektiem kā L

Jaunas transakcijas izveide savam organizācijas vadības objektam

Vienā no maniem iepriekšējiem ierakstiem es runāju par to, kā varat izveidot jaunu OM objektu + pievienot tam strukturālu meklēšanu

Es neiešu tālu no šī materiāla. Demonstrācijai es izveidošu jaunu darījumu objekta uzturēšanai 91.

Jauna objekta veida definēšana T77S0

Iestatīšanas skatā definējiet nākotnes darījuma nosaukumu T77S0

Vērtība "ZP91M" šajā gadījumā ir nākotnes darījuma nosaukums par objekta uzturēšanu 91 . Saglabājiet izmaiņas.

Jauna darījuma izveide OM objekta uzturēšanai

Izmantojot darījumu SE93 izveidot darījumu, lai uzturētu savu objektu. Zemāk ir video fragments ar darbību secību, kas jāveic, lai izveidotu atbilstošo darījumu

Ņemiet vērā vērtības, kas tika izmantotas laukiem Programma, Ekrāna numurs,Autorizācijas objekts. Tagad sāciet jaunu darījumu

Lietotājam ir iespēja strādāt tikai ar noteikta veida objektu, ko noteiktā nozīmē var saukt par ērtībām, un, ja vēlaties, minimizēt papildu darbības, lai izvēlētos vēlamo objektu.

Pēdējo reizi skatījāmies vienkāršākais veids izmantojot iebūvēto 1C valodu. Par praksi darījumiem daudz biežāk izmanto kopā ar dizainu. Tas ļauj kļūdas gadījumā turpināt koda izpildi, kā arī nodrošināt lietotājam atbilstošu kļūdas ziņojumu un ierakstīt informāciju reģistrācijas žurnālā vai žurnāla failā, lai sistēmas administrators veiktu turpmāku analīzi.

Ja mēs pievērsīsimies tehniskajai dokumentācijai vai ITS diskam, mēs redzēsim, ka 1C iesaka šādu darījuma organizēšanas metodi, mēģinot

Mēģinājums //1. Darījuma sākums. StartTransaction() ; //2. Darījumā veikto darbību bloks. //3. Ja visas darbības ir veiksmīgas, mēs veicam darījumu. CommitTransaction() ; Izņēmums //4. Ja koda izpildes laikā rodas kļūdas, atceliet darījumu. Atcelt Darījumu() ​​; //5. Ja nepieciešams, ierakstiet žurnālā. //6. Ja nepieciešams, parādiet lietotājam ziņojumu. EndAttempt ;

Patiesībā kodam nav nepieciešams īpašs skaidrojums. Ja notiek mēģinājumi Izpildot darījuma kodu, rodas kļūda, mēs uzreiz iekrītam blokā izņēmums, t.i. pirms metode CommitTransaction() mēs vienkārši nesanākam. Nu, izņēmuma gadījumā mēs attiecīgi atceļam darījumu un, ja nepieciešams, parādām kļūdas ziņojumu un ierakstām informāciju žurnālā. Kļūdas ir ļoti vēlams ierakstīt žurnālā, īpaši tām darbībām, kuras tiek veiktas bez lietotāja līdzdalības (piemēram, rutīnas uzdevumi). Tas ļaus vēlāk analizēt kļūdu. Reģistrācijas vietā varat organizēt ziņojumu nosūtīšanu administratoram pa e-pastu.

Tagad, bruņojušies ar jaunām zināšanām, mēģināsim modificēt kodu, kas apspriests rakstā par . Atgādināšu, ka mēs izskatījām ierakstu direktorijā Preces un informācijas reģistram Cena saskaņā ar šādu shēmu:

&OnServerBez konteksta StartTransaction() ; //ierakstīt jaunu produktu Produkts = Katalogi. Preces. CreateItem() ; Produkts. Nosaukums = "Caurums" ; Produkts. Rakstīt () ; //pierakstiet cenu RecordSet = Informācijas reģistri. Cena. CreateRecordSet() ; NewRecord = RecordSet. Pievienot() ; NewRecord. Periods = PašreizējaisDatums() ; NewRecord. Produkts = produkts. Saite; NewRecord. Summa = 100 ; Ierakstu komplekts. Rakstīt () ; CommitTransaction() ; Procedūras beigas

Tagad ievietosim darījumu blokā Mēģinājums izņēmums. Visticamāk, kļūdas var rasties tikai rakstot uz direktoriju vai informācijas reģistru, tātad iepriekšēja sagatavošanaŅemsim to ārpus darījuma.

&OnServerBez konteksta Procedūra RunTransactionOnServer() //izveidot jaunu produktu Produkts = Katalogi. Preces. CreateItem() ; Produkts. Nosaukums = "Caurums" ; //Izveidot ierakstu ar cenu RecordSet = Informācijas reģistri. Cena. CreateRecordSet() ; NewRecord = RecordSet. Pievienot() ; NewRecord. Periods = PašreizējaisDatums() ; NewRecord. Summa = 100 ; //Mēģinot izpildīt darījumu Mēģinājums StartTransaction(); Produkts. Rakstīt () ; NewRecord. Produkts = produkts. Saite; Ierakstu komplekts. Rakstīt () ; CommitTransaction() ; Izņēmums CancelTransaction() ; Ziņojums = New MessageToUser; Ziņojums. Teksts = ; Ziņojums. Ziņot() ; Žurnāla reģistrācija( "Radās kļūda, ierakstot preci un tā cenu") ; EndAttempt ; Procedūras beigas

Ko NEDRĪKST darīt

Tiem, kas tikai sāk strādāt ar darījumiem, bieži vien rodas vēlme to darīt šādi

StartTransaction() ; Mēģinājums StartTransaction(); //Operāciju bloks CommitTransaction() ; Izņēmums CancelTransaction() ; EndAttempt ; Mēģinājums StartTransaction(); //Operāciju bloks CommitTransaction() ; Izņēmums CancelTransaction() ; EndAttempt ; CommitTransaction() ;

Vai cilpā

StartTransaction() ; Par katru datu no datu masīva cilpas mēģinājums sākt darījumu () ; Dati. Rakstīt () ; CommitTransaction() ; Izņēmums CancelTransaction() ; EndAttempt ; EndCycle ; CommitTransaction() ;

No pirmā acu uzmetiena mēs visu darījām saskaņā ar uzņēmuma 1C ieteikumiem. Bet fakts ir tāds, ka 1C platforma neatbalsta ligzdotos darījumus. Tas ir, tīri tehniski ir iespējams rakstīt šādi. Bet tajā pašā laikā visi ligzdotie darījumi neveido jaunus, bet pieder pie viena un tā paša augstākā līmeņa transakcijas. Tādā veidā, ja viena no ligzdotajām transakcijām neizdodas, nākamo ligzdoto darījumu nevar veikt. Sistēma parādīs šādu ziņojumu: "Šajā darījumā jau ir notikušas kļūdas!". Pierādīsim to ar piemēru. Pieņemsim, ka mēs nolemjam reģistrēt divas preces, katru savā darījumā. Un padarīsim šos darījumus ligzdotas trešajā. Tālāk mēs mākslīgi radīsim kļūdu pirmajā darījumā, izmantojot metodi Paaugstināt izņēmumu:

&OnServerBez konteksta Procedūra RunTransactionOnServer() StartTransaction() ; Mēģinājums StartTransaction(); Produkts = Katalogi. Preces. CreateItem() ; Produkts. Nosaukums = "Tabula" ; Produkts. Rakstīt () ; Paaugstināt izņēmumu "Produkta ievadīšanas kļūda."; CommitTransaction() ; Izņēmums CancelTransaction() ; Ziņojums = New MessageToUser; Ziņojums. Teksts = ErrorDescription() AttemptStartTransaction() ; Produkts = Katalogi. Preces. CreateItem() ; Produkts. Vārds = "Krēsls" ; Produkts. Rakstīt () ; CommitTransaction() ; Izņēmums CancelTransaction() ; Ziņojums = New MessageToUser; Ziņojums. Teksts = ErrorDescription() ; Ziņojums. Ziņot() ; EndAttempt ; CommitTransaction() ; Procedūras beigas

Veicot šo procedūru, ziņojuma logā redzēsim sekojošo:

(ExternalProcessing.TransactionsAtTrying.Form.Form.Form(20)): Kļūda, rakstot vienumu. (ExternalProcessing.TransactionsAtTrying.Form.Form.Form(40)): Kļūda, izsaucot konteksta metodi (Write): šajā darījumā jau ir radušās kļūdas!

Tādējādi ligzdotu darījumu organizēšana 1C ir absolūti bezjēdzīga.

Iespējamie varianti

Tagad atgriezīsimies pie opcijas, kurā reģistrējām produktu un tā cenu. Ja darījuma veikšanas laikā radīsies kļūda, būs grūti saprast, kurā brīdī tā radusies – reģistrējot preci vai ierakstot cenu, jo abi notiek viena mēģinājuma laikā. Lai noteiktu, kur radās kļūda, katra rakstīšanas darbība ir jāiekļauj savā mēģinājumā un jāizvairās no ligzdotiem darījumiem. Lai to izdarītu, mēs ieviešam Būla mainīgo Atteikums un atkarībā no tā vērtības visu darbību beigās mēs veiksim vai atcelsim darījumu.

&OnServerBez konteksta Procedūra RunTransactionOnServer() // Sāciet darījumu Atteikt = False ; StartTransaction() ; // Mēģina ierakstīt produktu Mēģināt produktu = direktoriji. Preces. CreateItem() ; Produkts. Nosaukums = "Caurums" ; Produkts. Rakstīt () ; Izņēmums Failure = patiess ; Ziņojums = New MessageToUser; Ziņojums. Teksts = "Kļūda ierakstot produktu"; Ziņojums. Ziņot() ; EndAttempt ; // Mēģina ierakstīt cenu AttemptRecordSet = Informācijas reģistri. Cena. CreateRecordSet() ; NewRecord = RecordSet. Pievienot() ; NewRecord. Periods = PašreizējaisDatums() ; NewRecord. Produkts = produkts. Saite; NewRecord. Summa = 100 ; Ierakstu komplekts. Rakstīt () ; Izņēmums Failure = patiess ; Ziņojums = New MessageToUser; Ziņojums. Teksts = "Kļūda, ierakstot cenu"; Ziņojums. Ziņot() ; EndAttempt ; // Apstiprināt vai atcelt darījumu Ja NAV neveiksme, tad veiciet Transaction() ; Citādi Atcelt Darījumu() ​​; EndIf ; Procedūras beigas

Mēs varam darīt to pašu, atkārtojot un ierakstot jebkurus datus cilpā. Šajā gadījumā mēs varēsim iegūt visu datu sarakstu ar kļūdām, ja tādas ir.

Gatavojoties 1C Expert sertifikācijai, divu ļoti svarīgu un globālu tēmu - bloķēšanas - priekšvakarā es vēlētos aplūkot kaut ko, bez kura iepriekš minētie jēdzieni nav iespējami - DBVS darījumu.

Darījums- loģiski saistīta, nedalāma darbību secība. Darījumu var pabeigt pilnībā vai nepabeigt vispār. Lai veiktu darījumu DBVS, tiek izmantota COMMIT metode.

Tipisks darījuma piemērs ir pārskaitījums Nauda no viena konta uz citu:

  1. uzsākt darījumu;
  2. nolasīt naudas līdzekļu apjomu konta numurā 123;
  3. samazināt konta atlikumu 123 par 100 rubļiem;
  4. saglabāt konta bilances numuru 123;
  5. nolasīt naudas līdzekļu apjomu konta numurā 321;
  6. palielināt savu bilanci par 100 rubļiem;
  7. 321.kontā ieraksta jauno naudas līdzekļu summu;
  8. veikt darījumu.

Saņemiet 267 video nodarbības 1C bez maksas:

Kā redzam, ja darījums nav pilnībā pabeigts, tad tam nav nozīmes.

Galvenās prasības (ACID) darījumu DBVS

Viena no visizplatītākajām transakciju un transakciju DBVS prasību kopām ir ACID (atomicity, Consistency, Isolation, Durability) kopa. Šie ir rekvizīti, kuriem jābūt jebkuram darījumam:

  • Atomiskums— neviens darījums nav jāreģistrē daļēji;
  • Konsekvence- sistēma ir konsekventā stāvoklī pirms darījuma sākuma, un tai jāpaliek konsekventā stāvoklī pēc darījuma pabeigšanas;
  • Izolācija— darījuma izpildes laikā paralēli darījumi nedrīkst ietekmēt tā rezultātu;
  • Izturība- neveiksmes gadījumā veiksmīgi pabeigta darījuma veiktajām izmaiņām jāpaliek saglabātām pēc sistēmas atsākšanas darbā.

Darījumi 1C

Darījumi 1C 8.3 un 8.2 tiek izveidoti gan automātiski, gan izstrādātāji tos apraksta.

Varat izmantot TransactionActive() metodi, lai noskaidrotu, vai darījums ir aktīvs.

Automātiskās transakcijas piemērs ir dokumenta grāmatošanas apstrāde, direktorija vienuma ierakstīšana datu bāzē, informācijas reģistra ierakstu kopas rakstīšana utt.

Virsraksts iznāca āķīgs, bet uzvārījās. Es uzreiz teikšu, ka mēs runāsim par 1C. Cienījamie 1C lietotāji, jūs nezināt, kā strādāt ar darījumiem, un nesaprotat, kādi ir izņēmumi. Es nonācu pie šāda secinājuma, skatoties liels skaits 1C kods, dzimis vietējā uzņēmuma savvaļā. IN tipiskas konfigurācijas tas viss ir pietiekami labi, taču šausminoši daudz pielāgotā koda ir uzrakstīts neprasmīgi no datu bāzes viedokļa. Vai esat kādreiz redzējis kļūdu “Šajā darījumā jau ir radušās kļūdas”? Ja jā, tad raksta nosaukums attiecas arī uz jums. Beidzot izdomāsim, kas ir darījumi un kā ar tiem pareizi rīkoties, strādājot ar 1C.

Kāpēc mums vajadzētu izsaukt trauksmi?

Vispirms noskaidrosim, kas ir kļūda “Šajā darījumā jau ir radušās kļūdas”. Faktiski tā ir ārkārtīgi vienkārša lieta: jūs mēģināt strādāt ar datu bāzi jau atceltā (atceltā) darījumā. Piemēram, kaut kur tika izsaukta CancelTransaction metode, un jūs mēģināt to izdarīt.


Kāpēc tas ir slikti? Jo šī kļūda neko nesaka par to, kur problēma patiesībā radās. Kad atbalsta dienests no lietotāja saņem ekrānuzņēmumu ar šādu tekstu, un jo īpaši servera kods, ar kuru cilvēks nestrādā interaktīvi ir... Gribēju uzrakstīt “kritiskā kļūda”, bet nodomāju, ka tas ir tāds modes vārds, kuram neviens vairs nepievērš uzmanību... Šis ir ēzelis. Tā ir programmēšanas kļūda. Tā nav nejauša kļūme. Šī ir kļūda, kas nekavējoties jānovērš. Jo, kad jūsu fona servera procesi naktī noiet un uzņēmums sāk strauji zaudēt naudu, tad “Šajā darījumā jau ir radušās kļūdas” ir pēdējais, ko vēlaties redzēt diagnostikas žurnālos.


Protams, pastāv iespēja, ka servera tehnoloģiskais žurnāls (tas ir ieslēgts ražošanā, vai ne?) kaut kādā veidā palīdzēs diagnosticēt problēmu, taču šobrīd es nevaru izdomāt iespēju, kā tieši lai tajā atrastu patieso šīs kļūdas cēloni. Bet patiesais iemesls ir viens - programmētājs Vasja darījuma ietvaros saņēma izņēmumu un nolēma, ka reiz nebija slikta ideja, "padomājiet, tā ir kļūda, turpināsim."

Kas ir darījumi 1C

Ir neērti rakstīt par elementārām patiesībām, bet acīmredzot nedaudz būs nepieciešams. Darījumi 1C ir tādi paši kā darījumi DBVS. Tie nav daži īpaši “1C” darījumi, tie ir darījumi DBVS. Saskaņā ar darījumu vispārējo ideju tos var izpildīt pilnībā vai neizpildīt vispār. Visas izmaiņas datu bāzes tabulās, kas veiktas darījuma ietvaros, var nekavējoties atsaukt, it kā nekas nebūtu noticis.


Tālāk jums jāsaprot, ka 1C neatbalsta ligzdotos darījumus. Faktiski tie netiek atbalstīti “1C”, bet vispār netiek atbalstīti. Vismaz tās DBVS, ar kurām var strādāt 1C. Piemēram, ligzdotas transakcijas nepastāv MS SQL un Postgres. Katrs StartTransaction izsaukums vienkārši palielina darījumu skaitītāju, un katrs izsaukums uz CommitTransaction vienkārši samazina šo skaitītāju. Šī uzvedība ir aprakstīta daudzās grāmatās un rakstos, bet secinājumi no šīs uzvedības acīmredzot nav pietiekami analizēti. Stingri sakot, SQL ir ts. SAVEPOINT, bet 1C tos neizmanto, un šī lieta ir diezgan specifiska.



Procedūra Ļoti noderīgs un svarīgs kods (direktoriju saišu saraksts) StartTransaction(); Katrai saitei no direktoriju saišu saraksta Loop Directory Object = Link.GetObject(); Directory Object.SomeField = "Es tiku nomainīts no programmas koda"; Direktorija objekts.Write(); EndCycle; CommitTransaction(); Procedūras beigas

Kods angļu valodā

Ne īsti. Es absolūti nevēlos dublēt piemērus angļu valodā, lai uzjautrinātu svēto karu un svēto karu cienītājus.


Jūs droši vien rakstāt šādu kodu, vai ne? Piedāvātajā koda piemērā ir kļūdas. Vismaz trīs. Vai jūs zināt, kuras? Uzreiz teikšu par pirmo, tas ir saistīts ar objektu slēdzenēm un nav tieši saistīts ar darījumiem. Par otro - nedaudz vēlāk. Trešā kļūda ir strupceļš, kas notiks šī koda paralēlas izpildes laikā, taču šī ir atsevišķa raksta tēma; mēs to tagad neapskatīsim, lai nesarežģītu kodu. Atslēgvārds googlēšanai: strupceļā kontrolētas slēdzenes.


Lūdzu, ņemiet vērā, ka kods ir vienkāršs. Tā vienkārši ir daudz jūsu 1C sistēmās. Un tajā vienlaikus ir vismaz 3 kļūdas. Padomājiet savā brīvajā laikā, cik daudz kļūdu ir sarežģītākos scenārijos, strādājot ar jūsu 1C programmētāju rakstītiem darījumiem :)

Objektu slēdzenes

Tātad, pirmā kļūda. 1C ir objektu slēdzenes, tā sauktās “optimistiskās” un “pesimistiskās”. Es nezinu, kas izdomāja šo terminu, es būtu viņu nogalinājis :). Pilnīgi neiespējami atcerēties, kurš no viņiem par ko ir atbildīgs. Par tiem ir rakstīts detalizēti, kā arī citā vispārīgā IT literatūrā.


Problēmas būtība ir tāda, ka norādītajā koda piemērā tiek mainīts datu bāzes objekts, bet citā sesijā var būt interaktīvs lietotājs (vai blakus esoša fona pavediens), kas arī mainīs šo objektu. Šeit kāds no jums var saņemt kļūdu "ieraksts ir mainīts vai dzēsts". Ja tas notiek interaktīvā sesijā, lietotājs saskrāpēs savu dibenu, zvēr un mēģinās atkārtoti atvērt veidlapu. Ja tas notiek fona pavedienā, jums tas būs jāmeklē žurnālos. Un žurnāls, kā zināms, ir lēns, un tikai daži cilvēki mūsu nozarē iekārto ELK skursteni 1C baļķiem... (mēs, starp citu, esam starp tiem, kas iekārto un palīdz citiem izveidot :) )


Īsāk sakot, šī ir kaitinoša kļūda, un labāk tās nepieļaut. Tāpēc izstrādes standartos ir skaidri noteikts, ka pirms objektu maiņas ir nepieciešams uz tiem novietot objektu slēdzeni, izmantojot " Direktorija objekts.Lock()". Tad vienlaicīgā sesija (kurai tas arī jādara) nevarēs sākt atjaunināšanas darbību un saņems gaidīto, kontrolēto kļūmi.

Un tagad par darījumiem

Esam tikuši galā ar pirmo kļūdu, pāriesim pie otrās.


Ja šajā metodē nenodrošināsit izņēmumu pārbaudi, izņēmums (piemēram, ļoti iespējams, izmantojot metodi "Write()") izmetīs jūs no šī metode nepabeidzot darījumu. Izņēmums no metodes “Rakstīšana” var būt dažādu iemeslu dēļ, piemēram, tiek aktivizētas dažas lietojumprogrammu pārbaudes biznesa loģikā vai notiek iepriekš minētā objekta bloķēšana. Jebkurā gadījumā otrā kļūda saka: Kods, kas sāka darījumu, nav atbildīgs par tā pabeigšanu.



Tieši tā es nosauktu šo problēmu. Mūsu statiskajā 1C koda analizatorā, kura pamatā ir SonarQube, mēs pat atsevišķi ieviesām šādu diagnostiku. Tagad es strādāju pie tā izstrādes, un 1C programmētāju iztēle, kuru kods nonāk pie manis analīzei, dažreiz atstāj mani šokā un bijībā...


Kāpēc? Tā kā izņēmums, kas tiek izmests darījuma augšpusē, 90% gadījumu neļaus veikt šo darījumu un novedīs pie kļūdas. Jāsaprot, ka 1C automātiski atceļ nepabeigtu darījumu tikai pēc atgriešanās no skripta koda platformas koda līmenī. Kamēr atrodaties 1C koda līmenī, darījums paliek aktīvs.


Pacelsimies vienu līmeni uz augšu zvanu kaudzē:


Procedūra ImportantCode() LinkList = GetLinkListWhere(); VeryUsefulAndImportantCode (saišu saraksts); Procedūras beigas

Paskaties, kas notiek. Mūsu problemātiskā metode tiek izsaukta no kaut kurienes ārpuses, augstākas kaudzes. Šīs metodes līmenī izstrādātājam nav ne jausmas, vai ļoti noderīga un svarīga koda metodes ietvaros tiks veikti darījumi. Un, ja būs, vai tie visi tiks pabeigti... Mēs visi esam šeit miera un iekapsulēšanas dēļ, vai ne? Metodes "ImportantCode" autoram nevajadzētu domāt par to, kas īsti notiek viņa izsauktās metodes iekšienē. Tas pats, kurā darījums tiek apstrādāts nepareizi. Rezultātā mēģinājums strādāt ar datu bāzi pēc tam, kad no darījuma ir izmests izņēmums, visticamāk, radīs sekojošo: “Šajā darījumā bla bla...”

Darījumu izplatīšana dažādās metodēs

Otrais "darījumam droša" koda noteikums: Darījuma atsauces skaitam metodes sākumā un beigās ir jābūt vienādai vērtībai. Jūs nevarat sākt darījumu ar vienu metodi un pabeigt to ar citu. Iespējams, ir iespējams atrast izņēmumus šim noteikumam, bet tas būs kaut kāds zema līmeņa kods, ko rakstījuši kompetentāki cilvēki. Vispār jau tā nevar rakstīt.


Piemēram:


Procedūra ImportantCode() LinkList = GetLinkListWhere(); VeryUsefulAndImportantCode (saišu saraksts); CommitTransaction(); // Biļete uz elli, nopietna saruna ar autoru par mūsu sarežģītajām darba attiecībām. Procedūras beigas

Iepriekš minētais ir nepieņemams kods. Jūs nevarat rakstīt metodes, lai zvanītājs atcerētos un sekotu līdzi iespējamajiem (vai iespējamajiem - kas zina) darījumiem citu izsaukto metožu ietvaros. Tas ir iekapsulēšanas pārkāpums un spageti koda izplatība, ko nevar izsekot ar veselo saprātu.


Īpaši jautri ir atcerēties, ka īstais kods ir daudz lielāks nekā sintētiskie 3 rindu piemēri. Darījumu sākuma un beigu atrašana sešos ligzdošanas līmeņos — tas tieši motivē intīmas sarunas ar autoriem.

Mēģina labot kodu

Atgriezīsimies pie sākotnējās metodes un mēģināsim to labot. Uzreiz teikšu, ka objekta bloķēšanu pagaidām nelabosim, lai nesarežģītu parauga kodu.

Tipiska 1C segvārda pirmā pieeja

Parasti 1C programmētāji zina, ka ierakstīšanas laikā var rasties izņēmums. Viņi arī baidās no izņēmumiem, tāpēc cenšas tos visus noķert. Piemēram, šādi:


Procedūra Ļoti noderīgs un svarīgs kods (direktoriju saišu saraksts) StartTransaction(); Katrai saitei no direktoriju saišu saraksta Loop Directory Object = Link.GetObject(); Directory Object.SomeField = "Es tiku nomainīts no programmas koda"; AttemptDirectoryObject.Write(); Izņēmums Log.Error("Nevarēja ierakstīt elementu %1", Saite); Turpināt; EndAttempt; EndCycle; CommitTransaction(); Procedūras beigas

Nu, lietas ir uzlabojušās, vai ne? Galu galā, tagad iespējamās kļūdas ieraksti tiek apstrādāti un pat reģistrēti. Izņēmumi vairs netiks izmesti, rakstot objektu. Un žurnālā jūs pat varat redzēt, uz kura objekta, es nebiju pārāk slinks un ziņojumā iekļāvu saiti, nevis lakonisku “Kļūda, rakstot direktoriju”, jo bieži vien patīk rakstīt izstrādātājiem, kuri vienmēr steidzas. Citiem vārdiem sakot, ir bažas par lietotāju un kompetenču pieaugums.


Tomēr pieredzējis 1C lietotājs šeit teiks, ka nē, tas nav kļuvis labāks. Patiesībā nekas nav mainījies un varbūt pat pasliktinājies. Izmantojot metodi “Write()”, 1C platforma pati sāks rakstīšanas darījumu, un šis darījums jau būs ligzdots attiecībā pret mūsējo. Un, ja, strādājot ar 1C datu bāzi, darījums tiek atcelts (piemēram, tiek izmests biznesa loģikas izņēmums), mūsu augstākā līmeņa darījums joprojām tiks atzīmēts kā “bojāts” un to nevarēs veikt. Rezultātā šis kods paliks problemātisks, un, mēģinot veikt, tas parādīs “kļūdas jau ir notikušas”.


Tagad iedomājieties, ka runa nav par mazo metodi, bet gan par dziļo zvanu steku, kur pašā apakšā kāds paņēma un “atbrīvoja” iesākto darījumu no savas metodes. Augstākā līmeņa procedūrām var nebūt ne jausmas, ka kāds tur ir sācis darījumus. Rezultātā viss kods neizdodas ar neskaidru kļūdu, kuru principā nav iespējams izmeklēt.


Kods, ar kuru tiek sākts darījums, ir nepieciešams, lai to pabeigtu vai atsauktu. Neatkarīgi no jebkādiem izņēmumiem. Katra koda filiāle ir jāpārbauda, ​​lai noskaidrotu, vai metode tiek izvadīta, neveicot vai neatceļot darījumu.

Metodes darbam ar darījumiem 1C

Nebūtu lieki atgādināt, ko 1C mums parasti nodrošina darbam ar darījumiem. Šīs ir labi zināmās metodes:

  • StartTransaction()
  • CommitTransaction()
  • Atcelt Darījumu()
  • TransactionActive()

Pirmās 3 metodes ir acīmredzamas un dara to, ko saka to nosaukumi. Pēdējā metode atgriež True, ja darījumu skaitītājs ir lielāks par nulli.


Un ir interesanta iezīme. Darījuma izejas metodes (saņemt un atcelt) rada izņēmumus, ja darījumu skaits ir nulle. Tas ir, ja zvanīsit kādam no tiem ārpus darījuma, radīsies kļūda.


Kā pareizi izmantot šīs metodes? Tas ir ļoti vienkārši: jums ir jāizlasa iepriekš formulētais noteikums:


Kā ievērot šo noteikumu? Pamēģināsim:


Mēs jau iepriekš sapratām, ka Do Something metode ir potenciāli bīstama. Tas var radīt kādu izņēmumu, un darījums “izkāps” no mūsu metodes. Labi, pievienosim iespējamo izņēmumu apstrādātāju:


StartTransaction(); Izmēģiniet DoSomething (); Izņēmums // bet ko man te rakstīt? EndAttempt; CommitTransaction();

Lieliski, mēs konstatējām radušos kļūdu, bet kā ar to rīkoties? Vai rakstīt ziņu žurnālam? Nu, varbūt, ja kļūdu reģistrēšanas kodam vajadzētu būt tieši šajā līmenī un mēs šeit gaidām kļūdu. Un ja ne? Kā būtu, ja mēs šeit negaidītu nekādas kļūdas? Tad mums vajadzētu vienkārši nodot šo izņēmumu un ļaut ar to tikt galā citam arhitektūras slānim. Tas tiek darīts ar operatoru "CauseException" bez argumentiem. Šajos jūsu Javascripts tas tiek darīts tieši tāpat ar metiena operatoru.


StartTransaction(); Izmēģiniet DoSomething (); Exception ThrowException; EndAttempt; CommitTransaction();

Tātad, pagaidiet... Ja mēs vienkārši izmetam izņēmumu tālāk, tad kāpēc vispār ir vajadzīgs Mēģinājums? Lūk, kāpēc: noteikums liek mums nodrošināt uzsāktā darījuma pabeigšanu.


StartTransaction(); Izmēģiniet DoSomething (); IzņēmumsAtcelt Darījumu(); mestIzņēmums; EndAttempt; CommitTransaction();

Tagad šķiet, ka tas ir skaisti. Tomēr mēs atceramies, ka mēs neuzticamies Do Something() kodam. Ko darīt, ja autors nelasa šo rakstu un nezina, kā strādāt ar darījumiem? Kā būtu, ja viņš to paņemtu un izsauktu CancelTransaction metodi vai, gluži pretēji, to izdarītu? Mums tas ir ļoti svarīgi izņēmumu apstrādātājs jaunu izņēmumu neiemeta, pretējā gadījumā sākotnējā kļūda tiks zaudēta un problēmu novēršana kļūs neiespējama. Un mēs atceramies, ka Commit un Cancel metodes var radīt izņēmumu, ja darījums nepastāv. Šeit noder TransactionActive metode.

Pēdējā versija

Visbeidzot, mēs varam uzrakstīt pareizo, "darījumam drošu" koda versiju. Šeit viņš ir:


**UPD: komentāros tika ieteikta drošāka opcija, kad CommitTransaction atrodas blokā Mēģinājums. Šī konkrētā opcija ir parādīta šeit; iepriekš Fixation atradās aiz bloka Mēģinājums-Izņēmums.


StartTransaction(); Izmēģiniet DoSomething (); CommitTransaction(); Izņēmums, ja TransactionIsActive() then CancelTransaction(); endIf; mestIzņēmums; EndAttempt;

Pagaidiet, taču kļūdas var radīt ne tikai “CancelTransaction”. Kāpēc tad "CommitTransaction" nav iesaiņots tādā pašā stāvoklī ar "TransactionActive"? Atkal, izmantojot to pašu noteikumu: Kodam, ar kuru tika sākts darījums, ir jābūt atbildīgam par tā pabeigšanu. Mūsu darījums ne vienmēr ir pirmais; to var ligzdot. Mūsu abstrakcijas līmenī mums ir jārūpējas tikai par savu darījumu. Visi pārējie nedrīkst mūs interesēt. Viņi ir svešinieki, mums nevajadzētu par viņiem atbildēt. Tieši viņiem NEDRĪKST. Nedrīkst mēģināt noteikt faktisko darījumu skaitītāja līmeni. Tas atkal izjauks iekapsulēšanu un novedīs pie darījumu pārvaldības loģikas “smērēšanas”. Mēs pārbaudījām darbības tikai izņēmumu apdarinātājā un tikai tāpēc, lai pārliecinātos, ka mūsu apdarinātājs neradīs jaunu izņēmumu, “paslēpjot” veco.

Refaktoringa kontrolsaraksts

Apskatīsim dažas no visbiežāk sastopamajām situācijām, kurās nepieciešama koda iejaukšanās.


Raksts:


StartTransaction(); Dari kaut ko(); CommitTransaction();

Ietiniet to "drošā" dizainā ar mēģinājumu, saglabājiet dzīvību un izdariet izņēmumu.


Raksts:


Ja NotTransactionActive() ThenStartTransaction()EndIf

Analīze un pārstrukturēšana. Autors nesaprata, ko dara. Ir droši sākt ligzdotos darījumus. Stāvoklis nav jāpārbauda, ​​jums vienkārši jāsāk ligzdotais darījums. Zemāk modulī tas, iespējams, joprojām ir izkropļots ar to fiksāciju. Tas ir garantēts hemoroīdi.


Aptuveni līdzīgs variants:


Ja darījums ir aktīvs(), tad CommitTransaction() EndIf

līdzīgi: veikt darījumu ar nosacījumu ir dīvaini. Kāpēc šeit ir kāds nosacījums? Ko, kāds cits jau varēja reģistrēt šo darījumu? Tiesas iemesls.


Raksts:


StartTransaction() While Select.Next() Loop // objekta lasīšana pēc atsauces // objekta rakstīšana EndCycle; CommitTransaction();
  1. ieviest kontrolētu bloķēšanu, lai izvairītos no strupceļa
  2. ievadiet izsaukumu uz bloķēšanas metodi
  3. iesaiņojiet "izmēģiniet", kā parādīts iepriekš

Raksts:


StartTransaction() While Select.Next() Loop Attempt Object.Write(); Izņēmuma ziņojums ("Neizdevās uzrakstīt"); EndAttempt; EndCycle; CommitTransaction();

Izņēmuma gadījumā šis darījums vairs netiks pabeigts. Nav jēgas turpināt ciklu. Kods ir jāpārraksta, pārbaudot sākotnējo uzdevumu. Papildus sniedziet informatīvāku kļūdas ziņojumu.

Beidzot

Es, kā jūs droši vien jau uzminējāt, esmu viens no cilvēkiem, kam patīk 1C platforma un tās attīstība. Protams, par platformu ir pretenzijas, īpaši Highload vidē, taču kopumā tā ļauj lēti un ātri izstrādāt ļoti kvalitatīvas uzņēmuma aplikācijas. ORM, GUI, tīmekļa saskarnes, ziņošanas un daudz ko citu nodrošināšana. Habré komentāros viņi parasti raksta visādas augstprātīgas lietas, tāpēc puiši - galvenā problēma ar 1C kā ekosistēmu nav platforma vai pārdevējs. Tas ir pārāk zems ienākšanas slieksnis, kas ļauj nozarē ienākt cilvēkiem, kuri nesaprot, kas ir dators, datubāze, klients-serveris, tīkls un viss. 1C ir padarījis uzņēmuma lietojumprogrammu izstrādi pārāk vienkāršu. 20 minūtēs varu uzrakstīt uzskaites sistēmu pirkumiem/pārdošanai ar elastīgām atskaitēm un web klientu. Pēc tam man ir viegli pie sevis domāt, ka lielākā mērogā jūs varat rakstīt līdzīgi. Kaut kā 1C visu izdarīs iekšēji, es nezinu, kā, bet tas, iespējams, to darīs. Ļaujiet man uzrakstīt "StartTransaction()"....

Pievienojiet atzīmes