» »

[C# in baze] - Nasvet

[C# in baze] - Nasvet

janez69 ::

Pozdravljeni,

odločil sem se, da se tudi sam naučim programirati in iščem zaposlitev na tem področju.
Zanima me backend, zato sem si izbral C#, ki ga tudi pretežno uporabljajo moji sodelavci. Zraven bom dodal tudi znanje baz. Kot sem si pogledal, gre C# najbolj z roko v roki z Microsoft SQL Server?
Imam prav?

Če je temu tako, bi vas prosil, da mi svetujete dobre tečaje. Kar sem si do sedaj pogledal iz sveta IT-ja mi leži način, ki je predstavljen na Udemy-ju. Se pravi, da instruktor razlaga preko videa, razloži teorijo, postreže s primerom, sledi pa tudi naloga. Tako, da kodo čim več pišem sam.
Rabil bi tako za C#, kot tudi za MSSQL Server.
C# je na Udemy-u precej slabo pokrit. Obstajajo neki tečaji, da naregiš igrico, ampak to mi ne bo koristilo. Rad bi nekaj bolj praktičnega, kot je recimo pošiljanje podatkov sem in tja. To se venomer ponavlja.

Hvala za komentarje.

Pimoz ::

C# gre skupaj s prakticno katerokoli bazo. MSQL je resno samo ena izmed.
Sam v divjini bolj srecujem Oracle, DB2 in MySQL/MariaDb.

Nauci se delanja poizvedb v SQL. To je univerzalno znanje, ki ga lahko kombiniras z vsakim programskim jezikom pa se s cem. So pa malo razlike med posameznimi izvedenkami s cimer se za zacetek ne obremenjuj.
Ne poskusi razumeti samo select, insert in update ampak tudi procedure, funkcije in triggerje in explain plane.

Glede tecajev pa nimam nasveta. Sam jih ne uporabljam.

Ahim ::

OP: isci informacije/tutoriale za "Entity Framework". Kot je omenil predhodnik, obstajajokonektorji na razlicne baze (pri nas smo imeli MS SQL, zdaj je pa MySQL).

win64 ::

Če še nisi programiral priporočam, da prvo pridobiš osnove - to so algoritmi, podatkovne strukture, objektno programiranje.
Potem pa spoznat osnove jezika: podatkovni tipi, sintaksa, delo z nizi, globalizacija.

Potem pa lahko pričneš vključevati še zunanje module:
- Dependency Injection - https://docs.microsoft.com/en-us/dotnet...
- Beleženje - Microsoft.Abstraction.Logging in recimo Serilog
- EntityFrameworkCore za delo z bazo. Mogoče pogledaš tudi EntityFramework - to boš potreboval, če ima podjetje v katerem boš delal kakšne starejše projekte.
- AspNetCore - za pripravo API-jev

kuall ::

Ja, C# + MSSQL = best combo.
tutorialov ne rabiš. downloadaj primere in se uči na njih.
lahko enega pogledaš za začetek, da dobiš občutek, namesto filma, s pirom v roki. ampak bo zguba časa, ti že zdej povem.

Pa ne se jebat z nekimi fancy C# knjižnicami za baze. vse kar rabiš je to:

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand("select * from Requests where Complete = 0", connection))
{
    connection.Open();  
    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            Console.WriteLine(reader["Username"].ToString());
            Console.WriteLine(reader["Item"].ToString());
            Console.WriteLine(reader["Amount"].ToString());
            Console.WriteLine(reader["Complete"].ToString());
        }
    }
}

Zgodovina sprememb…

  • spremenilo: kuall ()

DamijanD ::

razni frameworki za bazo so fajn, ampak še bolj fino je, če uporabnik razume SQL, ker slej ali prej pride(š) do situacije, ko EF nekaj naredi narobe ali pa čudno in takrat rabiš to naredit ročno in razumeti kaj je narobe in kakko bi bilo bolje...

win64 ::

@kuall: DbCommand je sicer zelo dobro, da poznaš. Ampak pozabljaš eno veliko prednost ORM-jev in to je mapiranje v modele. Recimo že tvoj reader["Complete"].ToString() je primer neoptimalne uporabe DbReader.

Optimalno branje je tako, da v SQL stavku definiraš vsa polja, ki jih potrebuješ prebrati (pozabi *). Potem pa za vsako polje je potrebno tako branje: bool? completed = reader.IsDbNull(3) ? reader.GetBoolean(3) : (bool?)null;

