260 likes | 396 Views
N-lags Design. Definition Motivation. object. object. object. business. N-lags Design. Datadrevne applikationer har typisk N > 1 lag Præsentations- , Forretnings- , Datatilgangs- , og Data-laget. Presentation. Business. Data Access. Data Store. data access. DB.
E N D
N-lags Design • Definition • Motivation
object object object business N-lags Design • Datadrevne applikationer har typisk N > 1 lag • Præsentations-, Forretnings-, Datatilgangs-, og Data-laget Presentation Business Data Access Data Store dataaccess DB “Not to manage or store data, but to provide an interface between business logic & data store.” [Rocky Lhotka] "To support all security, business rules, and data processing (validation, manipulation & storage) for our particular business." [Rocky Lhotka]
object object object business Motivation • Hvorfor N-lags design? Mange gode grunde fx: • objektorienteret løsning • opdeling i logiske enheder • softwareudvikling i teams • genbrug af forretningslogik og data på tværs af præsentationer dataaccess Desktop App DB Web App
Eksempel • Lad os redesigne StudentInfo applikationen … • Forretningslaget omhandler de studerende • Datatilgangslaget omhandler databasen Students
Præsentationslaget • Præsentationslaget kommunikeret kun med forretningslaget: protected void Page_Load(object sender, EventArgs e) { object obj = this.Context.Items["ID"]; // Kom brugeren direkte? if (obj == null) this.Response.Redirect("Login.aspx", true /*afslut nu*/); // Hvis alt er ok ... BusinessTier.Students students; BusinessTier.Student s; id = System.Convert.ToInt64(obj); students = new BusinessTier.Students(); s = students.GetStudent(id); this.tbxName.Text = string.Format("{0}, {1}", s.LastName, s.FirstName); this.tbxEmail.Text = s.Email; this.tbxGPA.Text = s.GPA.ToString("0.00"); }
Forretningslaget • Erklærer en Student-klasse til at repræsentere en student • Erklærer en Students-klasse til at repræsentere en samling af studerende • kommunikerer med datatilgangslaget vha. SQL namespace BusinessTier { public class Students { private DataAccessTier.DataAccess data; public Students() { ... } public Student GetStudent(long id) { string sql = string.Format("Select * From Students Where SID={0};", id); DataSet ds = data.Select(sql); return new Student(...); } namespace BusinessTier { public class Student { . . . } }
Datatilgangslaget • En generisk og genbrugbar klasse til eksekvering af SQL • stiller metoder til rådighed til Select- og Action- forespørgsler namespace DataAccessTier { public class DataAccess { . . . public System.Data.DataSet Select(string sql) { // Udfører en sql-sætning og returnerer et DataSet } public int Action(string sql) { // Udfører en sql-sætning og returnerer antallet af berørte poster } . . . } }
N-lags Design • Der findes rigtig mange forskellinge måder at designe N-lags applikationer på • anvendelse af SQL til at forbinde lagene med er fleksibelt men risikofyldt • mange foretrækker at anvende "stored procedures" ved datatilgang • og så videre …
Assemblies • Logisk vs. fysisk design • Arbejde med assemblies
object object object business Logisk vs. fysisk design • Lagdelingen udgør det logiske design • Assemblies udgør det fysiske design dataaccess DB App.dll Data.DLL Business.DLL komponenter eller "assemblies"
Motivation • Hvorfor oprette fysisk adskilte assemblies? • assemblies kan skrives i forskellige sprog • assemblies kan deles af flere programmer • assemblies kan flyttes til andre maskiner • assemblies kan let erstattes/opdateres • .NET selv udgøres af en mængde assemblies, fx ASP.NET. App.dll Data.DLL Business.DLL DB
Eksempel • StudentInfo webapplikationen består af tre assemblies …
Oprettelse af Assemblies • Ethvert projekt i en Visual Studiosolution udgør én assembly • class library => .dll • File menu > Add > New Project … • Bemærk: • for at kunne bruge en assembly,skal der refereres til den! • Project menu > Add Reference… • brug .NET-fanen til kompileret kode • brug Project-fanen til andre projekter
Arbejde med flere projekter • Lav først en tom solution • File > New Project > Other Project Types > Visual Studio Solutions • Opret en webapplikation: • File > Add > New Web Site … • placeres i den tomme solution, som just er oprettet • Opret klassebibliotek: • File > Add > New Project > Class Library… • placeres også i den nyligt oprettede solution • Tilføj projektreferencer …
ADO.NET • Resumé af databasetilgang i .NET
Forespørgsler i VS 2005 • VS kan åbne databaser og lade dig forespørge i dem • For at teste SQL-forespøgsler, granske metadata, osv. • Tools menu > Connect to Database… • Vælg Datakilde m.v. — tryk OK • Du kan nu arbejde via Server Explorer-vinduet og Data-menuen …
DB Eksempel — Programmering med ADO.NET • Indlæs alle kunderne fra databasen • og vis dem i en ListBox … List<Customer> customers; customers = new List<Customer>(); . . // Indlæs Customers-tabellen og opret tilhørende objekter … . foreach (Customer c in customers) this.lstCustomers.Items.Add(c);
Databasetilgang - mønster • Tre trin: • opret og konfigurér objekter • forbered og udfør SQL • gennemløb data
Overblik over objekter • Datatilgang kræver flere forskellige objekter: • Connection – objekt, som repræsenterer forbindelsen • Command – objekt, som repræsenterer SQL-forespørgslen • DataAdapter – objekt, som udtrækker data fra databasen til et DataSet • DataSet – objekt, som er en beholder til tabeldata DB DataSet DataAdapter Command Connection DBengine "Table"
(1) Opret og konfigurér objekter • ADO.NET Factory klasse skjuler provider-specifikke detaljer • Eksempel: • opsætning af en Microsoft Access 2000 database ("Sales.mdb") using System.Data; using System.Data.Common; string provider; DbProviderFactory dbFactory; DbConnection dbConn; // Repræsenterer databasen DbCommand dbCmd; // Kommandoobjekt DbDataAdapter dbAdapter; // Indlæser data og gemmer i et DataSet DataSet ds; // Beholder til tabeldata provider = "System.Data.OleDb"; dbFactory = DbProviderFactories.GetFactory(provider); dbConn = dbFactory.CreateConnection(); dbCmd = dbFactory.CreateCommand(); dbAdapter = dbFactory.CreateDataAdapter(); ds = new DataSet(); dbCmd.Connection = dbConn; // Associér forbindelse og kommando dbAdapter.SelectCommand = dbCmd; // Associér adapter og kommando
(2) Forbered og udfør SQL • Opret de SQL-sætninger, som skal udføres • Åbn forbindelse til databasen, udfør SQL og luk forbindelsen igen! • forbindelses-info er også provider-specifikt • Sørg for at placere "Sales.mdb"-databasen i samme mappe som .exe-filen string sql, connection; sql = "Select * From Customers Order By LastName Asc, FirstName Asc;"; connection = string.Format("Provider={0};Data Source={1}", "Microsoft.Jet.OLEDB.4.0", "|DataDirectory|Sales.mdb"); dbConn.ConnectionString = connection; // Angiv database dbCmd.CommandText = sql; // Angiv SQL-forespørgsel dbConn.Open(); // Åbn, udfør, luk! dbAdapter.Fill(ds); dbConn.Close();
(3) Gennemløb data • Kopi af data findes nu i DataSet • Gennemløb data • Eksempel: • Lav kunde-objekter og vis dem i en ListBox this.customers = new List<Customer>(); foreach (DataRow row in ds.Tables["Table"].Rows) { Customer c; c = new Customer( System.Convert.ToInt64(row["CID"]), row["FirstName"].ToString(), row["LastName"].ToString(), System.Convert.ToDecimal(row["CreditLimit"]), System.Convert.ToDecimal(row["AcctBalance"]) ); this.customers.Add(c); } foreach (Customer c in customers) this.lstCustomers.Items.Add(c);
God programmeringsskik • Sørg for at lukke forbindelsen • Rapportér fejl . . dbFactory = DbProviderFactories.GetFactory(provider); try { using (dbConn = dbFactory.CreateConnection()) { dbCmd = dbFactory.CreateCommand(); dbAdapter = dbFactory.CreateDataAdapter(); . . . dbConn.Open(); dbAdapter.Fill(ds); } // Databasen lukkes automatisk } catch(Exception ex) { System.Diagnostics.Debug.WriteLine("Fejl: " + ex.Message); System.Diagnostics.Debug.WriteLine("Stack: " + ex.StackTrace); throw; }
Tilgang til andre typer databaser? • Gode nyheder — ændr provider- og connection-oplysningerne! • Eksempel: • udtræk af kunde fra Microsoft SQL Server . . provider = "System.Data.SqlClient"; . . . connection = string.Format("Server={0};Database={1};{2}", ".", // "." = lokal server, ellers ip-adresse/alias "Sales", "Integrated Security=SSPI"); // eller "uid=?;pwd=?" . .
Hvad så? • Øvelse #6
<blank> • …