Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Web programozás és haladó fejlesztési technikák

Hasonló előadás


Az előadások a következő témára: "Web programozás és haladó fejlesztési technikák"— Előadás másolata:

1 Web programozás és haladó fejlesztési technikák
Adatbázis-elérési rétegek Adatbázisok elérése DbConnection/DbReader módszerrel SQL server elérése DataSet módszerrel Adatfüggetlen logika: LINQ, IQueryable SQL server elérése Entity Framework módszerrel (ORM + DB-LINQ)

2 Web programozás és haladó fejlesztési technikák
Adatbázis-elérési rétegek Adatbázisok elérése DbConnection/DbReader módszerrel SQL server elérése DataSet módszerrel Adatfüggetlen logika: LINQ, IQueryable SQL server elérése Entity Framework módszerrel (ORM + DB-LINQ)

3 Alkalmazás rétegek Mindegyik réteg felbontható belső rétegekre is
Kapcsolódási pontok: interfészek segítségével Az „Alapvető műveletek” listán fogunk mindegyik módszernél végigmenni

4 Legalsó réteg: adatbázis/entities
Mai nap: a Data Access Layer implementációs lehetőségei Market Share adatok (Gartner, Mar/2012)

5 Népszerűség szerint (db-engines.com, FEB/2019)

6 MSSQL MSSQL: tipikusan kis- és középvállalatok által használt adatbázis-kezelő szerver SQL Express: kisebb változat: max 10GB/database, max 1 CPU, max 1GB RAM Korábbi VS verziók (x<2012): SQL Express integrálva volt a fejlesztőeszköz telepítőjébe (Data Source=.\SQLEXPRESS) VS 2010 óta elérhető, VS 2012-től default: LocalDB (Data Source=(localdb)\v11.0) Szerver-szolgáltatás helyett igény szerint induló library, ami egy adatbázis-file-t használ Órán ezt használjuk A gépek egy részén van MSSQL 2014 Express is, ha esetleg projekthez kell MSSQL: aki akarja, az elmondja itt, hogy ez fully ACID compliant :P SQL Express = MS SQL kisebb változata (Oracle, IBM, MSSQL, Sybase, Teradata ; Free: MySQL, PostgreSQL, MariaDB)

7 LocalDB létrehozása In-Solution In-Profile Adatok feltöltése
Project / Add New Item / Service-based Database (ez SQL server file lesz. Local Database: SQL server compact file) Nekünk mindkettő jó, service-based-et használunk: EmpDept Előbb feltöltjük az adatbázist, majd azután generálunk osztályokat In-Profile Server Explorer -> Right click (Data Connections) -> Add Connection ( Microsoft SQL Server + .Net provider for SQL Server <OK>) Server name = (localdb)\v11.0 , Database name = EMPDEPT <OK> "Database does not exist. Attempt to create?" <YES> Akár a „Create New SQL Server Database” is jó, ugyanilyen lépésekkel Adatok feltöltése Új DB-re jobbkatt, New query A létrehozó SQL -ből mindent copypaste, Execute, ez után a query bezárható Új db/tables- re jobbkatt, refresh: táblák megjelennek A táblák minden futtatáskor visszaállnak az eredeti állapotra!

8 DbConnection vs DataSet vs Entity Framework
Cél: adatbázis-kapcsolat felhasználása, SQL utasítások feldolgozása DbConnection Alap SQL-szintű elérés, string SQL utasításokkal, object tömb eredményekkel DataSet Az SQL réteg fölé egy erősen típusos, GUI központú réteg kerül, a műveleteket típusos metódusok végzik Egyedi megközelítés Entity Framework Az SQL réteg fölé ORM (Object Relational Mapping) réteget helyezünk: a táblákat mint objektumok általános gyűjteményét kezeljük Tervezési mintákat felhasználó, általános megközelítés Az „Alapvető műveletek” listán fogunk mindegyik módszernél végigmenni

9 Web programozás és haladó fejlesztési technikák
Adatbázis-elérési rétegek Adatbázisok elérése DbConnection/DbReader módszerrel SQL server elérése DataSet módszerrel Adatfüggetlen logika: LINQ, IQueryable SQL server elérése Entity Framework módszerrel (ORM + DB-LINQ)

