C# med ASP.NET - Winstrand Development

Databaser och C#
ADO.NET
Murach Kapitel 17-20
1
2013-01-30
© Winstrand Development
Databas
• ADO.NET
– Är en del av .NET ramverket och
tillhandahåller delar för att kommunicera
med olika datakällor.
– Dessa kan vara databaser, textfiler, Excelark eller XML-filer.
– Vi kommer att inrikta oss på att arbeta mot
databaser.
© Winstrand Development
2013-01-30
2
Uppgiftslämnare (Data Providers)
• Vi vet att ADO.NET låter oss interagera med olika
typer av datakällor och olika typer av databaser. Det
finns dock inte en enda uppsättning klasser som
tillåter dig att uppnå detta universellt. Eftersom olika
datakällor använder olika protokoll, behöver vi ett sätt
att kommunicera med rätt datakälla genom rätt
protokoll.
• Vissa äldre datakällor använder ODBC-protokollet,
många nyare datakällor använder OLEDB protokollet
och det kommer fler datakällor varje dag som tillåter
att du kommunicerar direkt med dem genom .NETs
ADO.NET klassbibliotek.
© Winstrand Development
2013-01-30
3
Data Providers forts.
• ADO.NET ger en relativt vanligt sätt att
samverka med datakällor, men finns i olika
uppsättningar av bibliotek för varje sätt du
kan prata med en datakälla. Dessa bibliotek
kallas Data Providers.
© Winstrand Development
2013-01-30
4
Tabellen listar några välkända uppgiftslämnare, API prefixet de använder, och vilken
typ av datakälla de tillåter dig att interagera med.
Data källa
API Prefix
Beskrivning
Odbc
Data Sources with an ODBC
interface. Normally older data
bases.
OleDb Data
Provider
OleDb
Data Sources that expose an
OleDb interface, i.e. Access or
Excel.
Oracle Data
Provider
Oracle
For Oracle Databases.
SQL Data Provider
Sql
For interacting with Microsoft
SQL Server.
Bdp
Generic access to many
databases such as Interbase,
SQL Server, IBM DB2, and
Oracle.
ODBC Data
Provider
Borland Data
Provider
© Winstrand Development
2013-01-30
5
ADO.NET Objekt
SQLConnection object
• För att interagera med en databas måste du ha en
anslutning till den.
• Anslutningen hjälper till att identifiera databasservern,
databasnamn, användarnamn, lösenord och andra
parametrar som krävs för att ansluta till databasen.
• Ett anslutningsobjekt används av kommandoobjektet
så att de vet vilken databas som ska användas.
© Winstrand Development
2013-01-30
6
ADO.NET Objekt
SqlCommand object
• Processen att interagera med en databas innebär att
du måste ange de åtgärder du vill ska inträffa.
• Detta görs med ett kommando-objekt. Du använder
ett kommando-objekt för att skicka SQL-satser till
databasen.
• Ett kommando-objekt använder ett anslutningsobjekt
för att veta vilken databas som ska kommuniceras
med.
• Du kan använda ett kommando-objekt ensamt för att
utföra ett kommando direkt, eller tilldela en referens
till en SqlDataAdapter.
© Winstrand Development
2013-01-30
7
ADO.NET Objekt
SqlDataReader objekt
• Många operationer kräver att du bara får en ström av
data för läsning.
• Tillåter dig att få resultatet av en SELECT-sats från
ett kommando-objekt.
• Av prestandaskäl är de data som returneras från
objektet är endast en ström av data.
• Detta innebär att du bara kan ta data från strömmen
på ett sekventiellt sätt
• Detta är bra för hastighet, men om du behöver
manipulera data, då är det bättre att arbeta med
DataSet-objekt.
© Winstrand Development
2013-01-30
8
ADO.NET Objekt
DataSet-objekt
• Är en in-memory representation av data.
• Innehåller flera DataTable-objekt som innehåller
kolumner och rader, precis som vanliga
databastabeller.
• Du kan även definiera relationer mellan tabeller för
att skapa överordnade och underordnade relationer.
• Är särskilt utformat för att hantera data i minnet och
för att stödja frånkopplade operationer på data när ett
sådant scenario krävs.
• Är ett objekt som används av alla uppgiftslämnarna,
varför den inte har ett DataProvider specifik prefix.
© Winstrand Development
2013-01-30
9
ADO.NET Objekt
SqlDataAdapter Objekt
• Ibland när man arbetar med främst skrivskyddad data
och sällan behöver göra ändringar i den
underliggande datakällan eller när vissa situationer
kräver cachning av data i minnet för att minimera
antalet databasanrop för uppgifter som inte ändras.
• Då är det lämpligt att använda sig av
SqlDataAdapter-objektet som gör det enkelt för dig
att utföra dessa saker genom att hjälpa till att hantera
data i en frånkopplad läge.
© Winstrand Development
2013-01-30
10
ADO.NET Objekt
SqlDataAdapter Objekt
• Populerar ett DataSet-objekt när man läser data och
skriver in alltsammans när man har gjort ändringar
• Innehåller en referens till anslutnings-objektet och
öppnar och stänger anslutningen automatiskt när
man läser från eller skriver till databasen.
• Dessutom innehåller kommandoobjekt referenser för
SELECT, INSERT, UPDATE och DELETE
operationer på datan.
• Det definieras en adapter för varje tabell i ett DataSet
och det kommer att sköta all kommunikation med
databasen för dig.
• Allt du behöver göra är att tala om för adaptern när
man laddar från eller skriver till databasen.
© Winstrand Development
2013-01-30
11
Skapa SQL koppling
• Skapa ett SQL kommando
SqlConnection conn = new SqlConnection(@"server=.\SQLExpress;”
+ ”database=spo12;integrated Security=SSPI;");
SqlDataReader rdr = null;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Customers", conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
txtUsers.Text = txtUsers.Text + rdr[1] + " " + rdr[2]
+ " [" + rdr[0] + "]\n";
}
}
finaly
{
if(rdr != null)
{
rdr.Close();
}
if (conn != null)
{
conn.Close();
}
}
© Winstrand Development
2013-01-30
12
Skapa ett SqlCommand objekt
• I likhet med andra C #-objekt, när man instansierar
ett SqlCommand-objekt med en ny instans
deklaration, enligt följande:
SqlCommand cmd = new SqlCommand("SELECT firstname FROM Users", conn);
• Detta är ett typiskt sätt att instansiera ett
SqlCommand-objekt. Det tar en strängparameter
som innehåller det kommando du vill köra och en
hänvisning till ett SQLConnection objekt.
© Winstrand Development
2013-01-30
13
Ställa en fråga
• När du använder SQL-kommandot SELECT får du ett data-set.
För att åstadkomma detta med SqlCommand-objektet använder
du ExecuteReader-metoden som returnerar ett SqlDataReaderobjekt.
• Exemplet nedan visar hur du använder SqlCommand objektet
för att få ett SqlDataReader objekt:
SqlCommand cmd = new SqlCommand ("SELECT firstname FROM Users", conn);
SqlDataReader rdr = cmd.ExecuteReader();
I exemplet ovan, instansierar vi SqlCommand-objektet, skickar
med kommandosträngen och anslutningsobjektet till
konstruktorn.
• Då kan vi få ett SqlDataReader-objekt genom att anropa
ExecuteReader -metoden i cmd.
© Winstrand Development
2013-01-30
14
Infoga data
• Om du vill infoga data i en databas, använder man
ExecuteNonQuery-metoden från SqlCommandobjektet. Följande kod visar hur du infogar data i en
databas tabell:
// Förbereda kommandosträng
string insertString = @"
INSERT INTO Users
(firstname, lastname)
VALUES (’Arne’, ’Andersson’’s’)";
SqlCommand cmd = new SqlCommand(insertString, conn);
cmd.ExecuteNonQuery();
• Denna SqlCommand instansiering är bara lite
annorlunda från vad du har sett förut, men det är i
princip samma.
© Winstrand Development
2013-01-30
15
• Istället för en sträng som första parameter i SqlCommand
konstruktorn använder vi en variabel, insertString.
• Lägg märke till de två apostroferna('') i insertString texten för
ordet ”Andersson’’s”. Det är så man ’escapar’ apostrofer för att
få strängen att fylla kolumnen ordentligt.
• En annan iakttagelse att göra om insert-kommandot är att vi
uttryckligen anger kolumnerna firstname och lastname. Tabellen
Users har ett primärnyckel-fält med namnet id. Vi utelämnade
detta ur listan eftersom SQL Server kommer att lägga till detta
fält själv. Försöker lägga till ett värde till ett primärnyckel-fält,
t.ex. id, kommer det att genereras ett undantag.
• För att utföra detta kommando kallar vi helt enkelt
ExecuteNonQuery-metoden från SqlCommand instansen cmd.
© Winstrand Development
2013-01-30
16
Uppdatera data
• ExecuteNonQuery-metoden används också för att uppdatera
data. Följande kod visar hur du uppdaterar data:
// Förbereda kommandosträng
string updateString = @"
UPDATE Users
SET firstname=’Bamse’
WHERE lastname=’Andersson’’s’";
SqlCommand cmd = new SqlCommand(updateString);
cmd.Connection = conn;
cmd.ExecuteNonQuery();
• Återigen satte vi SQL-kommandot till en sträng variabel, men
den här gången använder vi en annan SqlCommand konstruktor
som bara tar strängen. I steg 2, tilldelar vi SQLConnection
objektet, conn till Connection egenskapen för cmd.
© Winstrand Development
2013-01-30
17
Uppdatera data (forts)
• Detta skulle ha skett på samma sätt om konstruktorn används
med två parametrar. Det visar att man kan ändra anslutningsobjektet när som helst.
• ExecuteNonQuery-metoden utför uppdaterings-kommandot.
© Winstrand Development
2013-01-30
18
Ta bort data
• Du kan också radera data med hjälp av
ExecuteNonQuery-metoden. Följande exempel visar
hur du tar bort en post från en databas med
ExecuteNonQuery:
// Förbereda kommandosträng
string deleteString = @"
DELETE FROM Users
WHERE lastname=’Andersson’’s’";
SqlCommand cmd = new SqlCommand();
cmd.CommandText = deleteString;
cmd.Connection = conn;
cmd.ExecuteNonQuery();
• I exemplet används SqlCommand konstruktorn utan
parametrar. Istället sätter man explicit
CommandText och Connection egenskaperna i
SqlCommand-objektet cmd.
© Winstrand Development
2013-01-30
19
Ta bort data (forts)
• Vi kunde också använt något av de två föregående sätten i
anropet av SqlCommand konstruktorn, med samma resultat.
• Detta visar att du kan ändra både kommandosträngen och
anslutningen när som helst.
• Med ExecuteNonQuery-metodanropet skickar man kommando
till databasen.
© Winstrand Development
2013-01-30
20
• SqlDataReader Objekt
• Att skapa en instans av SqlDataReader är lite
annorlunda än på vilket sätt du initiera andra
ADO.NET objekt. Du måste kalla på ExecuteReader
från ett kommando-objekt, så här:
SqlDataReader rdr = cmd.ExecuteReader();
ExecuteReader är en metod i SqlCommand objektet
cmd, det returnerar en SqlDataReader instans. Man
behöver skapa ett SqlDataReader objekt för att
kunna ta hand om resultatet från de frågor man
ställer med SqlCommand-objektet, som nämnts
tidigare.
© Winstrand Development
2013-01-30
21
SqlDataReader
• Använda inläst data
• Såsom förklarats tidigare, återgår SqlDataReader
data via en sekventiell ström. För att läsa dessa data
måste du hämta data från en tabell rad-för-rad När en
rad har läst, är den tidigare raden inte längre
tillgänglig. För att läsa den raden igen, skulle du
behöva skapa en ny instans av SqlDataReader och
läsa igenom dataströmmen igen.
• Den typiska metoden för läsning från dataströmmen
returneras av SqlDataReader är att loopa igenom
varje rad med en while-slinga. Följande kod visar hur
du gör detta:
© Winstrand Development
2013-01-30
22
while (rdr.Read())
{
// get the results of each column
string contact = (string)rdr["ContactName"];
string company = (string)rdr["CompanyName"];
string city
= (string)rdr["City"];
// print out the results
Console.Write("{0,-25}", contact);
Console.Write("{0,-20}", city);
Console.Write("{0,-25}", company);
Console.WriteLine();
}
© Winstrand Development
2013-01-30
23
• Lägg märke till metodanropet rdr.Read() i villkoret för while.
• Returvärdet från Read är bool och true så länge det finns fler
poster att läsa. När den sista posten i dataströmmen är läst, så
returneras false.
• Tidigare, extraherade vi den första kolumnen från raden med
hjälp av SqlDataReader indexeraren, dvs rdr[0].
• Du kan extrahera varje kolumn i raden med en numerisk
indexerare som denna. I exemplet ovan används en strängindexerare, där strängen är kolumnnamnet från SQL-fråga
(tabell kolumnnamn om du använde en asterisk, *). String
indexerare gör det mycket mer lättläst, vilket gör koden lättare
att underhålla.
• Oavsett vilken typ av indexerarparameter, kommer en
SqlDataReader indexerare returnera ett typobjekt. Detta är
anledningen till typkonverteringen i exemplet ovan.
• När värdena utvinns, kan du göra vad du vill med dem, till
exempel skriva ut dem.
© Winstrand Development
2013-01-30
24
Skapa SQL koppling
• Skapa ett SQL kommando
SqlConnection conn = new SqlConnection(@"server=.\SQLExpress;”
+ ”database=spo12;integrated Security=SSPI;");
SqlDataReader rdr = null;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Customers", conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
txtUsers.Text = txtUsers.Text + rdr[1] + " " + rdr[2]
+ " [" + rdr[0] + "]\n";
}
}
finaly
{
if(rdr != null)
{
rdr.Close();
}
if (conn != null)
{
conn.Close();
}
}
© Winstrand Development
2013-01-30
25
• Länkar till bra sidor på nätet
• http://www.w3schools.com/ado/default.asp
© Winstrand Development
2013-01-30
26