Documente Academic
Documente Profesional
Documente Cultură
1/16
Entity Framework
Conexiuni, Tranzactii, Multithreading
Ce vom discuta:
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 2/16
EF foloseste stringul de conexiune din fisierul de configurare ce are extensia .config si va crea
si folosi automat o conexiune la baza de date.
In ADO.NET clasic trebuie sa realizam (in general) urmatoarele:
• sa deschidem o conexiune (DbConnection);
• sa instantiem si sa definim o comanda (DbCommand);
• sa executam comanda (ExecuteReader(), ExecuteScalar(), etc.);
• sa inchidem conexiunea.
In EF, ObjectContext face aceste lucruri in background. Exista situatii cand avem nevoie sa
controlam conexiunea in EF. Cum o facem?
Metadata
Puncteaza la fisierele :
Conceptual Schema Definition Layer [CSDL];
Mapping Schema Layer [MSL];
Store Schema Definition Layer [SSDL].
Provider connection
Stringul de conexiune la baza de date.
Provider name
Namespace-ul furnizorului bazei de date.
Name
Numele stringului de conexiune.
In exemplul de mai jos sunt marcate cu rosu cele patru parti componente pentru
EntityConnection.
<connectionStrings>
<add
name="BreakAwayEntities"
connectionString=
"metadata=res://*/BAModel.csdl|res://*/BAModel.ssdl|
res://*/BAModel.msl;
provider=System.Data.SqlClient;
provider connection string='Data Source=myserver;
Initial Catalog=BreakAway;
Integrated Security=True;
MultipleActiveResultSets=True'"
providerName="System.Data.EntityClient"
/>
</connectionStrings>
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 3/16
Cand distribuim in mediul real (productie) o baza de date unul din lucrurile care trebuiesc facute
este acela de modifica stringul de conectare din fisierul .config.
Stringul de conectare poate fi modificat si in mod programabil.
Clasa EntityConnection
In codul urmator, numele stringului de conexiune din fisierul .config este transferat ca un
parametru in ctor EntityConnection. Conexiunea in acest caz va fi creata din detaliile
furnizate in stringul de conexiune:
Putem selecta un string de conexiune particular din fisierul .config cand instantiem un
ObjectContext astfel:
Metadata si parametrii furnizorului spatiului de nume (furnizor ADO.NET EF) nu sunt afisate ca
proprietati ale clasei EntityConnection, si acestia vor fi accesati in momentul executiei unei
cereri cand EntityClient are nevoie sa citeasca EDM (Entity Data Model) si atunci se
determina furnizorul bazei de date (ex. Data.Sql.SqlClient) caruia ii va fi transferata cererea
pentru a o procesa.
Daca dorim sa citim complet stringul de conexiune din fisierul de configurare, putem folosi:
metode din System.Configuration.ConfigurationManager
si clasa EntityConnectionStringBuilder.
Clasa EntityConnectionStringBuilder
Observatie
Aaugati referinta la System.Configuration pentru a putea folosi
ConfigurationManager.
Exemplu
1. Memoram locatia fisierelor cu metadata (.csdl, .msl, .ssdl) in fisierul de resurse.
2. Dorim ca EntityConnectionString sa puncteze la aceasta locatie.
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 4/16
C:\EFModels\Model.csdl|C:\EFModels\Model.ssdl|C:\EFModels\Model.msl
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 5/16
Constructie EntityConnection
Name Description
Name Description
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 6/16
Observatie
Conexiunea nu e inchisa pana cand nu au fost “cititite” toate rezultatele. Metoda Load foloseste
aceeasi conexiune.
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 7/16
// executie cerere
var conList = cons.ToList();
// definitie cerere
var allCustomers = from con in context.Contacts.OfType<Customer>()
select con;
// executie cerere
var allcustList = allCustomers.ToList();
}
Conexiune explicita
Pentru a schimba comportarea implicita (cazul de mai sus) putem deschide conexiune la bd
programabil.
// definitie cerere
var cons = from con in context.Contacts where
con.FirstName == "Jose"
select con;
// executie cerere
var conList = cons.ToList();
// definitie cerere
var allCustomers = from con in context.Contacts.OfType<Customer>()
select con;
// executie cerere
var allcustList = allCustomers.ToList();
// inchidere conexiune
context.Connection.Close();
}
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 8/16
Eliberarea unui obiect ObjectContext are ca efect eliberarea conexiunii la baza de date.
ObjectContext poate fi eliberat in mod explicit sau preluat de garbage collector. In ultimul
caz conexiunea va fi eliberata in mod nedeterminist cu efecte colaterale asupra executiei codului
– in unele cazuri traducandu-se prin terminarea cu o exceptie a aplicatiei.
Observatie
Cand folosim LINQ to Entities sau ObjectContext, conexiunea va fi eliberata.
Daca am creat conexiunea in mod explicit va trebui sa eliberam EntityConnection (dispose) sau
sa asteptam ca garbage collector sa elibereze resursa.
In termeni de resurse deschiderea unei conexiuni este o operatie costisitoare ca timp de aceea se
foloseste acest mecanism de retinere in memorie a obiectelor create si de reutilizare a acestora
atunci cand e nevoie.
Connection pooling este controlat de furnizorul de ADO.NET, deci va trebui sa citim cu atentie
documentatia pentru a vedea daca este implementat un asemenea mecanism.
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 9/16
Ce este o tranzactie?
Commit.
Rollback.
Trebuie avut in vedere si faptul ca putem executa operatii in cadrul unei tranzactii, operatii ce
lucreaza cu mai multe baze de date si/sau Message Queue (MSMQ). Daca una din aceste operatii
esueaza trebuie sa se faca rollback pe toate operatiile din toate bazele de date. Pentru a realiza
acest lucru exista o componenta in System.Transaction numita Windows Distributed
Transaction Coordinator (DTC) ce supervizeaza actiunile ce sunt mult mai complexe decat
DbTransaction.
System.Transaction poate decide daca e nevoie de DTC sau DbTransaction – adica o tranzactie
individuala.
Tranzactii implicite in EF
Scenariu
Consideram tabelele Contact si Address dintr-o baza de date. Logica este ca nu poate exista o
adresa fara a exista un Contact, si nu e folosit “delete” in cascada, adica daca stergem o
inregistrare din Contact sa se stearga automat toate inregistrarile din Address ce corespund acelui
Contact.
Stergerea unei inregistrari din Contact pentru care exista inregistrari in Address va genera o
eroare.
Vom scrie o secventa de cod pentru a vedea o tranzactie in actiune.
O tranzactie implicita ce va executa roll back. In exemplul de mai jos se executa doua comenzi.
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 10/16
Observatie
Trebuiesc tratate exceptiile cand se executa SaveChanges.
Ce se intampla cu tranzactia?
ObjectContext.SaveChanges(false)
Observatie
Daca folosim LINQ to Entities si dorim sa folosim avantajele date de ObjectContext, trebuie sa
facem cast al cererii din LINQ to Entities la ObjectQuery.
Observatie
Trebuie adaugata referinta la System.Transactions.
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 11/16
context.AddToContacts(cust);
// In acest moment obiectul “cust” este in baza de date?
altcontext.SaveChanges();
}
tran.Complete();
context.AcceptAllChanges();
}
catch
{
//throw or handle database of Entity Framework exceptions
throw;
}
}
}
Analiza codului. Cate tranzactii sunt? Analizati si codul de mai jos si reveniti asupra
raspunsului.
Un exemplu din MSDN in care se observa mai clar ce inseamna TransactionScope si DTC.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
try
{
// se creaza TransactionScope pt a executa comenzile,
// garantand astfel ca cele comenzi vor fi ambele Commit sau Rollback.
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 12/16
connection1.Open();
// cod ...
// daca executia a ajuns aici inseamna ca
// command1 s-a executat cu succes.
connection2.Open();
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2,
connection2);
returnValue = command2.ExecuteNonQuery();
// cod ..
}
}
}
scope.Complete();
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException
Message: {0}", ex.Message);
}
catch (ApplicationException ex)
{
writer.WriteLine("ApplicationException Message: {0}", ex.Message);
}
Console.WriteLine(writer.ToString());
return returnValue;
}
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 13/16
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 14/16
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 15/16
Multithreading
Observatie
(MSDN docs): "ObjectContext only supports Single-Threaded scenarios."
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using BAGA;
internal static class Module2
{
t = new Thread(occ.SaveChanges);
t.Start();
}
Ioan Asiminoaei
Entity Framework 27.02.2012 Pag. 16/16
Ioan Asiminoaei