Databashantering
147 svar · 8 229 visningar · startad av kristoffer
Ja, med tanke på att det finns providers för Sql, OleDb och Odbc så tycker jag det är en god idé om man någon gång skulle ändra databas.
Dessutom blir det mindre kod och felhantering sker på ett enda ställe. Nackdelen är, som du redan nämnt i den andra tråden, att det kan vara lite krångligt att göra någonting annat än vad ursprungskoden är gjord för.
Än så länge har jag lite problem med den klassen jag försöker bygga...
I databaskursen som jag läser nu lär man ut att databaskommunikationen skall vara i en klass
Det är inte viktigt att databaslogik koncentreras till just en klass.
Det viktiga är att man separerar databaslogik från presentationslagret, presentationslagret skall aldrig behöva känna till hur underliggande logik är implementerad, annars får man beroenden som förhindrar ändringar, t.ex som Pace skriver, byte av databas etc.
Databaslogiken skall helst inte returnera t.ex ett ResultSet ut mot presentationslagret heller för den delen som det snackas om i J2EE-tråden, där har man automatiskt ett beroende till JDBC respektive ADO.Net, i ett senare skede kanske man har något helt annat underliggande datalagringssystem som t.ex en objektdatabas eller liknande. Databaslogiken skall hellre returnera dataobjekt med getters och setters för datat så att övriga lager endast behöver känna till dessa klasser eller deras gränssnitt.
Så, att separera databaslogik och presentation är inte bara en bra idé, det är generalfel att inte göra det :). Inget databasprat i ASP.Net-sidorna med andra ord :).
nån som har en liten skiss på hur en sådan klass skulle kunna se ut? Problemet jag ställs inför nu är att jag inte vet vilken databas jag kommer att utveckla mot (hmm jag kör mot mssql nu men vet inte om webbhotellet kommer ha stöd för det.) Bli då jobbigt att ändra i koden och byta ut allt mot mysql om det nu blir det....
Vilken approach tycker ni är bäst för en databasklass?
Jag har skapat en generell databasklass med en metod för GetData() och SaveData samt ett antal properties.
Sedan ärver jag in denna i de klasser som vill komma åt databasen. Typ en databasklass för customer som ärver in min GenericDb klass med de metoder och egenskaper som finns där.
Åsikter?
Jag kör så här:
1. Grund databaslagret som har alla funktion jag kan behöva RunProcedure, GetDataSet, GetDataReader.
2. Databas lagret ärver funktioner från (1). Och har funktion som t.ex Retrive som då använder (1).GetDataReader() för att t.ex retunera data till business lagret,
3. Business, här har jag t.ex en klass för användarna vid namn User som innehåller alla user varibler som t.ex Id, namn, email. Denna klass kan vara tom eller fyllas det anges vid new User(id) eller för tom new User().
4. Presentation, om jag ska visa användar information skapar jag bara en instans av User och anger då user id och får därmed all info om den användaren.
Hoppas jag förklarat på ett bra sätt :P
Hittade just
http://www.dotnetjunkies.com/tutorials.aspx?tutorialid=516
verkar vara en rätt bra artikel som är hyffsat relaterad till vad vi pratar om ;)
renholm -> ung så som jag hade tänkt mig. Dock kanske man skulle ha en genrell klass för att läsa data och en för att skriva data. Då skulle man kunna köra med Transaktionsattribut = Requires för skrivklassen och få med automatisk transaktionshantering.
Kan det vara något?
Lite mer om klassbyggandet:
http://www.webforum.nu/showthread.php?s=&threadid=50311
http://www.webforum.nu/showthread.php?s=&threadid=58190
Då jag funderade över detta frågade jag renholm om jag fick se vad han menade, till svar fick jag då en *.cs som jag anpassade till OleDb istället den ser ut så här nu:
[red]
using System;
using System.Data;
using System.Data.OleDb;
namespace Icaaq.Data
{
public abstract class OleDbData
{
protected OleDbConnection Connection;
public OleDbData(string ConnectionString)
{
Connection = new OleDbConnection(ConnectionString);
}
private OleDbCommand BuildCommand(string SqlStatement)
{
OleDbCommand Command = new OleDbCommand(SqlStatement, Connection);
Command.CommandType = CommandType.Text;
return Command;
}
protected void RunNonQuery(string SqlStatement)
{
try
{
Connection.Open();
OleDbCommand Command = BuildCommand(SqlStatement);
Command.ExecuteNonQuery();
}
finally
{
Connection.Close();
}
}
protected DataSet RetriveDataSet(string SqlStatement)
{
try
{
DataSet dataset = new DataSet();
Connection.Open();
OleDbDataAdapter Adapter = new OleDbDataAdapter();
Adapter.SelectCommand = BuildCommand(SqlStatement);
Adapter.Fill(dataset);
return dataset;
}
finally
{
Connection.Close();
}
}
protected OleDbDataReader RetriveDataReader(string SqlStatement)
{
OleDbDataReader DataReader;
Connection.Open();
OleDbCommand Command = BuildCommand(SqlStatement);
DataReader = Command.ExecuteReader(CommandBehavior.CloseConnection);
return DataReader;
}
}
}
[/red]
Frågan är nu hur jag får hämtar ett DataSet tex?
Jag har
[red]
using Icaaq.Data
[/red]
mvh icaaq
Fick ett pm om detta som jag han svara på innan jag såg detta, men svarar även här för det är säkert fler som vill veta.
Ett exempel:
using System;
using System.Data;
using System.Data.SqlClient;
namespace Icaaq.Data
{
public class Test : Icaaq.Data.OleDbData
{
public Test(string newConnectionString) : base(newConnectionString)
{ }
public DataSet Retrive()
{
SqlParameter[] parameters =
{ };
using(DataSet dataSet = RetriveDataSet("sp_getData", parameters))
{
return dataSet;
}
}
}
}
Sedan för att använda detta:
Test data = new Test(/* connstring */);
data.Retrive();
Ursäkta, men nu fattar jag nada :OO
Om man tar koden jag hade i mitt föregående inlägg, hur ska jag använda classen test med den?
Är det typ så här
[red]
using System;
using System.Data;
using System.Data.OleDb;
namespace Icaaq.Data
{
public abstract class OleDbData
{
protected OleDbConnection Connection;
public OleDbData(string ConnectionString)
{
Connection = new OleDbConnection(ConnectionString);
}
private OleDbCommand BuildCommand(string SqlStatement)
{
OleDbCommand Command = new OleDbCommand(SqlStatement, Connection);
Command.CommandType = CommandType.Text;
return Command;
}
protected void RunNonQuery(string SqlStatement)
{
try
{
Connection.Open();
OleDbCommand Command = BuildCommand(SqlStatement);
Command.ExecuteNonQuery();
}
finally
{
Connection.Close();
}
}
protected DataSet RetriveDataSet(string SqlStatement)
{
try
{
DataSet dataset = new DataSet();
Connection.Open();
OleDbDataAdapter Adapter = new OleDbDataAdapter();
Adapter.SelectCommand = BuildCommand(SqlStatement);
Adapter.Fill(dataset);
return dataset;
}
finally
{
Connection.Close();
}
}
protected OleDbDataReader RetriveDataReader(string SqlStatement)
{
OleDbDataReader DataReader;
Connection.Open();
OleDbCommand Command = BuildCommand(SqlStatement);
DataReader = Command.ExecuteReader(CommandBehavior.CloseConnection);
return DataReader;
}
}
public class Test : Icaaq.Data.OleDbData
{
public Test(string newConnectionString) : base(newConnectionString)
{ }
public DataSet Retrive()
{
SqlParameter[] parameters =
{ };
using(DataSet dataSet = RetriveDataSet("sp_getData", parameters))
{
return dataSet;
}
}
}
}[/red]
med viss modifikation på SqlParameters och dylikt....
mvh icaaq
Ja, så är det hela tänkt.
Men vad är fördelen med att använda ärvningen på detta vis?
mvh icaaq
[redigerat]Och vad skulle ett annat namn för test vara för bra namn[/redigerat]
Då jag sovit på saken har jag nog kommit på att detta är väldigt skalbart då man använder Icaaq.Data.OleDbData till alla sina sajter som använder OleDb. men man bygger upp "test" för olika sidor. Är jag rätt ute och tänker då ?
mvh icaaq
Nu är jag inte direkt vass på c# så jag är inte riktigt med på renholms förslag men jag tror jag fattar vad det går ut på.
icaaq -> du bygger snarare upp "test" för varje klass du har som skall accessa databasen. Säg t.ex. att du har en users-klass då skapar du en dbUsers klass som ärver in db-klassen.
Attans... Jag som trodde att jag hade fattat detta nu :OO
Jag får nog sova lite till för att få grepp på detta........
mvh icaaq
Tänk så här:
Du har en aspx-sida som vill läsa upp en user från databasen.
Din aspx-sida anropar user-klassen som du byggt tidigare. Denna user-klass anropar en dbUser klass som har hand om alla databasanrop som rör User-data.
dbUser ärver sina metoder och egenskaper från OledbData.
Så för att hämta user-data så anropar du dbUser.Retrieve efter det du har satt sqlstatment etc. Så i detta exempel motsvarar din "test" klass dbUser.
Lösningen är på så sätt 4-skiktad.
Presentationsskikt (aspx) -> Business Logic skikt (User)-> Business Object Dataaccessc skikt (dbUser som ärver från oledbdata) -> Databas
Blev det något tydligare nu?
/me *sover*..........*vaknar*.........*läser*.........*somnar om igen*
Skämt ossidå om om jag ska försöka mig på att förklara detta så som jag har fattat det......
- Databas (det är väll inte så mycket att prata om)
- Business Object Dataaccess Skikt (class som pratar med databasen)
- Business Logic Skikt (class som ärver BODS funktioner, men ,man bygger upp denna så att den passar PS, dvs att man har publica metoder för att hämta och föra in data.)
- Presentation Skikt (aspx sida där man använder sig av BLS för att lätt kunna hämta eller föra in data)
Är detta rätt på ett annat sätt än vad du förklarade det.....
mvh icaaq