Problem med MSSQL i C#/Visual Studio

Permalänk
Medlem

Problem med MSSQL i C#/Visual Studio

Tjena, jag har skrivit ett program i C# där jag ska spara data i en databas. Databas filen ligger i projektmappen, men när jag skriver data till den sparas den i en databas fil som ligger i debug mappen. Detta gör så jag kan inte kolla vad för data som är sparad i databasen vilket leder till att jag inte vet om det sparas eller inte. Jag har en temporär lösning genom att skapa ett nytt projekt, importera rätt db fil som new data source och kolla dbTables values. Finns det någon smidigare lösning på detta?

Nästa fråga handlar om att summera data från databasen. När jag summerar data för att räkna ut lön fungerar det fint, här är den koden:

int month = comboBox1.SelectedIndex + 1;

connection = new SqlConnection(connectionString);
connection.Open();
string query = "SELECT SUM (timeSpent) FROM timeReport WHERE month = @month AND username = @user";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.Add(new SqlParameter("@month", month));
command.Parameters.Add(new SqlParameter("@user", Login.currentUser));

SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
double minutesWorked = (double)reader.GetInt32(0);
double hoursWorked = minutesWorked / 60;
hoursWorked = Math.Round(hoursWorked, 2);
double salary = hoursWorked * 100 * 0.66;
salary = Math.Round(salary, 2);
MessageBox.Show("You've worked " + hoursWorked + " hours during " + months[month - 1] + " and your salary is " + salary.ToString() + " kr", "Your salary from " + months[month - 1]);

}
}
finally
{
reader.Close();
}

den funkar fint och jag får ut rätt data, men när jag ska summera data för att räkna ut tiden spenderat per ämne har jag denna kod, enligt mig borde den fungera eftersom den är gjord på typ samma sätt som koden ovan, men jag får error om att den hämtar values som är NULL och allt går sönder. Det är den här koden:

int math = 0;
int english = 0;
int programming = 0;
string[] subjects = new string[] { "Math", "English", "Programming" };

connection = new SqlConnection(connectionString);
connection.Open();
string query = "SELECT SUM (timeSpent) FROM timeReport WHERE week = @week AND username = @user AND subject = @subject";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.Add(new SqlParameter("@week", Form1.selectedWeek));
command.Parameters.Add(new SqlParameter("@user", Login.currentUser));
command.Parameters.Add(new SqlParameter("@subject", subjects[0]));

SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
math = reader.GetInt32(0);
}
}
finally
{
reader.Close();
}

Den kraschar på "math = reader.GetInt32(0);". Om nån skulle kunna förklara vad som är fel skulle det uppskattas djupt. I min db har jag en rad där alla kolumner har värdet null, men jag vet inte hur man får bort den, och jag vet inte om det är den som förstör eftersom koden för att räkna ut lön fungerar och då finns ju den raden där.

Permalänk
Medlem
Skrivet av Simon^L:

Tjena, jag har skrivit ett program i C# där jag ska spara data i en databas. Databas filen ligger i projektmappen, men när jag skriver data till den sparas den i en databas fil som ligger i debug mappen. Detta gör så jag kan inte kolla vad för data som är sparad i databasen vilket leder till att jag inte vet om det sparas eller inte. Jag har en temporär lösning genom att skapa ett nytt projekt, importera rätt db fil som new data source och kolla dbTables values. Finns det någon smidigare lösning på detta?

Du kan öppna databasfilen direkt i Visual Studio för att köra frågor mot den för att på så vis ta reda på informationen i databasen.
https://msdn.microsoft.com/en-us/library/ms239722.aspx

Skrivet av Simon^L:

Den kraschar på "math = reader.GetInt32(0);". Om nån skulle kunna förklara vad som är fel skulle det uppskattas djupt. I min db har jag en rad där alla kolumner har värdet null, men jag vet inte hur man får bort den, och jag vet inte om det är den som förstör eftersom koden för att räkna ut lön fungerar och då finns ju den raden där.

På vilket sätt krashar det?
Om det är så att det är nullvärden så kan du kontrollera det först. Din kod kräver att det är en int som kommer från GetValue vilket borde vara omöjligt då det ska vara en object.

Förslagsvis kan det hanteras på detta vis:

var value = reader.GetValue(0); if (val.GetType() == typeof(DBNull)) //Alternativt använda reader.IsDBNull(0) { //Värdet är null } else { math = (int)value; }

Det är ganska mycket kod men det blir så ibland. Du kan göra egna metoder för det där så blir det lättläst och trevligt. Exempelvis: reader.getSafeInt(0, -1) där första inten är ordinal och andra inten är defaultvärde om det är ett nullvärde.

