Starglazer
Tukijäsen
- Liittynyt
- 17.10.2016
- Viestejä
- 3 157
Totta, kiitos paljon! Huomaa että tarvitse enemmän kokemusta SQL:stä(TUOTE.HINTA = TAULU.MIN)
OR
(TUOTE.HINTA > TAULU.MIN
and TUOTE.HINTA <= TAULU.MAX)
Totta, kiitos paljon! Huomaa että tarvitse enemmän kokemusta SQL:stä(TUOTE.HINTA = TAULU.MIN)
OR
(TUOTE.HINTA > TAULU.MIN
and TUOTE.HINTA <= TAULU.MAX)
Paitsi ettei tämä sittenkään toimi:Totta, kiitos paljon! Huomaa että tarvitse enemmän kokemusta SQL:stä![]()
Jos EKA ja TOKA ovat ryhmiä jotka määritellään tuotteelle hinnan perusteella niin silloin kannattaa asettaa rajat niin että eivä t mene päällekkäin.Paitsi ettei tämä sittenkään toimi:
(TUOTE.HINTA = TAULU.MIN)
OR
(TUOTE.HINTA > TAULU.MIN
and TUOTE.HINTA <= TAULU.MAX)
Jos hinta = 10, kysely palauttaa molemmat rivit.
TUOTE MIN MAX
EKA 5 10
TOKA 10 15
Kaksi järkevää ratkaisua:SQL ongelma. Eli mulla on käsissä tyhmästi tehty taulu tähän tyyliin:
TUOTE MIN MAX
EKA 5 10
TOKA 10 15
ja tuossa rajalla katsotaan että arvon 10 tuote kuuluu luokkaan "EKA".
Haen taulusta arvoja näin vertailemalla:
TUOTE.HINTA > TAULU.MIN
and TUOTE.HINTA <= TAULU.MAX
Homma toimii hienosti muuten, mutta aivan alin arvo eli "5" jää pois. Miten tuon saa järkevimmin tehtyä?
SELECT * FROM (
SELECT
TUOTE.ID,
TUOTE.HINTA,
TAULU.TUOTE
FROM TUOTE
JOIN TAULU ON
(TUOTE.HINTA >= TAULU.MIN AND TUOTE.HINTA <= TAULU.MAX)
ORDER BY TAULU.MAX ASC
) AS t
GROUP BY t.ID
OWASP?Alkuvuodesta löysin kokonaisen sivuston, joka käsitteli nettipalveluiden turvallisuutta kehittäjän näkökulmasta. Siellä oli mm. tarkistuslistoja. Ei tullut laitettua kirjanmerkkeihin ja nyt en enää löydä sitäTietääkö kukaan mistä sivustosta mahtoi olla kyse?
Juuri tämä. Suurkiitokset!OWASP?
Oletettavasti täältä löytyy vastaus: using statement - C# ReferenceMistähän syystä tuo Context.Users.Add ei toimi? Kokeilin myös ilman asyncia. Koodi menee tuosta läpi kyllä, mutta mitään muutosta ei tapahdu tuolla tietokannassa..?
Tässä vielä tuo DbContext:
EDIT: Auttoi, kun vaihdoin tuon "using (Context)" => "using (var c= new DatabaseContext())". Miksiköhän ihmeessä? Eikö tuo Context palauta aina uuden DatabaseContext:n, kun siellä (luokassa minkä tuo perii) lukee:
"Context => new DatabaseContext();"
Juuri noin kuin ississ jo vastasikin. Toi using tyhjentää lopuksi sen contextin. Toinen yrityksesi toimii koska siinä se luodaan aina uudestaan ennen käyttöä. Todennäköisesti tuossa ei kannattaisi käyttää usingia lainkaan, voit käyttää suoraan sitä alkuperäistä Contextia minkä loit.EDIT: Auttoi, kun vaihdoin tuon "using (Context)" => "using (var c= new DatabaseContext())". Miksiköhän ihmeessä? Eikö tuo Context palauta aina uuden DatabaseContext:n, kun siellä (luokassa minkä tuo perii) lukee:
"Context => new DatabaseContext();"
Hmm, otin nuo using-blokit pois ja laitoin vaan pääluokkaan tuon "public DatabaseContext Context => new DatabaseContext();" ja sitten funktioihin suoraan Context:n käytön. Tuli sama virhe kuin aiemmin sillä using (Context) blokilla, eli Add ja Update eivät tee mitään.Juuri noin kuin ississ jo vastasikin. Toi using tyhjentää lopuksi sen contextin. Toinen yrityksesi toimii koska siinä se luodaan aina uudestaan ennen käyttöä. Todennäköisesti tuossa ei kannattaisi käyttää usingia lainkaan, voit käyttää suoraan sitä alkuperäistä Contextia minkä loit.
Do I always have to call Dispose() on my DbContext objects? Nope
Trollaatko vai teetätkö töitäsi muillaHmm, otin nuo using-blokit pois ja laitoin vaan pääluokkaan tuon "public DatabaseContext Context => new DatabaseContext();" ja sitten funktioihin suoraan Context:n käytön. Tuli sama virhe kuin aiemmin sillä using (Context) blokilla, eli Add ja Update eivät tee mitään.
for /f "delims=: tokens=2" %%a in ('ipconfig ^| findstr /R /C:"IPv4 Address"') do (set tempip=%%a)
set tempip=%tempip: =%
echo %tempip%
Tuolta löytynee vastaus tähän syntaksiin:Pahoitteluni jos menee väärälle osiolle tai väärään ketjuun:
Mitä tuo set tempip=%tempip: =% tekee? Tai siis se poistaa välilyönnin ip-osoitteen edestä, sen tiedän mutta miten se tekee sen? Googlella en löytänyt ratkaisua.Koodi:for /f "delims=: tokens=2" %%a in ('ipconfig ^| findstr /R /C:"IPv4 Address"') do (set tempip=%%a) set tempip=%tempip: =% echo %tempip%
Kiitos jo etukäteen vastauksesta.
Aukeni, kiitos paljon!Tuolta löytynee vastaus tähän syntaksiin:
CMD Variable edit replace - Windows CMD - SS64.com
Aukeaako?![]()
Jokaisella kutsulla tuo property palauttaa uuden instanssin tuosta dbcontext luokasta. Ja kun tuota suhteuttaa tuohon alkuperäiseen koodinpätkään minkä aiemmassa postissa laitoit niin mitään ei luonnollisesti tapahdu, kun SaveChanges:ia kutsutaan, siinä kyseisessä instanssissa ei ole mitään muutoksia mitä tallentaa, muutokset on siinä edellisessä instanssissa.Hmm, otin nuo using-blokit pois ja laitoin vaan pääluokkaan tuon "public DatabaseContext Context => new DatabaseContext();" ja sitten funktioihin suoraan Context:n käytön. Tuli sama virhe kuin aiemmin sillä using (Context) blokilla, eli Add ja Update eivät tee mitään.
npm run startTää on ehkä liian tyhmä kysymys, mutta menkööt.
Mun pitäisi saada windows 10:n käynnistyessä ajettua komentokehotteella tietyssä folderissa komento: npm run start
Ilmeisesti pitäisi tehdä -bat filu, jonka vie windowsin käynnistyksen yhteydessä startattaviin ohjelmiin.
Mutta mikä tuon batch-filun sisältö pitäisi olla, jotta toiveeni toteutuisi?
Joissain tapauksissa parempi vaihtoehto voi olla ajaa sovellus(ta) Windows-palveluna. Hakukoneeseen how to run(/install) node app as windows service..Ilmeisesti pitäisi tehdä -bat filu, jonka vie windowsin käynnistyksen yhteydessä startattaviin ohjelmiin.
Jos tarkoitus on ajaa yksi ainoa komento kertaalleen koneen käynnistyksen yhteydessä, niin en kyllä ihan heti keksi miksi siitä kannattaisi tehdä yhtään monimutkaisempaa kikkailemalla se palveluksi.Joissain tapauksissa parempi vaihtoehto voi olla ajaa sovellus(ta) Windows-palveluna. Hakukoneeseen how to run(/install) node app as windows service..
Ei siellä batissa tarvitse olla muuta, mutta yleensä alussa laitetaan komentojen kaiutus pois päältä, eli tähän tapaan:okei. Eli käytännössä tuo TheMell:n postaus olisi meikäläisen pelastus.
"npm run start
Vie se sitten siihen kansioon missä haluat ajaa sen komennon ja tee pikakuvake käynnistettäviin ohjelmiin
kun teet tekstieditorilla niin tallenna lainausmerkeissä "npmstart.bat" niin notepad ei tee siitä npmstart.bat.txt"
Siis batin sisällä ei tarvitse olla mitään muuta kuin tuo npm run start komento? Olen dorka jos ja kun en tuota yksinkertaisuutta ymmärtänyt. Ja totta, jos se on siellä kansiossa niin siellähän se sitten ajetaan.
@echo off
npm run start
Jos (ja ilmeisesti kun) kyseessä on Windows, fiksuin tapa lienee päästää bat vapaaksi helvetistä, ja ottaa käyttöön VBScript:Noniin. Jatkokysymys jo aiemmin aloitetulle batin tekemiselle, jossa ratkaisu oli siis luoda bat-tiedosto joka ajaa asiansa ja on nyt:
@echo off
npm run start
Milläs ilveellä tuon npm run startin joka avaa erilisenn komentokehotteen auki, saa minimoitua? Nyt prompti aukeaa suoraan näytölle muun oleellisen päälle, joten pitäisi saada jätettyä auki mutta pienennettyä alapalkkiin.
CreateObject("Wscript.Shell").Run "npm run start", 0
Ihan viestin lopussa olikin sivuhuomiona, että ikkuna on kokonaan piilossa - ja vaihtamalla nollan tilalle kakkosen toimii halutulla tavallaHeps kukkuu. @wex , eli tuo 0 jättää kokonaan aukeamatta ruutuun. Tavallaan hyvä, mutta voisi olla näppärämpi tässä skenaariossa että olisi minimoitu vain alapalkkiin. Onko tuohon jokin vaihtoehto. Kyseessä tosiaan win10, ja komentokehotteessa pyörii google assistantin loki sitä mukaa kun jotain tapahtuu tai ei tapahdu. Näppärää olisi, että jos assistant menee mykäksi niin ikkunaa maksimoimalla näkisi mikä error ruudussa on. Muutoin ikkuna saisi olla tosiaan alapalkissa jemmassa, koska lokia ei tarvitse kovinkaan usein käydä vilkuilemassa.
Juu mä en ymmärtänyt, enkä tiedä ymmärsinkö edelleenkään että jääkö se ikkuna auki, alapalkkiin, vai kokonaan aukeamatta noilla numerovaihtoehdoilla. Mä kuitenkin viisastun kun tuossa alan testailemaanIhan viestin lopussa olikin sivuhuomiona, että ikkuna on kokonaan piilossa - ja vaihtamalla nollan tilalle kakkosen toimii halutulla tavalla![]()
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': './debug.log',
},
},
'loggers': {
'django.db.backends':{
'handlers': ['file'],
'level': 'DEBUG',
}
},
}
import React from "react";
import "./Form.css";
const Form = props => {
return (
<form onSubmit={props.createNewItem} className="input-form">
<input type="text" name="name" placeholder="name" required />
<input
type="text"
name="description"
placeholder="description"
required
/>
<input type="text" name="comment" placeholder="comment <optional>" />
<div className="form-btns">
<button
onClick={props.clearFields}
className="form-btn btn-disabled"
id="clear-btn"
>
Clear
</button>
<button className="form-btn">Add</button>
</div>
</form>
);
};
export default Form;
Joko:Reactin harjoittelua, mutta itse kysymykseen. Miten tuollaisessa funktionaalisessa komponentissa saa inputin valuen selville?
Tarkoituksena muuttaa napin luokkaa riippuen onko kentät tyhjiä vai ei.
const Form = (props) => {}..
const Form = props => {}..
Tuo ei liity mitenkään oikeastaan Reactiin, vaan JavaScriptiin. Nuolisyntaksia käytettäessä, jos funktiolla on vain yksi argumentti, niin sulkuja ei tarvita, muissa tapauksissa tarvitaan.Reactiin ja ylläolevaan kyssäriin liittyen, onko sillä mitään käytännön eroa onko se props suluissa vai ei? Vai onko se tietyissä tilanteissa? Kummastelen vaa ku oon törmännyt muutaman kerran muiden koodissa.
vs.Koodi:const Form = (props) => {}..
Koodi:const Form = props => {}..
// huom sulut pakolliset, vaikka parametrejä on "yksi"
const Form = ({ handleChange, handleSubmit }) => {
// ....
<input onChange={handleChange} ... />
}
// vs.
const Form = props => {
// ....
<input onChange={props.handleChange} ... />
}
// jos tähän lisää uuden, versionhallinta highlightaa vaan lisätyn rivin, versus lisätyn + pilkun lisäämisen
const states = [
'OPEN',
'CLOSED',
'ERROR',
]
const string = 'Marko sanoi: "Hepsan hei"'
// vs.
const string = "Marko sanoi: \"Hepsan hei\""
const foo = ({a, b}) => {...}
Tässä on tullutkin jo hyviä vastauksia, mutta kannan oman korteni kekoon.Reactiin ja ylläolevaan kyssäriin liittyen, onko sillä mitään käytännön eroa onko se props suluissa vai ei? Vai onko se tietyissä tilanteissa? Kummastelen vaa ku oon törmännyt muutaman kerran muiden koodissa.
vs.Koodi:const Form = (props) => {}..
Koodi:const Form = props => {}..
declare @Avaintable (uusi int, vanha int)
insert into uusitaulu (sarake1, sarake2, sarake3)
output insterted.avain into @Avaintable(uusi)
select tieto1, tieto2, tieto3
from vanhataulu
Juuh elikkäs MS SQL kyssäri vaihteeksi.
Teen tietojen kopioinnin INSERT INTO lausekkeella.
Laitan uudet avaimet talteen output komennolla.
Pitäisi laittaa talteen myös kopioidun rivin avaintieto eli parina pitää nämä uudet ja vanhat avaimet.
Mitenkäs tuo tehdään?
eli vanhan taulun pääavain pitäisi kohdistaa uuden taulun pääavaimeen.Koodi:declare @Avaintable (uusi int, vanha int) insert into uusitaulu (sarake1, sarake2, sarake3) output insterted.avain into @Avaintable(uusi) select tieto1, tieto2, tieto3 from vanhataulu
Taustalla on että pääavaimella kohdistetaan toisessa taulussa tietoja, ja nämäkin tiedot pitää kopioida vanhoilta avaimilta uusille avaimille. Nyt tuo onnistuu avain kerrallaan määrittelemällä alussa kopioitava avain muuttujaan mutta kun näitä kopioitavia avaimia saataa olla useita kymmeniä.
Helpommin ja nopeimmin menee kun teet uuteen tauluun kentän sille vanhalle avaimelle.Juuh elikkäs MS SQL kyssäri vaihteeksi.
Teen tietojen kopioinnin INSERT INTO lausekkeella.
Laitan uudet avaimet talteen output komennolla.
Pitäisi laittaa talteen myös kopioidun rivin avaintieto eli parina pitää nämä uudet ja vanhat avaimet.
Mitenkäs tuo tehdään?
eli vanhan taulun pääavain pitäisi kohdistaa uuden taulun pääavaimeen.Koodi:declare @Avaintable (uusi int, vanha int) insert into uusitaulu (sarake1, sarake2, sarake3) output insterted.avain into @Avaintable(uusi) select tieto1, tieto2, tieto3 from vanhataulu
Taustalla on että pääavaimella kohdistetaan toisessa taulussa tietoja, ja nämäkin tiedot pitää kopioida vanhoilta avaimilta uusille avaimille. Nyt tuo onnistuu avain kerrallaan määrittelemällä alussa kopioitava avain muuttujaan mutta kun näitä kopioitavia avaimia saataa olla useita kymmeniä.
Itse taulun sarakkeisiin en kajoa koska tuotantojärjestelmä on kyseessä. Google kuitenkin tuotti tulosta ja sain hoidettua homman kursorilla.Helpommin ja nopeimmin menee kun teet uuteen tauluun kentän sille vanhalle avaimelle.
Eli uusi taulu tyyliin
create tabke uusi (
avain identity,
vanha_avain,
kenttä1,
kenttä2,
jne
)
ja sen jälkeen insert into uusi select avain, kenttä1, kenttä2, jne from vanha;
sitten kun loputkin kohdistukset/muunnokset on tehty niin poistat uudesta taulusta vanha_avain- kentän.
declare @Avaintable (vanha int)
declare @HaettuAvain int
declare kursori cursor fast_forward read_only for select vanha from @Avaintable
insert into @Avaintable
select
avain
from
taulu
open kursori
fetch next from kursori into @HaettuAvain
while @@FETCH_STATUS = 0
begin
... kopioi tiedot sekä siihen liittyvän toisen taulun tiedot ...
fetch next from kursori into @HaettuAvain
end
close kursori
deallocate kursori
Voihan sen noinkin tehdä. Tosin rivimäärästä riippuen tuo kursori ja rivi kerrallaan voi olla vähän hidas.Itse taulun sarakkeisiin en kajoa koska tuotantojärjestelmä on kyseessä. Google kuitenkin tuotti tulosta ja sain hoidettua homman kursorilla.
Pseudona suunnilleen näin:
Koodi:declare @Avaintable (vanha int) declare @HaettuAvain int declare kursori cursor fast_forward read_only for select vanha from @Avaintable insert into @Avaintable select avain from taulu open kursori fetch next from kursori into @HaettuAvain while @@FETCH_STATUS = 0 begin ... kopioi tiedot sekä siihen liittyvän toisen taulun tiedot ... fetch next from kursori into @HaettuAvain end close kursori deallocate kursori
No tässä ei ole kyseessä kuin maksimissaan muutama sata riviä niin ei suorituskyvyllä ole kovin isoa merkitystä. Ihan oppimismielessä tämän tein kun SQLlää en ole opetellut ja tässä työssä sitä pääsee näpylöimään. Tämä tietokanta on toimittajan tietokanta ja minä vain lähinnä muuttelen tietoja siellä. Tietokannan ylläpitovastuu on toimittajalla.Voihan sen noinkin tehdä. Tosin rivimäärästä riippuen tuo kursori ja rivi kerrallaan voi olla vähän hidas.
Jos rakenteisiin ei saa koskea ja rivejä on paljon niin tekisin edelleen alkuperäisellä tavalla mutta tulokset ensin temp- tauluun ja sieltä viralliseen uuteen identity_insert päällä jolloin riveille ei enää luoda uusia avaimia syötettäessä viralliseen. Lopuksi temp- taulun poisto.
Harvoin on tullut vastaan niin tiukkoja järjestelmiä ettei datamigraation aikana ole saanut tehdä uusia rakenteita kantaan
OT: Eräs vanha pomoni sanoi, että tulee lyömään minua, jos laitan vielä tuotantokantaan kursoreita. En sitten laittanut, niin en tiedä, olisiko hakkaamisia tapahtunut..No tässä ei ole kyseessä kuin maksimissaan muutama sata riviä niin ei suorituskyvyllä ole kovin isoa merkitystä. Ihan oppimismielessä tämän tein kun SQLlää en ole opetellut ja tässä työssä sitä pääsee näpylöimään. Tämä tietokanta on toimittajan tietokanta ja minä vain lähinnä muuttelen tietoja siellä. Tietokannan ylläpitovastuu on toimittajalla.
Mitä tässä parin vuoden aikana olen opiskellut samalla SQL kieltä niin onhan tuo aivan älyttömän monipuolinen kieli.
No tämä kursori ei ehdi kauaa olla olemassa niin jos selviäisin ilman huutoaOT: Eräs vanha pomoni sanoi, että tulee lyömään minua, jos laitan vielä tuotantokantaan kursoreita. En sitten laittanut, niin en tiedä, olisiko hakkaamisia tapahtunut..
Niiden suorituskyky on oikeassa käytössä karmea, luettavuus huono ja ne voi aina korvata paremmalla ratkaisulla. Esim. tietokannan käyminen läpi kaksi kertaa on parempi ratkaisu. Siis vaikka niin, että tehdään tuo temppitaulu ensin ja sen avulla hoidetaan homma toisella iteraatiolla.
declare @Avaintable (vanha int)
declare @HaettuAvain int
declare @Rivimaara
declare
insert into @Avaintable
select
avain
from
taulu
set @Rivimaara= (select count(*) from @Avaintable)
begin
while rivi < @Rivimaara
set @Haettuavain = @Avaintable(vanha) rivi?
... kopioi tiedot sekä siihen liittyvän toisen taulun tiedot ...
rivi = rivi +1
end
Miksi haluat välttämättä käyttää looppia, se ei ole oikea tapa tehdä asioita tietokannassa.Niin muuten, miten tuo sama tehdään käytännössä while loopilla? Jostain syystä en löytänyt selkeää esimerkkiä? Eli tallennan vaikka 5 tietuetta väliaikaiseen tauluun, miten käyn ne läpi while loopissa?
Koodi:declare @Avaintable (vanha int) declare @HaettuAvain int declare @Rivimaara declare insert into @Avaintable select avain from taulu set @Rivimaara= (select count(*) from @Avaintable) begin while rivi < @Rivimaara set @Haettuavain = @Avaintable(vanha) rivi? ... kopioi tiedot sekä siihen liittyvän toisen taulun tiedot ... rivi = rivi +1 end
Tsekkasitko ohjeet: Heroku Scheduler | Heroku Dev CenterMulla pyörii Herokussa Node/React-sovellus. Sovelluksen pyörittämiseen liittyy pari päivittäin ajettavaa node-skriptiä. Saan ajastettua skriptien ajamisen Heroku Scheduler -addonilla, mutta ongelma on se, että en näe skriptien ajosta mitään ajon aloituksen ja loppumisen lisäksi mitään logeja. Mulla on molemmista skripteissä paljon console.logeja / console.erroreita ja oletin, että ne tulostuisi Herokun logeihin.
Näin ei kuitenkaan ole. Skriptit eivät ole osa sovellusta, joten niiden logit eivät tulostu. Herokun logiin tulostuu ainoastaan sovelluksen sisäiset logit. Onko tähän olemassa mitään helppoa ratkaisua? Logitiedot ovat tärkeitä sovelluksen pyörimisen kannalta.