10 ADO.NET: DbConnection/DbReader
„Kapcsolt” adatbázis-elérés (Connected Data-Access Architecture) Előny: gyors, egyszerű Hátrány: nehéz módosítani és technológiát/tárolási módszert váltani; kapcsolat elveszését kezelni kell A különböző adatbázis-szerverekhez különböző implementációk Közös ősosztályok a különféle feladatokhoz Adatbázis-kapcsolat: DbConnection SQL/RPC utasítás végrehajtása: DbCommand Utasítás eredményének beolvasása: DbDataReader Specifikus utódosztályok a különféle adatbázis-szerverekhez SqlConnection (MSSQL System.Data.SqlClient) MySqlConnection (MySQL MySql.Data.MySqlClient) NpgsqlConnection (PostgreSQL - Npgsql) OracleConnection (Oracle System.Data.OracleClient) Connected: bármilyen művelet végrehajtásához kapcsolódsz vagy folyamatosan életben tartod a kapcsolatod

11 1. Inicializálás string connStr Source=(LocalDB)\v11.0;AttachDbFilename=path\to\empdept.mdf;Integrated Security=True;"; SqlConnection conn; private void Connect() { conn = new SqlConnection(connStr); conn.Open(); Console.WriteLine("CONNECTED"); }

12 2. INSERT private void Insert() { SqlCommand cmd = new SqlCommand("insert into EMP (ENAME, MGR, DEPTNO, EMPNO) values ('BELA', NULL, 20, 1000)", conn); int affected=cmd.ExecuteNonQuery(); Console.WriteLine(affected.ToString()); }

13 3. UPDATE private void Update() { SqlCommand cmd = new SqlCommand("update EMP set ENAME='JOZSI' where EMPNO=1000", conn); int affected=cmd.ExecuteNonQuery(); Console.WriteLine(affected.ToString()); }

14 4. DELETE private void Delete() { SqlCommand cmd = new SqlCommand("delete from EMP where EMPNO=1000", conn); int affected=cmd.ExecuteNonQuery(); Console.WriteLine(affected.ToString()); }

15 5. SELECT private void Select() { SqlCommand cmd = new SqlCommand("select * from EMP where SAL>=3000 order by ENAME", conn); SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) Console.WriteLine(reader["ENAME"].ToString()); } reader.Close(); Cél: azon nevekkel feltölteni egy listboxot, akiknek a fizetése >= 3000