Visa signatur

ηλί, ηλί, λαμά σαβαχθανί!?

Permalänk
Medlem

Du otroligt mycket onödig kod om du bara ska ta ut ett värde från en fråga, Dvs en scalär fråga.

SqlDataReader reader = command.ExecuteReader(); try { while (reader.Read()) { math = reader.GetInt32(0); } } finally { reader.Close(); }

Kan du summera till enbart detta + typ av felhantering du nu behöver.

math = Convert.ToInt32(command.ExecuteScalar());

Visa signatur

Speldator: Ryzen 7800X3D, 64GB DDR5, RTX 3070
Server: i7-8700k, 32GB DDR4, RTX2080
Steam deck + de fiesta konsoller.

Permalänk
Medlem
Skrivet av Leedow:

Du kan öppna databasfilen direkt i Visual Studio för att köra frågor mot den för att på så vis ta reda på informationen i databasen.
https://msdn.microsoft.com/en-us/library/ms239722.aspx

På vilket sätt krashar det?
Om det är så att det är nullvärden så kan du kontrollera det först. Din kod kräver att det är en int som kommer från GetValue vilket borde vara omöjligt då det ska vara en object.

Förslagsvis kan det hanteras på detta vis:

var value = reader.GetValue(0); if (val.GetType() == typeof(DBNull)) //Alternativt använda reader.IsDBNull(0) { //Värdet är null } else { math = (int)value; }

Det är ganska mycket kod men det blir så ibland. Du kan göra egna metoder för det där så blir det lättläst och trevligt. Exempelvis: reader.getSafeInt(0, -1) där första inten är ordinal och andra inten är defaultvärde om det är ett nullvärde.

Okej tack så mycket! Ska kolla in detta om se om jag tar mig nån vart.

Skrivet av MugiMugi:

Du otroligt mycket onödig kod om du bara ska ta ut ett värde från en fråga, Dvs en scalär fråga.

SqlDataReader reader = command.ExecuteReader(); try { while (reader.Read()) { math = reader.GetInt32(0); } } finally { reader.Close(); }

Kan du summera till enbart detta + typ av felhantering du nu behöver.

math = Convert.ToInt32(command.ExecuteScalar());

Nu är det här första gången jag håller på med SQL så är rejält grön på området men ger inte ExecuteScalar bara det första värdet från rätt kolumn i den första raden i tabellen? Jag vill ju nämligen ha värdet från samma kolumn från varje rad i tabellen. Eller missförstår jag bara?

Permalänk
Medlem
Skrivet av Simon^L:

Okej tack så mycket! Ska kolla in detta om se om jag tar mig nån vart.

Nu är det här första gången jag håller på med SQL så är rejält grön på området men ger inte ExecuteScalar bara det första värdet från rätt kolumn i den första raden i tabellen? Jag vill ju nämligen ha värdet från samma kolumn från varje rad i tabellen. Eller missförstår jag bara?

Du förstår korrekt saken är den att när du använder SUM() eller COUNT() o.s.v som är en Aggregate funktion så summerar den resultatet som du nu har skrivit i dina frågor, vist går det att få fler resultat om du använder dig av grupperingar o.s.v. men i dina fall får du inte det.

SELECT SUM (timeSpent) FROM timeReport WHERE month = @month AND username = @user SELECT SUM (timeSpent) FROM timeReport WHERE week = @week AND username = @user AND subject = @subject

Dessa resulterar bara i en rad med ett svar så länge du träffar något, annars får du svaret NULL.
Det sagt, du kan lösa så du alltid får 0 i de fallen med t.ex, vilket också löser ditt andra problem.

SELECT ISNULL(SUM (timeSpent), 0) FROM timeReport WHERE month = @month AND username = @user

Visa signatur

Speldator: Ryzen 7800X3D, 64GB DDR5, RTX 3070
Server: i7-8700k, 32GB DDR4, RTX2080
Steam deck + de fiesta konsoller.

Permalänk
Medlem

För att datan ska finnas kvar i databasen vid varje debug körning måste du välja i egenskaper att den endast ska kopiera filen om det är ny. Annars kopieras databasfilen till debug mappen vid varje körning och skriver över dina ändringar.

Välj att visa alla filer i visual studio, klicka på databasfilen, gå till egenskaper och ändra hur den ska kopieras så den inte skrivs över vid varje debug tillfälle.

Permalänk
Medlem

@furbel: Jo jag hittade tillslut denna inställning själv, men tack för att du tog din tid att hjälpa!:)