ORM ti SQL generira sam(če uporabljaš LINQ), kot tudi sam zgenerira in prevede metodo za mapiranje. Lahko je par % počasnejši od ročnega mapiranja, ampak pridobiš veliko razvojnega časa.
PS: tudi z uporabo ORM-ja lahko ročno napišeš SQL stavek in še vedno uporabiš ORM mapiranje.

MH0 ::

win64 je izjavil:

@kuall: DbCommand je sicer zelo dobro, da poznaš. Ampak pozabljaš eno veliko prednost ORM-jev in to je mapiranje v modele. Recimo že tvoj reader["Complete"].ToString() je primer neoptimalne uporabe DbReader.

Optimalno branje je tako, da v SQL stavku definiraš vsa polja, ki jih potrebuješ prebrati (pozabi *). Potem pa za vsako polje je potrebno tako branje: bool? completed = reader.IsDbNull(3) ? reader.GetBoolean(3) : (bool?)null;

ORM ti SQL generira sam(če uporabljaš LINQ), kot tudi sam zgenerira in prevede metodo za mapiranje. Lahko je par % počasnejši od ročnega mapiranja, ampak pridobiš veliko razvojnega časa.
PS: tudi z uporabo ORM-ja lahko ročno napišeš SQL stavek in še vedno uporabiš ORM mapiranje.


Kako pa potem isto aplikacijo poženeš na različne podatkovne baze? Sam se že 20 let čim bolj držim stran od RAD orodij, ki so mi prepogosto res hitro prevozila nekaj ovinkov v slepo ulico.

win64 ::

Da začnemo na začetku. Osnova za EntityFramework je DbContext. To lahko vzameš kot nekakšen upravitelj objektov. DbContext hrani stanje objektov in preko zunajih providerjev generira SQL stavke, ki se potem izvajajo.
Primer DbContext je recimo TrgovinaDbContext, ki hrani podatke za produkte in cene.

Ta zunanji provider je lahko karkoli: Oracle, MsSql, Sqlite, InMemory(za testiranje),..

Zasnova DbContext, ko recimo želiš brati produkte iz različnih baz je naslednja:
- Ustvariš osnovni DbContext in modele. Recimo TrgovinaDbContext
- Ustvariš DbContext za vsako bazo, ki jo boš podpiral v aplikaciji. Recimo OracleTrgovinaDbContext, MsSqlTrgovinaDbContext. Vse pa razširjajo osnovni TrgovinaDbContext.
- Naslednji korak je definicija polj za entitete(modele) v kodi. Tukaj se lahko greš code-first pristop ali pa generiraš definicije iz obstoječe baze(ukaz Scaffold-DbContext)
- To narediš za vsako bazo posebej. Lahko pa recimo splošne stvari za polja definiraš v TrgovinaDbContext in potem samo specifike definiraš v OracleTrgovinaDbContext ali MsSqlTrgovinaDbContext. Splošne lastnosti so recimo imena. Specifike so kakšni posebni indexi, posebni tipi polj ki obstajajo samo v eni bazi...
- Če delaš po principu code-first, lahko generiraš migracije. Glede na vrsto deploya, lahko migracijo izvedeš v kodi na začetku izvajanja ali pa generiraš SQL za migracijo in ročno zaženeš
- Potem je pa na tebi kako in kje boš kakšen tip DbContext uporabil. Novi pristopi težijo k temu, da vse servise definiraš ob zagonu aplikacije(DI način) in orodja za konfiguracijo so tudi prilagojena temu načinu. To pa ne pomeni, da se ne da na roke konfigurirat.

kuall ::

win64 je izjavil:

Ampak pozabljaš eno veliko prednost ORM-jev in to je mapiranje v modele. Recimo že tvoj reader["Complete"].ToString() je primer neoptimalne uporabe DbReader.

Optimalno branje je tako, da v SQL stavku definiraš vsa polja, ki jih potrebuješ prebrati (pozabi *). Potem pa za vsako polje je potrebno tako branje: bool? completed = reader.IsDbNull(3) ? reader.GetBoolean(3) : (bool?)null;


Malo nakladaš, da je ORM bolj hiter kot SqlConnection. ORM je samo wrapper, SqlConnection je osnova. Ne more bit wrapper hitrejši. Čitaj:
https://stackoverflow.com/questions/953...

Prednost ORM naj bi bila samo manj kode za tipkat za programerja. Kar pa spet ni res IMO.
ORM je en primer navlake, ki je nepotrebna, upočasnjuje program. Jaz se takih navlak izogibam, ker probam imeti možgane frej navlake za bolj pomembne stvari. Raje uporabljam osnove.