16 5. SELECT for (int i = 0; i < reader.FieldCount; i++) {
string coltext = reader.GetName(i).ToLower(); Console.WriteLine(coltext); for (int i = 0; i < reader.FieldCount; i++) { Console.WriteLine(reader[i].ToString()); Console.WriteLine(reader.GetValue(i)); Console.WriteLine(reader.GetDecimal(i)); }

17 Problémák SQL Injection: Figyelni kell rá, hogy a usertől kapott adat SOHA ne értelmeződjön utasításként string uName = "yyy", uPass = "xxx"; string sql = $"SELECT * FROM users WHERE username='{uName}' AND userpass=sha2('{uPass}'); uPass = "x') OR 1=1 OR 1<>sha2('x"; Az üzleti logikai kódba bele kell helyezni az SQL kódot, amit módosítani kell adatbázis szerver vagy adatstruktúra módosítás esetén. Az üzleti logika SOHA ne függjön az adattárolás módjától Megoldás: Prepared statements (sql command parameters) Valamilyen erősen típusos, az SQL funkcionalitásával azonos (vagy ahhoz nagyon közelítő) réteget helyezünk az SQL réteg fölé

18 Web programozás és haladó fejlesztési technikák
Adatbázis-elérési rétegek Adatbázisok elérése DbConnection/DbReader módszerrel SQL server elérése DataSet módszerrel Adatfüggetlen logika: LINQ, IQueryable SQL server elérése Entity Framework módszerrel (ORM + DB-LINQ)

19 ADO.NET: DataAdapter/DataSet/DataTable
„Kapcsolat nélküli” adatbázis-elérés (Disconnected mode) Előny: nem kell konkrét SQL utasításokat írni, könnyebb adatkapcsolódás a GUI elemeihez Hátrány: nehéz módosítani és technológiát/tárolási módszert váltani; nagy memóriaigény; egyedi megközelítés Automatikusan generált, adatfüggő típusozott osztályok keletkeznek (~200KB teljesen normális méret egy két táblás adatbázishoz) Az osztályok legenerálása után egyedi osztályok vannak a táblákhoz/adatmezőkhöz: TableAdapter: az adatbázishoz való kapcsolatot építi fel, eredményeket olvas DataSet: az adatbázis reprezentációja BindingSource: adatforrás-kapcsolat az ablak felé Kapcsolat nélküli: NEM tart fenn folyamatos kapcsolatot, az adatbázist teljes egészében a memóriába húzza és ott tartja. Kapcsolódáskor viszi fel a db-be az addigi változtatásokat.

20 DataSet létrehozása (Visual Studio)
Server explorer és Data Sources (Shift+Alt+D) fül kell Server explorer: Adatbázis/connection létrehozása Például LocalDb is jó Data sources: Add new data source Database / DataSet Connection kiválasztása, „Include sensitive data” „Save connection string to the application file”, Táblák kiválasztása Ezután a DataSources-ból a tervező nézetben az ablakra egyszerűen ráhúzzuk a táblát, máris kész az alkalmazás Szerkesztőfelület + beszúrás + törlés + grid

21 1. Inicializálás private void Init() { eMPTableAdapter.Fill(nikdbDataSetVariable.EMP); Console.WriteLine("CONNECTED"); }

22 2. INSERT private void Insert() { DataRow ujsor = nikdbDataSetVariable.EMP.NewRow(); //NewEmpRow() is használható lenne ujsor["ENAME"] = "BELA"; ujsor["MGR"] = DBNull.Value; ujsor["DEPTNO"] = 20; ujsor["EMPNO"] = 1000; nikdbDataSetVariable.EMP.Rows.Add(ujsor); eMPTableAdapter.Update(nikdbDataSetVariable); Console.WriteLine("DONE"); }

23 3. UPDATE private void Update() { DataRow dr = nikdbDataSetVariable.EMP.Rows[0]; dr.BeginEdit(); dr["ENAME"] = "JOZSI"; dr.EndEdit(); nikdbDataSet valtozas=(nikdbDataSet)nikdbDataSetVariable. GetChanges(DataRowState.Modified); if (valtozas.HasErrors) { nikdbDataSetVariable.RejectChanges(); } else { nikdbDataSetVariable.AcceptChanges(); eMPTableAdapter.Update(valtozas); }

24 4. DELETE private void Delete() { DataRow dr = nikdbDataSetVariable.EMP.Rows[0]; dr.Delete(); nikdbDataSetVariable.AcceptChanges(); eMPTableAdapter.Update(nikdbDataSetVariable); } DataRow dr = nikdbDataSetVariable.EMP.Select("empno=1000")[0]; // EZ NEM A LINQ EXTENSION METHOD, CSAK UGYANAZ A NEVE! A kód papíron működik (VS2005-ben még ezt használtam )

25 5. SELECT private void Select() { foreach (DataRow dr in nikdbDataSetVariable.EMP.Select("sal>=3000")) Console.WriteLine(dr["ENAME"].ToString()); } Cél: azon nevekkel feltölteni egy listboxot, akiknek a fizetése >= 3000

26 Web programozás és haladó fejlesztési technikák
Adatbázis-elérési rétegek Adatbázisok elérése DbConnection/DbReader módszerrel SQL server elérése DataSet módszerrel Adatfüggetlen logika: LINQ, IQueryable SQL server elérése Entity Framework módszerrel (ORM + DB-LINQ)

27 A korábbi megközelítések hátránya
Nagyon nehéz szétválasztani az üzleti logikát és az adatfeldolgo-zást végző kódot Nagyon nehéz olyan kódot írni, amelyben ugyanaz az üzleti logikai kód használható attól függetlenül, hogy milyen adatforrást használ (az adatforrás lehet List<T>, XML, MySQL Adatbázis, Oracle Adatbázis, MSSQL Adatbázis …) Nagyon nehéz olyan kódot írni, amelyben futásidőben változtatható, hogy az adatokat honnan szedje Nagyon nehéz olyan kódot írni, amelyhez könnyű igazán jó egységteszteket írni (üzleti logika tesztelése ténylegesen működőképes, ténylegesen használt adatelérő réteg nélkül)

28 Lambda kifejezések használata LINQ metódusokkal
A lambda kifejezések… A LINQ kiegészítő metódusok paraméterei Automatikusan meghívódik mindegyik gyűjtemény elemre Bemenete IEnumerable<T> esetén tipikusan T Kimenete változó (pl. WhereSzűrésbool; OrderByRendezésIComparable) A lambda kimenetekből határozza meg a LINQ metódus kimenetét, ami lehet IEnumerable<T>, IEnumerable<X>, T, int Adatbázisokkal Azonos szintaxis, IQueryable<T> bővítményei expression lambda  optimalizálható! Func<T> helyett Expression<Func<T>>, kívülről ez egyáltalán nem látszik

29 Web programozás és haladó fejlesztési technikák
Adatbázis-elérési rétegek Adatbázisok elérése DbConnection/DbReader módszerrel SQL server elérése DataSet módszerrel Adatfüggetlen logika: LINQ, XML formátum SQL server elérése Entity Framework módszerrel (ORM + DB-LINQ)

30 ORM = Object Relational Mapping – alapfeladat
REJTETT fizikai adatelérés, ami SQL utasításokkal dolgozik Kívülről használható műveletek: dialektus-függetlenség Dialektus-független konverzió: a műveletek végrehajtása független legyen attól, hogy milyen a használt SQL dialektus / adattárolási mód A felső réteg ne SQL nyelvet lásson: Lambda kifejezések (Java Stream Api/C# LINQ) vagy saját lekérdező nyelv (Doctrine) vagy egyszerű CRUD metódusok (Active Record rendszerek) Objektum-tár A felső réteg csak típusos objektumokat lát A lekérdezés eredmények objektumokká/gyűjteményekké konvertálódnak Akár műveletek között is megoszthatóak Az ORM segítségével a felsőbb réteg képes az adatbázist memóriában lévő objektumgyűjteményként kezelni, függetlenül a ténylegesen használt fizikai tárolási módtól

31 ORM = Object Relational Mapping – rendszerek
C#: Entity Framework Java: Hibernate/JPA Python: Django ORM, SQLAlchemy Ruby on Rails PHP: Eloquent, Propel, Doctrine

32 Doctrine DQL

33 Java + Hibernate + Stream API

34 C# + Entity Framework + LINQ
Részletesebben: C# gyakorlatok a mostani héten (LINQ to XML) és a következő héten (Linq to Entities)

35 EF Rétegek

36 Entity Framework (LINQ: to SQL / to Entities)
Formailag nagyon hasonló Régebbi módszer, NEM UGYANAZ! Csak közvetlen leképezést, és csak MSSQL dialektust támogat Egyszerű és gyors, de nagyon korlátozottan használható („Rapid development”) Osztályok létrehozása: Project/Add Class/LINQ to SQL classes ADO.NET Entity Framework (+LINQ to Entites) Teljes ORM N:M kapcsolatokat is támogat Alternatív adatbázis-dialektusokkal is működik/het (Oracle, MySQL...) Entity osztályok létrehozása: Data sources / Add new data source / Database / Entity Data Model Újabb VS verzióknál: Project / Add New Item / Data / ADO.NET Entity Data Model

37 Entity Framework verziók
EF1 = EF3.5  .NET 3.5 (2008) EF4  .NET 4 (2010) „POCO support, lazy loading, testability improvements, customizable code generation and the Model First workflow” EF4.1  „first to be published on NuGet. This release included the simplified DbContext API and the Code First workflow” (2011)  a furcsa ObjectContext api helyére a logikus DbContext api került! EF4.3  „Code First Migrations” (2012)  használható ORM! EF5 (2012), API változások … EF6 (2013), API változások … EF (2014), EF 6.2 (2017)  elterjedt és JÓ ORM!

38 Entity Framework Core EF7: RC … „EF7 introduces some significant changes and improvements over EF6.x. Because EF7 is based on a new core, the features from EF6.x do not automatically carry over into EF7. EF6.x may still be the most suitable release for many applications” EF7 átnevezve, majd kiadva: EF Core „Because of the fundamental changes in EF Core we do not recommend attempting to move an EF6.x application to EF Core unless you have a compelling reason to make the change. You should view the move from EF6.x to EF Core as a port rather than an upgrade.„

39 Entity Framework Core EF Core 1.0: (with ASP.NET Core 1.0) EF Core 2.0: (with ASP.NET Core 2.0) EF Core 2.1: (with ASP.NET Core 2.1)  LAZY LOAD + GROUP BY, elértünk az EF 6.1 szintjére… EF Core 2.2: (with ASP.NET Core 2.2) „small release” - Jó: Client-side/query keys, Cmdline, Mixed client/server evaluation, Raw SQL with LINQ, Statement batches, DbContext pooling - Nem gond: no graphical visualization, no EDMX - Kis gond: Limited inheritance models, No entity splitting, No Database.Log - NAGYON NAGY gond: No entityless many-to-many , No change tracking via Proxies, No lifecycle hooks, No update model from database, No stored procedures

40 Entity Framework Core .NET Core 3  inkább a UI-ra lesz kihegyezve (preview 1 óta tudjuk, hogy igazából arra sem, de erről részletesen majd a Prog4-ben lesz szó…) EF Core 3.0 célok Linq upgrades C#8 support Query types (better support for views) Property bag entities (Dictionary<string, object> szerű elérés  entityless many-to-many support?) EF 6.3 on .NET Core (Könnyebb portolni … ???)

41 Entity model megközelítési módok
Code First: Kézzel megírjuk a POCO entity osztályokat és a DbContext osztályt, és ebből generáljuk az adatbázist Database/SQL First: Kész adatbázisból generáljuk le modell és a context osztályokat Model First: Modellező eszközzel „megrajzoljuk” az adatmodellt (= osztálydiagramot) (EF 6-ban utoljára, a későbbi verziókkal nem támogatott) ( )

42 A modell legenerálása (SQL first)
Előfeltétel: meglévő táblák Project, Add new Item, ADO.NET Entity Data Model <ADD> Generate from database <NEXT> Az MDF file legyen a legördülő menüben + save connection settings <NEXT>; EF6.0 <NEXT>; Mindegyik tábla mellett pipa + Model namespace = EmpDeptModel <FINISH> Konfigurációtól függően: Template can harm your computer, click ok to run ... <OK> <OK> Eredmény: automatikusan generált osztályok (mint DataSetnél), csak ezek nagyrészt generikus osztályok típusparaméterezett változatai vagy POCO osztályok  ~30KB a két táblás adatbázis

43 1. Inicializálás ED = new EmpDeptEntities(); Console.WriteLine("Connect OK"); // DbSet<T> típus, LINQ bővítménymetódusokkal // LINQ query syntax is lehetséges // IEnumerable<T> vs IQueryable<T> DEPT reszleg = ED.DEPT.First(); Console.WriteLine(reszleg.DNAME); // Lazy loading string reszlegNeve = ED.EMP.First().DEPT.DNAME;

44 2. INSERT EMP ujdolg = new EMP() { ENAME = "BELA", MGR = null, DEPTNO = 20, EMPNO = 1000 }; ED.EMP.Add(ujdolg); ED.SaveChanges(); // Save via change tracking! Console.WriteLine("Insert OK");

45 3. UPDATE EMP valaki = ED.EMP.Single(x => x.EMPNO == 1000); valaki.ENAME = "JOZSI"; ED.SaveChanges(); Console.WriteLine("Update OK");

46 4. DELETE EMP valaki = ED.EMP.Single(x => x.EMPNO == 1000); ED.EMP.Remove(valaki); ED.SaveChanges(); Console.WriteLine("Delete OK");

47 ORM használatának előnyei
A kódban sehol sem használunk dialektus függő SQL utasításokat Bármikor dialektust/szervert válthatunk a kód átírása nélkül Saját EF/Linq provider írásával akár tetszőleges tárolási mód is lehetséges A string formátumú SQL utasítások helyett a fordítás közben szintaktikailag ellenőrzött lekérdező formátumot használunk A fordítás közben kiderül, ha a bárhol szintaktikai hiba van A string formátumú SQL paraméterek (string összefűzés) helyett változókat használunk lekérdezés paraméterként SQL injection elkerülése A lekérdezések eredménye nem általános anonymous típus / objektum / asszociatív tömb Helyette erősen típusos ismert típusú érték / példány / lista Az ORM rétegre +1 réteg elhelyezésével könnyedén megoldható az adatforrás tetszőleges cseréje és a kód tesztelése Repository Pattern, Dependency Injection Pattern

48 ORM használatának hátrányai
“ORM is a terrible anti-pattern that violates all principles of object-oriented programming, tearing objects apart and turning them into dumb and passive data bags. There is no excuse for ORM existence in any application” Ez persze csak egyetlen vélemény, de tipikus negatívumok: Nehezebb konfiguráció Nagyobb memóriaigény Nagyobb CPU igény Bonyolultabb lekérdezések szegényes/nehéz támogatása Nehéz optimalizáció

49 ORM sebessége (C#)

50 ORM sebessége (PHP)

51 Rétegek: DATA

52 Rétegek: REPO

53 Rétegek: REPO

54 Rétegek: REPO

55 Források http://msdn.microsoft.com/en-us/library/bb882674
… és még soksok link az msdn.microsoft.com –ról … és még soksok link a stackoverflow.com –ról LINQ: Reiter István: C# jegyzet ( , 250. oldal (A könyv az alap LINQ to Objects-et tartalmazza)

56

57


Letölteni ppt "Web programozás és haladó fejlesztési technikák"

Hasonló előadás


Google Hirdetések