320 likes | 448 Views
ADO.NET - Pr áca s databázou. ADO.NET. ADO.NET představuje soubor tříd pro přístup k datům v technologii .NET. ADO.NET a .NET Framework. Microsoft .NET Framework. Web Services. User Interface. Data and XML. ADO.NET. XML. Base Classes. Common Language Runtime.
E N D
ADO.NET ADO.NET představuje soubor tříd pro přístup k datům v technologii .NET
ADO.NET a .NET Framework Microsoft .NET Framework Web Services User Interface Data and XML ADO.NET XML ... ... Base Classes Common Language Runtime
Základní pojmy a architektura • Základní jmenné prostory • System.Data – třídy reprezentující obecný přístup k datům, bez ohledu na konktrétní databázi (DataSet, DataTable, Constraint) • System.Data.(OleDb|Oracle|SqlClient|Odbc) – třídy poskytovatelů dat (data providers) • System.Data.Common • System.Data.SqlTypes, System.Data.Sql – specifické třídy pro Microsft SQL Server
.NET Data Providers Hierarchie System.Data .OleDb .SqlClient SqlCommandSqlConnectionSqlDataReaderSqlDataAdapter OleDbCommandOleDbConnectionOleDbDataReaderOleDbDataAdapter
Třídy poskytovatelů dat jsou vždy odvozeny od jedné základní třídy a implementují společné rozhraní podle toho, co mají dělat každá třída má čtyři verze, jejichž jména začínají jménem příslušného poskytovatele dat např. (Sql|OleDB|Oracle|ODBC)Connection implementují rozhraní IDbConnection a dědí od třídy DbConnection, umožňují se připojit k databázi
DatabaseConnection • <provider>Connection • třídy representující spojení s databází • spojení je representována řetězcem (connectionstring), který se předá konstruktorunebonastaví ve vlastnosti ConnectionString • příklad řetězce : “server = (local); integrated security = SSPI; database=Northwind” SqlConnectionconn= newSqlConnection( "server=localhost;database=mojeDatabaze;uid=sa;pwd=");
DatabaseConnection • vlastní spojení se otevře metodou Open • spojení je potřeba nakonec zavřít metodou Close, ideální je následující schéma použití : try { using (SqlConnection c = newSqlConnection(s)) { c.Open(); … ; c.Close() } } catch (SqlException) {…}
RECORD SET • Record set v ADO.NET neexistuje, existoval v ADO • Nahradili ho: • DataReader • DataAdapter • DataSet
DataReader Umožňuje použití souboru záznamů, které jsou výsledkem SQL dotazu. Chová se stejně jako forward-only server-side kursor v klasickém ADO
Príklad Con.Open(); OleDBCommand = new OleDBCommand(“SELECT * FROM Studenti, con”) OleDBDataReader dtr = cmd.ExecuteReader(); While dtr.Read() { listBox.Items.Add(dtr(“meno”)) } … Con.Close();
DataSet a DataAdapter DataSet a DataAdapter, umožňují přenesení dat do lokální cache klienta (tím může být widowsový nebo i webový formulář) a práci s těmito daty i ve stavu, kdy je přerušeno spojení s databází.
DataSet DataSet je výsledkem úsilí spojit klasické ADO s XML datovým formátem DataSet je třída, která se nestará o spojení s databází nebo o SQL dotazy. Jedná se o klientský nástroj pro zpracování dat.
Naplnenie DataSetu • Dva spôsoby: • Použití objektu DataAdapter, který vrací výsledek SQL dotazu ve formě XML. • Pracovat přímo s XML. DataSet má metody s jejichž pomocí umí číst a zapisovat XML data a schémata.
DataAdapter • adaptér je třída představující spojení do databáze a čtyři příkazy • SelectCommand – slouží k vybrání řádků z databáze • UpdateCommand – ukládání změn v řádcích • InsertCommand – ukládání nových řádků • DeleteCommand – mazání řádků • má metody • Fill, která použije SelectCommand k naplnění daty tabulky v DataSetu • Update, která zavolá příslušné příkazy na řádcích, aby se změny projevily v databázi
DataAdapter příkazy je možno nastavit ručně nebo pomocí třídy providera <provider>CommandBuilder CommandBuilder nastaví ostatní příkazy pomocí již nastaveného SelectCommandu SelectCommand musí vracet alespoň jeden primární klíč nebo alespoň sloupec s UniqueConstraint pokud změníte nějaký parametr SelectCommandu musíte metodou RefreshSchema přegenerovat CommandBuilder metody GetUpdateCommand ap. – vrátí příslušný příkaz
Naplenenie cez DataAdapter OleDbConnection con = new OleDbConnection(conStr); OleDbCommand cmd = new OleDbCommand(“SELECT * FROM Studenti”,con); OleDbDataAdapter da = new OleDbDataAdapter(); Da.SelectCommand = cmd; DataSet ds = new DataSet(); da.Fill(ds,”Studenti”);
Iná možnosť da.Fill() SqlDataAdapter adapter = new SqlDataAdapter( "select * from zamestnanci", "server=localhost;database=mojeDatabaze;uid=sa;pwd="); DataSet ds = new DataSet(); adapter.Fill(ds,"zamestnanci");
Update SqlDataAdapter adapter = new SqlDataAdapter("select * from zamestnanci","server=localhost;database=mojeDatabaze;uid=sa;pwd="); DataSet ds = new DataSet(); adapter.Fill(ds,"zamestnanci"); SqlCommandBuilder stavitel = new SqlCommandBuilder(adapter); //Vložení nového řádkuDataTable tabulka = ds.Tables["zamestnanci"]; DataRow novy_radek = tabulka.NewRow(); novy_radek["jmeno"] = "Jan Okoun"; novy_radek["pozice"] = "sef"; novy_radek["adresa"] = "Nekde 12"; novy_radek["telefon"] = "555685"; novy_radek["plat"] = "45000"; tabulka.Rows.Add(novy_radek); //Postoupení změněných řádek zpátky do databázeadapter.Update(ds);
Príklad použitia DataView SqlDataAdapter adapter = new SqlDataAdapter( "select * from zamestnanci","server=localhost;database=mojeDatabaze;uid=sa;pwd="); DataSetds= new DataSet(); adapter.Fill(ds,"zamestnanci"); DataView pohled = new DataView(ds.Tables["zamestnanci"]); pohled.Sort = "jmeno"; pohled.RowFilter = "plat > 20000"; DataGrid.DataSource = pohled; DataGrid.DataBind(); //podla zmeny pohled.RowStateFilter = DataViewRowState.Deleted;
Sql query • Sql príkaz: • SELECT * FROMuzivateleWHEREjmeno=’Maurenc’
Chybná autentifikace – SQL poison bool OveritUzivatele(string login,string heslo){ SqlConnection prip = new SqlConnection ("server=localhost;database=mojeDatabaze;uid=sa;pwd=");try{ prip.Open();SqlCommand prikaz = new SqlCommand ("SELECT count(*) FROM uzivatele WHERE login='"+login+"'"+ "AND heslo='"+heslo+"'",prip);int pocet = (int)prikaz.ExecuteScalar(); return (pocet > 0);}catch(SqlException){returnfalse;}finally{ prip.Close();}}
Možnosti SQl poisoning SELECT count(*) FROM uzivatele WHERE login='Admin' AND heslo='cokoliv' OR 1=1;--‚ Login: cokolivHeslo: x'; INSERT INTO uzivatele VALUES('Hacker','heslo');-- Login: cokolivHeslo: x'; DROP TABLE uzivatele;-- Login: cokolivHeslo: x'; SHUTDOWN WITH NOWAIT;--
Parametrizované príkazy Existujú spôsoby parsovania ako by bolo možné SQL injection predísť Odporučané je ale používať parametrizované príkazy
bool OveritUzivatele(string login,string heslo){ SqlConnection prip = new SqlConnection ("server=localhost;database=mojeDatabaze;uid=sa;pwd="); try{ prip.Open();SqlCommand prikaz = new SqlCommand ("SELECT count(*) FROM uzivatele WHERElogin=@login AND"+ "heslo=@heslo",prip);prikaz.Parameters.Add("@login",SqlDbType.VarChar);prikaz.Parameters.Add("@heslo",SqlDbType.VarChar);prikaz.Parameters["@login"].Value = login;prikaz.Parameters["@heslo"].Value = heslo;int pocet = (int)prikaz.ExecuteScalar();return (pocet > 0); }catch(SqlException){returnfalse;}finally{ prip.Close();}}
bool OveritUzivatele(string login,string heslo){OleDbConnection prip = newOleDbConnection ("provider=sqloledb;server=localhost;database="+ "mojeDatabaze;uid=sa;pwd=");try{ prip.Open();OleDbCommand prikaz = newOleDbCommand ("SELECT count(*) FROM uzivateleWHERE login=? AND"+ "heslo=?",prip);prikaz.Parameters.Add("@login",OleDbType.VarChar);prikaz.Parameters.Add("@heslo",OleDbType.VarChar); prikaz.Parameters["@login"].Value = login;prikaz.Parameters["@heslo"].Value = heslo;int pocet = (int)prikaz.ExecuteScalar();return (pocet > 0);}catch(OleDbException){returnfalse;}finally{ prip.Close();}}
Uložené procedúry CREATEPROCEDURE proc_OveritUzivatele, @loginvarchar(30 ), @heslovarchar(30 ), @pocet int OUTPUTASSELECT @pocet = count(*) FROM uzivatele WHERE login=@login AND heslo=@hesloGO
bool OveritUzivatele(string login,string heslo){ SqlConnection prip = newSqlConnection("server=localhost;database=mojeDatabaze;uid=sa;pwd=");try{prip.Open();SqlCommand prikaz = new SqlCommand("proc_OveritUzivatele",prip);prikaz.CommandType = CommandType.StoredProcedure;prikaz.Parameters.Add("@login",login);prikaz.Parameters.Add("@heslo",heslo);SqlParameter pocet = prikaz.Parameters.Add ("@pocet",SqlDbType.Int);pocet.Direction = ParameterDirection.Output;prikaz.ExecuteScalar();return ((int)pocet.Value > 0); }catch(SqlException){returnfalse;}finally{ prip.Close();}}