Imaš prav, da je dobivanje polj po številki hitrejše kot po imenu polja, ampak to so malenkosti v hitrosti. Prevaga berljivost kode.

win64 ::

ORM ni hitrejši od ročnega mapiranja po postopku, ki sem ga zgoraj zapisal. To je tudi omenjeno.
Že če uporabiš iskanje po imenu zaradi berljivosti je ta % izgubljen.
In ko govorimo o berljivosti in dodamo zraven še vzdrževanje, tukaj delo preko ORM zmaga.

ORM tudi ne potrebuješ uporabljati v celoti:
- Če ne želiš spremljanja sprememb, uporabiš AsNoTracking()
- Če želiš sam zapisati kakšen SQL stavek, uporabiš FromSqlRaw()
- Če ne želiš uporabljati ORM mapiranja lahko še zmeraj uporabiš SqlReader

Na začetku sem tudi tako kot ti delal vse z DbConnection in bil ponosen, ko sem pisal ročno branje in vse naredil sam.
Potem sem po sili razmer moral uporabljati Telerik DataAccess in neke stare verzije EntityFramework. Pri delu spoznaš dobre in slabe stvari.
Sedaj večinoma uporabljam EF Core in ročne SQL stavke uporabljam samo tam kjer ORM dela prepočasi - res zahtevni SQL stavki in batch obdelave.

nightshop ::

Živjo Janez,

drugače, če boš uradno brezposeln ti ZZZS plača tečaj programiranja spletnih aplikacij v C#. Ta tečaj sicer stane par tisoč evrov in je namenjen tistim, ki že programirajo ampak se tega na firmi, ki te tečaje izvaja zavedajo in malo prilagodijo za začetnike. Na koncu pa če si zelo priden narediš še izpit in certifikat, ki pa v .NET/C# svetu kar nekaj pomenijo. Je pa tečaj zelo zahteven in ti pobere praktično ves čas, če želiš narediti izpite računaj 500 ali rajši tam nekje 1000ur.

Na omenjenem tečaju nam je profesor predlagal tole knjigo: https://introprogramming.info/english-i...

Sicer je starejša ampak so programerski problemi noter zelo osnovni, tako da je C# koda notri še vedno delujoča. Jaz sem jo predelal in mi je dala zelo dober uvid v algoritme in strukture, pomoje več kot to ne rabiš za prvo zaposlitev programerja :).

Na Udemy-ju sem vzel pa tale tečaj, nekako mi je še najbolj ustrezal: https://www.udemy.com/course/aspnet-cor... Je pa to osebna preferenca. Delaš pa z bazo z Entity Frameworkom.

Plus, če te bodo zanimale osnove programiranja na malce globljem nivoju, je pa eden boljših (brezplačnih) tečajev Harvard CS50, ki ravno te stvari zelo dobro obdela, je pa tud kar zahtevem ampak nič strašnega.

6bt9hmDwY ::

(k)nightshop, wow, nekoč je vsa napredna certifikacija prišla s tečaji vred par tisoč eurov... Kakšen tečaj je to in kje? Lahko tudi na ZS...

Zgodovina sprememb…

  • spremenilo: 6bt9hmDwY ()

kuall ::

win64 je izjavil:

vzdrževanje, tukaj delo preko ORM zmaga.


Si ziher v to?

1. ORM prekopira celotno strukturo tabel v C#, kar se meni ne zdi ok. Podvojevanje kode. ORM zgenerira več C# kode, to je dejstvo. Spremeniš strukturo tabele, moraš spet generirat C# kodo. Pozabiš to naredit in imaš bug.

2. Debuggiranje ORM je težje, ker moraš kopat v zgenerirano kodo velikokrat.

3. Naučit se moraš neke nove knjižnice, česar se je dobro izognit. Dobro je bit majster v eni stvari, ne povprečen v 100ih.

To so 3 glavni razlogi, zakaj sem proti.

win64 ::

Mogoče odpreva novo temo.

Ja, včasih se je uporabljalo EF z designerjem, ki je zgeneriral edmx definicijo, ki se je embedal v assembly. Na podlagi tega so se zgenerirali modeli in sam DbContext.
Če gledamo danes se modele in dbcontext in ki jih potrebuješ ročno ustvari(ali pa prvič dovoliš da ti jih zgenerira iz baze). Definicija je tudi v bazi.
Spremembe so potrebne, če v bazi spreminjaš tip polja ali pa ga odstraniš. Prilagodiš model in defincijo. Prevajalnik ti pa pomaga videti kje vse uporabljaš spremenjena polja.
V primeru branja z DbConnection pa ravno tako potrebuješ modele, kako boš pa drugače vrnil podatke iz data layerja. V primeru sprememb baze po drugi strani, boš pa moral ročno iskati in spreminjati po vse klice kjer uporabljaš to polje. Nevem meni se zdi ORM v tem primeru bolj varna varjanta.

