mboost-dp1

C# - Mærkværdig exception


Gå til bund
Gravatar #1 - klh
28. jan. 2008 20:55
Hej,

Jeg er i gang med en mindre C#-applikation (skoleprojekt), som skal hente data fra en Access-database og vise nogle opskrifter. Til dette har jeg skrevet nogle klasser til at hente fra databasen. Dog får jeg problemer i den ene klasse jeg har skrevet - med noget kode, der er magen til noget der virker i en anden klasse. Klassen kan ses herunder:

private string DbPlacering = Application.StartupPath + "\\App_Data\\Opskrifter.mdb";
public string LavOpskrift(int personer, string opskrift)
{
// Databaseforbindelsen oprettes
OleDbConnection aaConnection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + DbPlacering);

// Opret array til opskrift
string[] Enheder = new string[16];
string[] Antal = new string[16];
string[] Ingredienser = new string[16];
string[] Fremgangsmåde = new string[1];

string returnString = null;

try
{
for (int i = 0; i <= 15; i++)
{
// Opretter kommandoobjekt og gemmer SQL-forespørgslen
OleDbCommand aaCommand = new OleDbCommand("SELECT EnhedID" + Convert.ToString(i) + ",Antal" + Convert.ToString(i) + ",IngrediensID" + Convert.ToString(i) + ", FremgangsmådeID FROM Opskrifter WHERE Navn = " + opskrift, aaConnection);

// Datalæserobjektet oprettes og sættes til at være tomt.
OleDbDataReader aaReader = null;

// Åbn dataforbindelse
aaConnection.Open();

// Opret datalæseren
aaReader = aaCommand.ExecuteReader();

if (aaReader.GetInt32(0) != 0)
{
// Opretter kommandoobjekt og gemmer SQL-forespørgslen
OleDbCommand bCommand = new OleDbCommand("SELECT Enhed FROM Enheder WHERE ID = " + Convert.ToString(aaReader.GetInt32(0)), aaConnection);

// Datalæserobjektet oprettes og sættes til at være tomt.
OleDbDataReader bReader = null;

// Opret datalæseren
bReader = bCommand.ExecuteReader();

Enheder[i] = bReader.GetString(0);
}

if (aaReader.GetInt32(1) != 0)
{
int j = aaReader.GetInt32(1) * personer;
Antal[i] = Convert.ToString(j);
}

if (aaReader.GetInt32(2) != 0)
{
// Opretter kommandoobjekt og gemmer SQL-forespørgslen
OleDbCommand cCommand = new OleDbCommand("SELECT Råvare FROM Råvarer WHERE ID = " + Convert.ToString(aaReader.GetInt32(2)), aaConnection);

// Datalæserobjektet oprettes og sættes til at være tomt.
OleDbDataReader cReader = null;

// Opret datalæseren
cReader = cCommand.ExecuteReader();

Ingredienser[i] = cReader.GetString(0);
}

if (aaReader.GetInt32(3) != 0)
{
// Opretter kommandoobjekt og gemmer SQL-forespørgslen
OleDbCommand dCommand = new OleDbCommand("SELECT Fremgangsmåde FROM Fremgangsmåder WHERE ID = " + Convert.ToString(aaReader.GetInt32(3)), aaConnection);

// Datalæserobjektet oprettes og sættes til at være tomt.
OleDbDataReader dReader = null;

// Opret datalæseren
dReader = dCommand.ExecuteReader();

Fremgangsmåde[0] = dReader.GetString(0);
}
}
}
catch (OleDbException e)
{
//Noget MessageBox som viser fejlen fra e
MessageBox.Show(e.Errors[0].Message, "Der er opstået en fejl", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
finally
{
aReader.Close();
bReader.Close();
cReader.Close();
dReader.Close();
}

returnString = opskrift + Environment.NewLine + Environment.NewLine;

for (int i = 0; i <= 15; i++)
{
if (Enheder[i] != null)
{
returnString = returnString + Antal[i] + " " + Enheder[i] + " " + Ingredienser[i] + Environment.NewLine;
}
}

returnString = Environment.NewLine + returnString + Fremgangsmåde;

return returnString;
}
}
}


Jeg får fejlen i linjen

                    // Opret datalæseren
aaReader = aaCommand.ExecuteReader();


Og den giver følgende fejl: "Der er ikke angivet nogen værdi for en eller flere krævede parametre."

Hvad kan det skyldes? Som jeg ser det, burde koden være korrekt.

