ADO.NET
( Active Data Objects . NET)
tworzenie i przetwarzanie lokalnych,
relacyjnych baz danych
współpraca z zewnętrznymi systemami
zarządzania relacyjnymi bazami danych
Lokalna baza danych programu( System.Data )
przestrzeń nazw System.Data klasy:
DataColumn, DataRow, DataTable, DataGridView, DataSet
DataColumn reprezentacja pojedynczej kolumny tabeli danych DataTable
DataColumn colName = new DataColumn();
colName.DataType = Type.GetType("System.String");
// ReadOnly, Caption, ColumnName
dodawanie do tabeli danych
DataTable myTable = new DataTable("MyTable");
myTable.Columns.Add(colName);
autoinkrementacja (przy tworzeniu wierszy)
DataColumn empID = new DataColumn ("EmpID", Type.GetType("System.Int32"));
empID.AutoIncrement = true;
empID.AutoIncrementSeed = 100;
empID.AutoIncrementStep = 10;
DataRow wiersz tabeli danych DataTable
DataTable empTable = new DataTable("Employees");
// columns EmpID, FirstName, LastName
DataRow row = empTable.NewRow(); // !
row["FirstName"] = "John";
row["LastName"] = "Brown";
empTable.Rows.Add(row);
// .DataRow.Delete()
// .AcceptChanges(), .RejectChanges(),
// .BeginEdit(), .EndEdit(), .CancelEdit()
// .DataRow.Deleted , .Detached, .Modified
// .New, .Unchanged
DataTable tabela danych (relacja)
─ definiowanie i dodawanie kolumn
─ dodawanie i wypełnianie wierszy
─ określenie klucza głównego ( kluczy )
DataColumn[ ] PK = new DataColumn [ 1 ];
PK [ 0 ] = MyTable.Columns["EmpID"];
MyTable.PrimaryKey = PK;
─ wyświetlanie tabeli danych
element DataGridView
─ przeciągnąć z palety elementów lub
DataGridView MyGrid = new DataGridView();
─ następnie
MyGrid.DataSource = MyTable;
usuwanie wierszy
try
{ MyTable.Rows[ rowNumber ].Delete( );
MyTable.AcceptChanges( );
}
catch( Exception ex )
{
MessageBox.Show( ex.Message );
}
filtrowanie tabeli danych
string filterStr = "FirstName='John'";
DataRow [ ] TheFirstName =
MyTable.Select( filterStr ); // ,ftSt2, ...
wyrażenie filtrujące ( wybrane operatory i funkcje)
AND OR // operatory logiczne
< <= > >= = <> IN LIKE // relacje
+ - * / % // operatory arytmetyczne
*xxx xxx* %xxx xxx% // uogólnienia
Sum Avg Min Max Count StDev Var // funkcje
sortowanie tabeli danych
TheFirstName = MyTable.Select ( filterStr, "LastName ASC");
// "LastName DESC"
aktualizacja wierszy
DataRow temp;
for(int i=0; i < TheFirstName.Length; i++)
{
temp = TheFirstName[ i ];
temp["FirstName"] = "Ben";
}
ograniczenia : Unique, Foreign Key
try
{
Table_A.Rows.Add(dr);
}catch (ConstraintException ce){
MessageBox.Show (ce.Message ); }
zapis/odczyt do/z plików dyskowych
- serializacja binarna
- serializacja XML
- czytak (tylko odczyt)
DataTableReader dtR = dt.CreateDataReader();
while (dtR.Read())
for (int i = 0; i < dtReader.FieldCount; i++) { // ……… }
dtR.Close();DaBa
DataSet relacyjna baza danych
dowolna liczba tabel DataTable z określonymi powiązaniami
Customers Inventory
FirstNameLastNameCustID (k)
CarID (k)MakeColorPetName
Orders
OrderID (k)CarIDCustID
tworzenie bazy danych
// Data Tables
private DataTable inventoryTable = new DataTable("Inventory");
private DataTable customersTable = new DataTable("Customers");
private DataTable ordersTable = new DataTable("Orders");
// make columns, set keys
// Data Set
private DataSet carsDataSet =
new DataSet("CarDataSet");
// add to data set
carsDataSet.Tables.Add(ordersTable);
carsDataSet.Tables.Add(customersTable);
carsDataSet.Tables.Add(carsTable);
// connect to data grid
CarDataGrid.SetDataBinding (carsDataSet, "Inventory");
CustomerDataGrid.SetDataBinding (carsDataSet, "Customers");
właściwości i funkcje klasy DataSet
DataSet Work = new DataSet("Cars Workshop");
Work.ExtendedProperties["TimeStamp"] = DateTime.Now; Work.ExtendedProperties["DataSetID"] = Guid.NewGuid(); Work.ExtendedProperties["Company"] = "Blue Skrew Super Shop";
▪ serializacja do/z pliku XML
.dataSet1.WriteXml("Plik.xml");
.dataSet1.WriteXml("Plik.xml", XmlWriteMode.WriteSchema);
.dataSet1.ReadXml("Plik.xml");
.dataSet1.ReadXml("Plik.xml",XmlReadMode.ReadSchema);
▪ inne funkcje klasy DataSet
.AcceptChanges()
.Clear()
.Clone()
.Copy()
.GetChanges() // tylko zmienione
.HasChanges()
.Merge()
.RejectChanges()
Grid
definiowanie powiązań pomiędzy tabelami
DataRelation dr = new DataRelation("CustomerOrder",
// parent
carsDataSet.Tables["Customers"]. Columns["CustID"],
// child carsDataSet.Tables["Orders"].
Columns["CustID"]);
carsDataSet.Relations.Add(dr); // Exception
dr = new DataRelation("InventoryOrder",
carsDataSet.Tables["Inventory"].
Columns["CarID"],
carsDataSet.Tables["Orders"].
Columns["CarID"]);
carsDataSet.Relations.Add(dr);
nawigowanie pomiędzy tabelami, np. wyszukanie opisu zamówienia i opisu samochodów na podstawie custID
string strInfo = "";
DataRow drCust = null;
DataRow[ ] drsOrder = null;
int theCust = ... ; // custID
// using custID, get the correct row
drCust = carsDataSet.Tables["Customers"]. Rows[theCust];
strInfo += "Customer Name" + drCust["FirstName"] + "\n";
// navigate from customer table// to order table.
drsOrder = drCust.GetChildRows (carsDataSet.Relations["CustomerOrder"]);
// Get customer orders descriptions
if(drsOrder != null)
foreach(DataRow r in drsOrder)
strInfo += "Order Number: " + r["OrderID"] + "\n";
// navigate from order table // to inventory table
if (drsOrder != null)
{
DataRow[ ] drsInv = new DataRow [drsOrder.Length];
for(int i = 0; i < drsOrder.Length; ++i )
drsInv[i] = drsOrder[i].GetParentRows
(carsDataSet.Relations["InventoryOrder"]);
}
// Get cars descriptions
if(drsInv.Length > 0)
foreach(DataRow r in drsInv)
{
strInfo += "Make: " + r["Make"] + "\n";
strInfo += "Color: " + r["Color"] + "\n";
strInfo += "Pet Name: " + r["PetName"] + "\n";
}
MessageBox.Show(strInfo + " Info based on cust ID");
CarDataSet
PracSam
LINQ to DataSet
var ImPe =
from osa
in dataSet1.Tables["Osoby"].AsEnumerable()
where osa["Imie"].ToString() == "Alicja" //osa["Imie"] : object
select new { im = osa["Imie"], pe = osa["Pobory"] };
foreach (var os in ImPe)
st += os.im + ", " + os.pe.ToString() + "\n";
LinqDS
Współpraca z DBMS
tryb połączeniowy
tryb bezpołączeniowy
Entity Framework
Dostawcy danych ( data providers )
Connection // połączenie
Command // zapytanie SQL
DataReader // czytak
DataAdapter // odwzorowanie
Parametr // parametr
Transaction // transakcja
Dostawcy danych ( data providers )
- wbudowani, np:
- zewnętrzni
www.sqlsummit.com/DataProv.htm
ODBC databases Microsoft OLE DB Provider for ODBC
Microsoft Jet databases OLE DB Provider for Microsoft Jet
Microsoft SQL Server Microsoft OLE DB Provider for SQL Server
Oracle databases Microsoft OLE DB Provider for Oracle
wybór dostawcy na podstawie pliku konfiguracyjnego
enum DataProvider { SqlServer, OleDb, Odbc, None } // Read the provider key.string dataProvString = ConfigurationManager.AppSettings["provider"]; // Transform string to enum.DataProvider dp = DataProvider.None;if (Enum.IsDefined(typeof(DataProvider), dataProvString)) dp = (DataProvider)Enum. Parse(typeof(DataProvider), dataProvString);elseConsole.WriteLine("Sorry, no provider exists!");
// App.config
<configuration>
<appSettings>
<!-- This key value maps to one of
enum values-->
<add key="provider" value="SqlServer"/>
</appSettings>
</configuration>
tryb połączeniowy
- tworzenie i konfigurowanie obiektu połączenia
- tworzenie i konfigurowanie obiektu poleceń
- tworzenie czytaka przekazującego polecenie
- odczytywanie kolejnych rekordów i ich przetwarzanie
- połączenie
using (SqlConnection scn = new SqlConnection())
{
scn.ConnectionString =
// ciag par Property = Value
@"DataSource=(local)\SQLEXPRESS;" +
"Integrated Security=SSPI;" +
"Initial Catalog=AutoLot" +
"Connect Timeout=50";
scn.Open();
}
klasa SqlConnectionStringBuilder
SqlConnectionStringBuilder cnStb = new SqlConnectionStringBuilder();
cnStb.InitialCatalog = ".\Database";
cnStb.DataSource = @"(local)";
// SQL Server
cnStb.ConnectTimeout = 35;
cnStb.IntegratedSecurity = true;
odczytywanie stanu połączenia
scn.DataSource
scn.Database
scn.ConnectionTimeout
scn.State
...............
//
enum ConnectionState
{ Broken, Cloosed, Connecting,
Executing, Fetching, Open }
- polecenie
string strSQL = "Select * from Customers"; SqlCommand FirstCommand = new SqlCommand(strSQL,scn);
// albo
SqlCommand NextCommand =
new SqlCommand( );
NextCommand.Connection = scn;
NextCommand.CommandText = strSQL;
odczytanie strumienia rekordów (bez nawigacji, bez zapisu)
SqlDataReader FirstReader;
FirstDataReader = FirstCommand.ExecuteReader();
while ( FirstDataReader.Read() )
{ .... FirstDataReader ["Make"] ..... }
// można też przekazywać parametry
// SqlParameter
// i wykonywać procedury z bazy danych
// FirstCommand.ExecuteNonQuery
CarsDtReader
indeksowanie pól
SqlDataReader sdr = sCmd.ExecuteReader();
while (sdr.Read())
for(int i = 0; i < sdr.FieldCount; ++i)
{
Console.WriteLine("{0} = {1}", sdr.GetName(i), sdr.GetValue(i).ToString() );
}
odczytywanie rekordów z wielu źródeł
SqlCommand scmd = new SqlCommand(
"SELECT * FROM Customers;" +
"SELECT * FROM Orders", cns);
SqlDataReader sdr = scmd.ExecuteReader();
do
while (sdr.Read())
for(int i = 0; i < sdr.FieldCount; ++i)
{ // ............ }
while(sdr.NextResult());
tryb bezpołączeniowy
- odwzorowanie bazy danych w DataSet DataAdapter
- nie jest konieczne otwieranie i zamykanie
połączenia z bazą danych
- funkcje i właściwości klasy DataAdapter :
Fill() // odwzorowanie wyniku zapytania
SelectCommand
InsertCommand
UpdateCommand
DeleteCommand
Update( )
// odwzorowanie bezpośrednie
string cnStr = "Integrated Security=SSPI;” +
"Initial Catalog=AutoLot;" +
@"DataSource=(local)\SQLEXPRESS";
DataSet ds = new DataSet("AutoLot");
SqlDataAdapter dAdapt = new SqlDataAdapter( "Select * From Inventory", cnStr);
dAdapt.Fill(ds, "Inventory");
// redefinicja nazw
DataTableMapping custMap = dAdapt.TableMappings.Add(
"Inventory", "Magazyn");custMap.ColumnMappings.Add("CarID",
"Identyfikator");custMap.ColumnMappings.Add("Make", "Model");
// aktualizacja bazy danych
DataSet DS = new DataSet("CarsDataSet");
dAdapt.Fill(DS, "Orders");
// dodawanie rekordów do tabeli zamówień
DataRow[] DataRowArray = DS.Tables["Orders"].
Select(null, null, DataViewRowState.Added);
dAdapt.Update( DataRowArray );
// generowanie pozostałych poleceń// w wersji domyślnej (śledzenie zmian)
SqlDataAdapter dAdapt = new SqlDataAdapter("Select * From Orders", cnStr);dAdapt.Fill(DS, "Orders"); // . . . modyfikacja DS
SqlCommandBuilder sqlB =
new SqlCommandBuilder(dAdapt);
dAdapt.Update(DS, "Orders");
Cars
LINQ to SQL
- pobieranie danych z DataSet
( zwykłe połączenie z bazą danych)
var NaPe = from car in
dataSet1.Tables["Inventory"].AsEnumerable()
where (string)car["Color"] == "Red"
select new { ma = (string)car["Make"], pe = (string)car["PetName"] };
Linq3
Pobieranie danych
do obiektu specjalizowanej klasy
dziedziczącej z klasy DataSet
( strongly typed DataSet )
• automatyczne dołączanie bazy danych
DataGridView / Choose Data Source /
Add Project Data Source / Database / Database
New Connection / Browse / Tables
• powstaje klasa opakowująca bazę danych :
tabele, wiersze => klasy wewnętrzne tej klasy
kolumny => składowe klasy wierszy
• powstaje klasa specjalizowanego adaptera danych
=> wywoływany w momencie ładowania formy
TDS
• pobieranie danych
var MaCo = from car in carsDataSet.inventory
where car.Color == "Black"
select new { ma = car.Make, pt = car.PetName };
• aktualizacja
CarsDataSet.inventoryRow dr = carsDataSet.inventory.NewinventoryRow();
dr.CarID = 387; dr.Color = "Black";
dr.Make = "BMW"; dr.PetName = "Mimi";
carsDataSet.inventory.AddinventoryRow(dr);
// lub
carsDataSet.inventory.AddinventoryRow(
444,
"Alfa Romeo",
"Gold",
"Beauty");
// następnie
inventoryTableAdapter.Update
(carsDataSet.inventory);
• dla elementu dataGridView wskazać jako źródło danych wybraną tabelę
=> powstanie specjalizowany obiekt powiązania
• aktualizacja na podstawie dataGridView
inventoryBindingSource.ResetBindings(false);
inventoryTableAdapter.Update(carsDataSet.inventory);
Linq4
ENTITY FRAMEWORKEntity Data Model
• współpraca bezpośrednio z SZBD ( bez kopiowania do DataSet )
• entity – dane związane z pewnym obiektem przetwarzane przez konkretną aplikację { Pracownik : Nazwisko, Pensja }
• Database first - EF tworzy klasy odwzorowujące istniejącą bazę danych
• Design first - program zawiera definicję modelu, na podstawie którego EF tworzy bazę danych
• Code first - EF definiuje model i następnie bazę danych na podstawie istniejącego programu
• mapa (entity) specjalizowana klasa odwzorowująca bazę danych i tworząca jej model
• obsługa mapy (object services) współdziałanie programu z modelem (śledzenie zmian,
aktualizacja, itp.)
• klient mapy (entity client) nawiązywanie połączenia z bazą danych, generowanie zapytań SQL, itp.
• trzy poziomy modeli (plik .edmx):
– model koncepcyjny : definicja map i powiązań między mapami (.csdl)
– model logiczny : odwzorowanie map i ich powiązań w tabele bazy danych (.msl)
– model fizyczny : reprezentacja dostawcy danych (.ssdl)
Database First
• klasa ObjectContext : klasa bazowa klasy definiującej mapę
OsobyEntities kontekst = new OsobyEntities())//dataGridView1.DataSource = kontekst.Lista;
// Osoby : nazwa bazy danych// Lista : nazwa tabeli
// Główne funkcje:AddObject() DeleteObject()AcceptAllChanges() SaveChanges()
ExecuteFunction<T>()GetObjectByKey()
// WłaściwościComandTimeout Connection
//ZdarzeniaSavingChanges
• tworzenie pliku .edmx
─ EdmGen.exe // z konsoli
─ Add New Item ADO.NET Entity Data Model Generate from database
// lub
─ Data Add New Data Source Database Entity Data Model EF Designer from Database
• wizualizacja
StudenciEntities kontekst = new StudenciEntities();//{ dataGridView1.DataSource = kontekst.Student;}// edycja DataGridView// . . . . . . . . . .private void dataGridView1_Validating( object sender, CancelEventArgs e){ kontekst.SaveChanges();}
EDM-DBF-1; 3.5
• aktualizacja
// dodawanie rekorduStudent st = new Student(){ Album = 112233, Imię = "Ewa", Nazwisko = "Kolska", Semestr = 7};kontekst.Student.AddObject(st);kontekst.SaveChanges();
// usuwanie rekorduint alb = 112233;var usu = (from st in kontekst.Student where st.Album == alb select st).FirstOrDefault() // ! if (usu != null){ kontekst.Student.DeleteObject(usu); kontekst.SaveChanges();}
EDM-DBF-2
Design first
–Add New Item ADO.NET Entity Data Model Empty EF Designer Model
–przeciągnąć Entity
–zmienić nazwę, wprowadzić pola
–Generate Database from Model(New Connection)
–SQL : Execute
EDM-DF-1; 4.5
Code First
Przetwarzanie plików XML
wyczytywanie i zapis plików XML
a) serializacja
using System.Xml.Serialization;
//
[Serializable]
public class Disk
{ public string Make ;
[NonSerialized]
public int something ;
public bool SATA;
}
[Serializable]
public class Computer
{ public Disk disk = new Disk ( ) ;
public long Price ;
}
//
[Serializable]
public class Laptop : Computer
{
public double Weight;
}
XmlSerializer xs =
new XmlSerializer(typeof (Laptop));
FileStream data = File.Create ("Lap.xml");
//
Laptop lap = new Laptop();
//
xs.Serialize(data , lap );
data.Close();
//
data = File.OpenRead("Lap.xml");
Laptop nn = (Laptop)xs.Deserialize(data);
<?xml version="1.0"?>
<Laptop xmlns:xsi="http://www.w3.org/2001/
XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<disk>
<Make>NEC</Make>
<SATA>true</SATA>
</disk>
<Price>2127</Price>
<Weight>2</Weight>
</Laptop>
- serializowane są składowe publiczne
- musi istnieć publiczny konstruktor bezargmentowy
- nazwy składowych => nazwy elementów XML
- atrybuty
[XmlAttribute("Producer")]
public string make;
//
[XmlIgnore]
//
b) odczyt bez ładowania dokumentu XmlTextReader
//
XmlTextReader xtr =
new XmlTextReader("Lap.xml");
xtr.Read(); // kolejny element
Console.WriteLine
(
xtr.NodeType.ToString() +
" < " + xtr.Name + " > " +
xtr.Value
);XRD
c) tworzenie pliku XML XmlTextWriter
XmlTextWriter xw =
new XmlTextWriter("NaPro.xml", Encoding.UTF8);
//
xw.WriteStartElement("car");
xw.WriteElementString("Name", CarList[i, 0]); xw.WriteValue(i);
xw.WriteEndElement();
//
xw.Flush();
xw.Close(); XWR
analiza pliku XML XmlDocument
- podstawowe właściwości
ChildNodes // węzły podrzędne I stopnia
FirstChild // pierwszy węzeł podrzędny
Name // nazwa węzła
NodeType // typ węzła XmlNodeTypes
Value // wartość (test)
Attributes // atrybuty
InnerText // wartość węzła i wszystkich
// węzłów zagnieżdżonych
InnerXml // XML : wszystkie zagnieżdżone
OuterXml // XML : bieżący
// i wszystkie zagnieżdżone
- odnajdywanie elementów
GetElementByTagName => XmlNodeList
XmlDocument xdoc = new XmlDocument();
xdoc.Load("FileName");
string TagName = "City"; // <City> Oslo </City>
XmlNodeList xlist =
xdoc.GetElementsByTagName(TagName);
foreach (XmlNode xn in xlist)
{ xn. .... }
string st = xn.FirstChild.Value;
// albo
st = xlist[0].FirstChild.Value; XDoc1
- dopisywanie i usuwanie elementów
xdoc = ..... // XmlDocument
parent = ..... // from XmlNodeList
XmlNode newCar = xdoc.CreateElement("car");
parent.AppendChild(newCar);
XmlNode newName = xdoc.CreateElement("Name");
newCar.AppendChild(newName);
newName.AppendChild ( xdoc.CreateTextNode("Liana") );
xdoc = ..... // XmlDocument
parent = ..... // from XmlNodeList
child = ...... // one of parent’s children
//
parent.RemoveChild(child);
// and all its children
//
xdoc.Save("FileName");
XDoc2
- wyrażenia XPath
<Order>
<Client>
<Name>John Brown</Name>
</Client>
<Items>
<Item>
<Name>DVD Recorder</Name>
<Price>142.99</Price>
</Item>
</Items>
</Order>
XmlDocument doc = new XmlDocument();
doc.Load("orders.xml");
//
XmlNodeList nodes =
doc.SelectNodes("/Order/Items/Item/Name");
//
foreach (XmlNode node in nodes)
{
Console.WriteLine(node.InnerText);
}
LINQ to XML
- tworzenie pliku XML z kolekcji
XDocument xml = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("ListaOsob",
from osoba in listaOsob // list<Osoba>
orderby osoba.Wiek
select new XElement("Osoba",
new XAttribute("Id", osoba.Id),
new XElement("Nazwisko", osoba.Nazwisko),
new XElement("Wiek", osoba.Wiek)))
- pobieranie danych z pliku XML
XDocument xml = XDocument.Load("Osoby.xml");
//
IEnumerable<string> listaOsobPelnoletnich =
from osoba in xml.Descendants("Osoba")
where int.Parse(osoba.Element("Wiek").Value) >= 18
orderby osoba.Element("Nazwisko").Value
select osoba.Element("Nazwisko").Value;
LinqXML
analiza poprawności pliku XML
- składnia XML
XmlDocument xdoc = new XmlDocument();
xdoc.Load("FileName"); // Exception
- wzorzec pliku XML => *.xsd
DataSet ds = ....
ds.WriteXmlSchema(FileName);
//
xsd.exe file.xml => file.xsd
XRD
XmlSchemaSet sc = new XmlSchemaSet();
sc.Add(null, "Cars.xsd");
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas = sc;
XmlReader reader = XmlReader.Create("Cars.xml", settings);
try
{ while (reader.Read()) { } } // read all
catch (XmlSchemaValidationException err)
{...} Veri
korzystanie z serwisów internetowych ( Web Service )
- Project / Add Web Reference
- język WSDL
<wsdl:definitions targetNamespace=
"http://terraserver-usa.com/terraserver/">
<s:element name="ConvertLonLatPtToNearestPlace"><s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="point" type="tns:LonLatPt"/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="LonLatPt">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="Lon" type="s:double"/>
<s:element minOccurs="1"
maxOccurs="1" name="Lat" type="s:double"/>
</s:sequence>
</s:complexType>
<s:element name="ConvertLonLatPtToNearestPlaceResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="ConvertLonLatPtToNearestPlaceResult"
type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
. . . . . . . . . . . . .
- protokół SOAP
<soap:Envelope xmlns:xsi="http://www.w3.org ....
<soap:Body>
<GetWeather
xmlns="http://www.webserviceX.NET">
<CityName>string</CityName>
<CountryName>string</CountryName>
</GetWeather>
</soap:Body>
</soap:Envelope>
net.webservicex.www.GlobalWeather gw =
new net.webservicex.www.GlobalWeather( );
//
string panstwo = " .... ";
//
string Miasta = gw.GetCitiesByCountry(panstwo);
// pobranie nazwy miasta z tekstu XML
string Pogoda = gw.GetWeather(miasto, panstwo);
// pobranie danych pogodowych z tekstu XML
WebSer