Tretja točka pa vsakemu svoje. Tudi meni nekatere knjižnice niso pri srcu in se jih izogibam, ta mi je kar prav zastavljena.

6bt9hmDwY ::

Kuall in win64, ef je dober za rapid development (prototype, preproste aplikacije), ne pa tudi za very accurate development. Vsak povprečen developer lahko naredi svojo em, entitetne razredede imaš sicer materializirane v kodi in zadošča mogoče za nek % elementarnih operacij. Takšne stvari smo že uspešno prodajali, samo ne za umazane denarje (no, odvisno od gledišča ;))

To lahko rečem sklicujoč se samo na svojo avtoriteto po skoraj 1l limonovca :-)

Vi toliko nekaj moralizirate in se greste purizem, meni pa je Fseeno, kaj stranka hoče, dokler v redu plača in smo vsi zadovoljni.

Zgodovina sprememb…

  • spremenilo: 6bt9hmDwY ()

win64 ::

Stranka tako ne ve kaj je ORM :)

Še zmeraj velja, da zmeraj vzameš najprimernejše orodje za dosego cilja. Glede na naloge na katerih delam je začet z EF core največkrat prava pot.

Grem še jaz na kak kozarček. Srečno

Zgodovina sprememb…

  • spremenil: win64 ()

kuall ::

win64 je izjavil:

zmeraj vzameš najprimernejše orodje za dosego cilja

tole je en tak predsodek, da glava boli.
dejstvo je, da se da naredit skoraj vse s skoraj vsem. neumnost je menjavat orodja, ker si z novim manj učinkovit. dobro je čimveč stvari naredit na enak način, z istim orodjem, ker tako si bolj učinkovit (hitrejši, manj bugov, ker orodje bolj poznaš). iz istega principa je pogosto menjavanje služb manj učinkovito, ker rabiš vsaj 1 leto, da se dobro vpelješ. če ti pride en programer v službo za pol leta, to ti dela samo zgubo.

janez69 ::

Zdravo,

hvala za vse komentarje. Sam sem trenutni začel s temle videom, ki bo za kakšen teden, potem pa grem na Udemy na daljši tečaj.
Preko ZZZS žal ne bo šlo, saj nisem (in ne nameravam biti) brezposeln. Drugače bi bilo tole super. Morda se da kako pridružiti online? Našel nisem nič kaj konkretne dokumentacije.

Pri kodi se mi je pojavila težava. Spisana je v while loopom, sedaj pa bi jo rad zapisal v do-while loopom. Ne znam dodati, da zapiše, da je igralec izgubil.
Princip gre, da ima 3x možnost ugibati, potem pa izgubi igro. Če zadane je seveda WIN.


Tole je delujoča zadeva:

string secretWord = "giraffe";
            string guess = "";
            int guessCount = 0;                         //starting count; it's 0, because user hasn't entered anything
            int guessLimit = 3;                         //user can guess 3 times
            bool outOfGuesses = false;                  //if user still has guesses it'll be false; if he's out of guesses this is going to be true

            while (guess != secretWord && !outOfGuesses) //if he still have guesses he can guess
            {
                if (guessCount < guessLimit)             //if user still have guesses, he can guess
                {
                    Console.Write("Enter your guess: ");
                    guess = Console.ReadLine();
                    guessCount++;                             //counter guessCount will increment with every guess
                }
                else 
                {
                    outOfGuesses = true;                      //user is out of guesses (called a Flag)
                }
                
            }

            if (outOfGuesses)                                //if outOfGuesses is true -> he lose
            {
                Console.Write("You Lose!");
            }
            else 
            {
                Console.WriteLine("You Win!");
            }



Tole pa je moja z do-while, ki ne deluje:

string secretWord = "giraffe";
            string guess = "";
            int guessCount = 0;
            int guessLimit = 3;
            bool outOfGuesses = false;

            do
            {
                if (guessCount < guessLimit && !outOfGuesses)
                {
                    Console.Write("Enter your guess: ");
                    guess = Console.ReadLine();
                    guessCount++;
                }
                else
                {
                    outOfGuesses = true;
                }

            }
            while (guess != secretWord);
            Console.WriteLine("You WIN!");

            if (outOfGuesses)
            {
                Console.WriteLine("lose");
            } 
            else 
            {
                Console.WriteLine("win");
            }