På forhånd tak for hjælpen!
Gravatar #2 - zin
29. jan. 2008 10:40
Undlad "= null;" delen af initialiseringen af aaReader, så det bliver til:

// Datalæserobjektet oprettes og sættes (implicit) til at være tomt.
OleDbDataReader aaReader;

Jeg er dog ikke sikker på, om dette hjælper. Ellers vil jeg påpege at dette er verdens længste try og for-løkke jeg har set - det bør kunne gøres bedre, for performance skyld..
Gravatar #3 - Saxov
29. jan. 2008 10:57
#1, ikke at det er fejlen, men du kan overveje at bruge @ når du laver path-stier (o.l. hvor stringen ikke skal parses før brug).

På den måde bliver
private string DbPlacering = Application.StartupPath + "\\App_Data\\Opskrifter.mdb";

til
private string DbPlacering = Application.StartupPath + @"\App_Data\Opskrifter.mdb";



Men hvad er i-counteren få når du får fejlen.. ? er det allerede ved 0 ?
Og indeholder din database godt nok EnhedID0, EnhedID1, ... EnhedID15, Antal0, Antal1, ..., Antal15, osv. ?
Gravatar #4 - Pally
29. jan. 2008 12:02
Du opbygger dit SQL som en streng hvor du selv indsætter værdier i fx din WHERE-del. Det er simpelthen noget hø (læs: skod-kode).

Brug SQL-parametre!

I tabellen Opskrifter er feltet Navn med garanti en streng; ergo skal den rå sql være: ... Navn = 'en værdi' ... Bemærk apostrofferne! Den slags (og meget andet) havde du undgået ved at bruge SQL-parametre.
Gravatar #5 - Cyrack
29. jan. 2008 12:12
@Pally: Yep han burde bruge paramtere.

@klh:
Nogen chance for at du kan stykke et databasediagram sammen? Umiddelbart virker dine tabeller temmeligt FUBAR (hvis jeg forstår din kode korrekt), så måske er problemet ikke så meget din exception, men mere hele din måde at løse opgaven på.
Generelt bør en meget voldsom advarselslampe begynde at lyse når man har KolonneNavn1, KolonneNavn2, KolonneNavn3 osv.

Ud over det, så giver dine variabelnavne ikke mange hints om hvad man kan forvente af dem. aaReader er...? Eller dReader fortæller dig hvad om to uger? Brug logiske navne!
Fx. vil et navn som opskriftReader sammen med opskriftCmd give mere mening, da de nu logisk er grupperet under opskrift-navnet, og man kan let gennemskue at de har en tilknytning.
Gravatar #6 - klh
29. jan. 2008 17:37
#2 - ZiN
Det løser ikke problemet, har jeg prøvet uden held. Ja, jeg ved godt det er en umådeligt lang try og for løkke, men jeg har ikke lige haft tid til at sætte mig og prøve at gribe det an på en anden måde.

#3 - Saxov
Det vil jeg gøre - burde jeg have tænkt på, istedet for escapes. Og ja, det er allerede ved første gennemkørsel den fejler. Min database indeholder alle de felter, og det irriterer mig så grusomt at min lærer insisterede på, at det skulle bygges sådan op i stedet for med ordentlige relationer.

#4 - Pally
Det er en string, ja. Dog løser ' ikke problemet. Jeg vil kigge på brug af SQL-parametre, hvis jeg får tid inden programmet skal afleveres. Kan godt se pointen i at bruge sådanne :)
- Og ja, det er noget skod-kode.

#5 - Cyrack
Der var en meget voldsom advarselslampe allerede da jeg fik stillet opgaven, og fik at vide af min lærer, at jeg ikke måtte løse opgaven sådan, men at det skulle være et statisk antal.

Og ja, jeg bør give mine variabler mere logiske navne. Må jeg se at få gjort.

Men som sagt, forstår jeg slet ikke at der kommer en fejl under eksekvering, da en anden klasse med kode til datahentning der ligner fuldstændig, ikke fejler :s
Gravatar #7 - Mort
29. jan. 2008 22:12
"...Opskrifter WHERE Navn = " + opskrift...


Så vidt jeg kan se så mangler du 'apostroffer' rundt om din opskrift, således:


// Opretter kommandoobjekt og gemmer SQL-forespørgslen
OleDbCommand aaCommand = new OleDbCommand("SELECT EnhedID" + Convert.ToString(i) + ",Antal" + Convert.ToString(i) + ",IngrediensID" + Convert.ToString(i) + ", FremgangsmådeID FROM Opskrifter WHERE Navn = '" + opskrift + "'", aaConnection);
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login