Mi lahko kdo prosim pove, kaj delam narobe pri 2. kodi?

Hvala.

kuall ::

ok:
 while (guess != secretWord && !outOfGuesses)


bad:
 while (guess != secretWord);



alternativni ok:
                else
                {
                    outOfGuesses = true;
                    break;
                }

janez69 ::

Tole mi je potem uspelo:

    če vpišem "Giraffe", dobim "You win"
    če 3x vpišem narobe dobim "You're wrong and out of guesses."
    če npr. 2x vpišem narobe in v tretje uganim spet dobim "You Win".


Ali je to optimalno? Vem, da se da še drugače na 100 načinov, a vseeno me zanima.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BuildAguessingGame
{
    class Program
    {
        static void Main(string[] args)
        {
            string secretWord = "giraffe";
            string guess = "";
            int guessCount = 0;
            int guessLimit = 3;
            bool outOfGuesses = false;

            do
            {
                if (guessCount < guessLimit && !outOfGuesses)
                {
                    Console.Write("Enter your guess: ");
                    guess = Console.ReadLine();
                    guessCount++;
                }
                else
                {
                    outOfGuesses = true;
                }

            }
            while (guess != secretWord && !outOfGuesses);

            if (outOfGuesses)
            {
                Console.WriteLine("You're wrong and out of guesses.");
            }
            else
            {
                Console.WriteLine("You Win!");
            }

            Console.ReadLine();
        }
    }
}

HotBurek ::

Moja dva centa...


Kar meni ni ok v spodnjem primeru:
- Iz pogoja if (outOfGuesses) ni takoj jasno, da loviš pravi oz. napačni vnos. Rajši bi videl, da je v pogoju if (guess != secretWord). Pa obrnil bi pogoj, iz != na ==.
- Format; če je po if-u in else-u samo en ukaz, se lahko oklepaji izpustijo. Če pa se že uporabijo, je vsaj moja preferenca, da se oklepaj zapiše v isti vrstici, kot if oz. else.

Začetni primer:
if (outOfGuesses)
{
    Console.WriteLine("You're wrong and out of guesses.");
}
else
{
    Console.WriteLine("You Win!");
}

Mogoče še ena opcija:
if (guess == secretWord) 
    Console.WriteLine("You Win!");
else
    Console.WriteLine("You're wrong and out of guesses.");

Drugo, dodal bi komentarje:
- Prvi del za init
- Drugi del za branje in preverjanje vnosa
- Ter trejti del za končni izpis


Ter tretje, za učenje je verjetno ok, da spoznaš do/while, ampak za reševanje tega problema bi vedno izbral for zanko.

Kar še lahko dodaš je izpis, v katerem poizkusu od skupno si (1/3, 2/3, 3/3), ter da za vsak nepravilen vnos izpišeš, da je nepravilen.


Sample v programskem jeziku Python:
#!/usr/bin/python3.9

# init
loops = 3;
match = False;
secret = "giraffe";

# read input in loop and compare if there is secret match
for i in range(0, loops, 1):

    print("[" + str(i+1) + "/" + str(loops) + "] Enter your guess: ", end =" ");
    text = str(input());

    if(text == secret):
        match = True;
        break;
    else:
        print("Fail.");

# print result if win or out of guesses
if match == True:
    print("You Win!");
else:
    print("You're wrong and out of guesses.");

Primer outputa:
[1/3] Enter your guess:  a
Fail.
[2/3] Enter your guess:  b
Fail.
[3/3] Enter your guess:  c
Fail.
You're wrong and out of guesses.

[1/3] Enter your guess:  a
Fail.
[2/3] Enter your guess:  giraffe
You Win!
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Zgodovina sprememb…

  • spremenilo: HotBurek ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[UWP] [C#]

Oddelek: Programiranje
424185 (2215) BivšiUser2
»

C# Branje iz datoteke

Oddelek: Programiranje
5977 (786) boogie_xlr
»

[C#] Kopiranje osebe iz seznama v drug seznam

Oddelek: Programiranje
51491 (1352) Presidente
»

[C#] Klicanje metod

Oddelek: Programiranje
141710 (1478) Cvenemir
»

[C# Linq2SQL]

Oddelek: Programiranje
111366 (1225) BlueRunner

Več podobnih tem