SQL Server, behöver guidning!

Permalänk
Medlem
Skrivet av PapaDiouf:

Mina tables ser ut såhär just nu:
ParkingSpace

[ParkingSpaceID] INT IDENTITY (1, 1) NOT NULL, [PSpaceNumber] INT NOT NULL, [PSpaceSize] INT NOT NULL, [PSpacesRemaining] INT NOT NULL, PRIMARY KEY CLUSTERED ([ParkingSpaceID] ASC)

Vehicles

[VehicleID] INT IDENTITY (1, 1) NOT NULL, [VehicleType] NVARCHAR (10) NOT NULL, [VehicleRegNumber] NVARCHAR (10) NOT NULL, [VehicleArrivalTime] DATETIME NOT NULL, [ParkingSpaceID] INT NOT NULL, PRIMARY KEY CLUSTERED ([VehicleID] ASC), CONSTRAINT [FK_ParkingSpaceID] FOREIGN KEY ([ParkingSpaceID]) REFERENCES [dbo].[ParkingSpace] ([ParkingSpaceID])

Min stored procedure ser ut såhär:

CREATE PROCEDURE spAddVehicle @VehicleType NVARCHAR(10), @VehicleRegNumber NVARCHAR(10), @VehicleArrivalTime DATE, @PSpaceSize INT, @PSpacesRemaining INT AS BEGIN INSERT INTO Vehicles(VehicleType , VehicleRegNumber, VehicleArrivalTime) VALUES (@VehicleType, @VehicleRegNumber, GETDATE()) BEGIN DECLARE @PSpaceNumber INT SET @PSpaceNumber = (SELECT COUNT(*) FROM ParkingSpace) + 1 BEGIN INSERT INTO ParkingSpace(PSpaceNumber, PSpaceSize, PSpacesRemaining) VALUES (@PSpaceNumber, @PSpaceSize, @PSpacesRemaining) RETURN @PSpaceNumber END END END

Angående mina inserts så har jag ändrat fram och tillbaka och testat massa olika varianter, bör parkingspaceID ligga inne i parameterna?

Och min C# kod för att kalla på dessa:

using(SqlConnection dbConn = new SqlConnection(connString)) { SqlCommand cmd = new SqlCommand(sp, dbConn); cmd.CommandType = CommandType.StoredProcedure; addVehicle.VehicleType = UserInputHandler.GetVehicleType(); if (addVehicle.VehicleType == "Car") { addVehicle.VehicleRegNumber = UserInputHandler.GetVehicleRegNumberHandler(); addVehicle.VehicleRegNumber = addVehicle.VehicleRegNumber.ToUpper(); cmd.Parameters.AddWithValue("@VehicleType", addVehicle.VehicleType); cmd.Parameters.AddWithValue("@VehicleRegNumber", addVehicle.VehicleRegNumber); cmd.Parameters.AddWithValue("@VehicleArrivalTime", DateTime.Now); //SqlParameter vehicleID = new SqlParameter("@VehicleID", SqlDbType.Int); //vehicleID.Direction = ParameterDirection.Output; //cmd.Parameters.Add(vehicleID); //SqlParameter parkingSpaceID = new SqlParameter("@ParkingSpaceID", SqlDbType.Int); //parkingSpaceID.Direction = ParameterDirection.Output; //cmd.Parameters.Add(parkingSpaceID); SqlParameter pspacenumber = cmd.Parameters.Add("@PSpaceNumber", SqlDbType.Int); pspacenumber.Direction = ParameterDirection.ReturnValue; cmd.Parameters.AddWithValue("@PSpaceSize", 2); cmd.Parameters.AddWithValue("@PSpacesRemaining", 0); try { dbConn.Open(); cmd.ExecuteNonQuery(); TextToUser.PrintVehicleAdded(); } catch (Exception msg) { TextToUser.PrintExceptionMessage(msg); } finally { dbConn.Close(); } }

Kommenterade bort några rader för att testa lite olika varianter bara

Hej!

Jag tycker att det saknas lite information om hur du tänker dig att det ska fungera med motorcyklar.

Om du har ett tomt garage och sätter in en motorcykel, så kommer den ju att hamna på plats 1. Kommer det alltid att finnas plats för två (och endast två) motorcyklar eller ska det finnas flera varianter? Jag tänker att detta är det som är din PSpaceSize?

Just nu finns den inte definierad någonstans?

Oavsett varianter så behöver du ju ha en IF-sats som tar hänsyn till detta:
Hitta nästa parkeringsplats i garaget där det finns plats för en till motorcykel.

För bilar så är ju frågan redan löst, men nu behöver du justera den att fungera för motorcyklar.

Permalänk
Skrivet av MickeBoy:

Hej!

Jag tycker att det saknas lite information om hur du tänker dig att det ska fungera med motorcyklar.

Om du har ett tomt garage och sätter in en motorcykel, så kommer den ju att hamna på plats 1. Kommer det alltid att finnas plats för två (och endast två) motorcyklar eller ska det finnas flera varianter? Jag tänker att detta är det som är din PSpaceSize?

Just nu finns den inte definierad någonstans?

Oavsett varianter så behöver du ju ha en IF-sats som tar hänsyn till detta:
Hitta nästa parkeringsplats i garaget där det finns plats för en till motorcykel.

För bilar så är ju frågan redan löst, men nu behöver du justera den att fungera för motorcyklar.

Ja precis, får försöka lite med den. Men ja tanken är väl att om PSpacesRemaining = 1 så skall en motorcykel kunna läggas in där så blir remaining 0 liksom.

Sedan angående min foreign key och det felmeddelande jag får, ser du någonstans vart det kan gå fel? Har googlat som en dåre men hittar inget som fungerar, eftersom pk i mina tables är identity så ska dom ju automatiskt öka med en, dock verkar min parkingspaceId bli null när den hamnar i vehicles vilket den inte får. Dock får parkingspace rätt parkingspaceID när jag lägger till fordon? hmm

Permalänk
Medlem
Skrivet av PapaDiouf:

Ja precis, får försöka lite med den. Men ja tanken är väl att om PSpacesRemaining = 1 så skall en motorcykel kunna läggas in där så blir remaining 0 liksom.

Sedan angående min foreign key och det felmeddelande jag får, ser du någonstans vart det kan gå fel? Har googlat som en dåre men hittar inget som fungerar, eftersom pk i mina tables är identity så ska dom ju automatiskt öka med en, dock verkar min parkingspaceId bli null när den hamnar i vehicles vilket den inte får. Dock får parkingspace rätt parkingspaceID när jag lägger till fordon? hmm

Du har definierat Vehicles som

[VehicleID] INT IDENTITY (1, 1) NOT NULL, [VehicleType] NVARCHAR (10) NOT NULL, [VehicleRegNumber] NVARCHAR (10) NOT NULL, [VehicleArrivalTime] DATETIME NOT NULL, [ParkingSpaceID] INT NOT NULL, PRIMARY KEY CLUSTERED ([VehicleID] ASC), CONSTRAINT [FK_ParkingSpaceID] FOREIGN KEY ([ParkingSpaceID]) REFERENCES [dbo].[ParkingSpace] ([ParkingSpaceID])

I denna tabell har du en kolumn som heter ParkingSpaceID som lagrar heltal. Den har också har en begränsning (constraint) att värden i den kolumnen (för varje rad) måste kunna återfinnas i [dbo].[ParkingSpace] ([ParkingSpaceID].

Så om du försöker att sätta in NULL i något anrop så är det rimligt att det inte fungerar.

Jag tänker att du skulle utöka din kod så att när du fångar det exception som kastas när detta inträffar också loggar värdet av de parametrar som du försöker anropa din lagrade procedur med. Utöka alltså TextToUser.PrintExceptionMessage så att du kan få med mer information.

Om du sedan fångar dessa värden i ett felmeddelande eller en logg så kan du använda t.ex. Management Studio för att ta upp den lagrade proceduren och köra enbart logiken i ett nytt fönster. Genom att använda PRINT så kan du skapa dig själv utskrifter till skärmen.

På detta vis borde du kunna komma fram till vad som behöver andras.

Permalänk
Skrivet av MickeBoy:

Du har definierat Vehicles som

[VehicleID] INT IDENTITY (1, 1) NOT NULL, [VehicleType] NVARCHAR (10) NOT NULL, [VehicleRegNumber] NVARCHAR (10) NOT NULL, [VehicleArrivalTime] DATETIME NOT NULL, [ParkingSpaceID] INT NOT NULL, PRIMARY KEY CLUSTERED ([VehicleID] ASC), CONSTRAINT [FK_ParkingSpaceID] FOREIGN KEY ([ParkingSpaceID]) REFERENCES [dbo].[ParkingSpace] ([ParkingSpaceID])

I denna tabell har du en kolumn som heter ParkingSpaceID som lagrar heltal. Den har också har en begränsning (constraint) att värden i den kolumnen (för varje rad) måste kunna återfinnas i [dbo].[ParkingSpace] ([ParkingSpaceID].

Så om du försöker att sätta in NULL i något anrop så är det rimligt att det inte fungerar.

Jag tänker att du skulle utöka din kod så att när du fångar det exception som kastas när detta inträffar också loggar värdet av de parametrar som du försöker anropa din lagrade procedur med. Utöka alltså TextToUser.PrintExceptionMessage så att du kan få med mer information.

Om du sedan fångar dessa värden i ett felmeddelande eller en logg så kan du använda t.ex. Management Studio för att ta upp den lagrade proceduren och köra enbart logiken i ett nytt fönster. Genom att använda PRINT så kan du skapa dig själv utskrifter till skärmen.

På detta vis borde du kunna komma fram till vad som behöver andras.

Okej, ska försöka hinna med det. Tycker det är konstigt bara när det har fungerat i tidigare program och övningar jag har gjort, gör liksom ingen skillnad nu zzZzz..(Vad jag ser iaf) xD

Permalänk
Skrivet av MickeBoy:

Du har definierat Vehicles som

[VehicleID] INT IDENTITY (1, 1) NOT NULL, [VehicleType] NVARCHAR (10) NOT NULL, [VehicleRegNumber] NVARCHAR (10) NOT NULL, [VehicleArrivalTime] DATETIME NOT NULL, [ParkingSpaceID] INT NOT NULL, PRIMARY KEY CLUSTERED ([VehicleID] ASC), CONSTRAINT [FK_ParkingSpaceID] FOREIGN KEY ([ParkingSpaceID]) REFERENCES [dbo].[ParkingSpace] ([ParkingSpaceID])

I denna tabell har du en kolumn som heter ParkingSpaceID som lagrar heltal. Den har också har en begränsning (constraint) att värden i den kolumnen (för varje rad) måste kunna återfinnas i [dbo].[ParkingSpace] ([ParkingSpaceID].

Så om du försöker att sätta in NULL i något anrop så är det rimligt att det inte fungerar.

Jag tänker att du skulle utöka din kod så att när du fångar det exception som kastas när detta inträffar också loggar värdet av de parametrar som du försöker anropa din lagrade procedur med. Utöka alltså TextToUser.PrintExceptionMessage så att du kan få med mer information.

Om du sedan fångar dessa värden i ett felmeddelande eller en logg så kan du använda t.ex. Management Studio för att ta upp den lagrade proceduren och köra enbart logiken i ett nytt fönster. Genom att använda PRINT så kan du skapa dig själv utskrifter till skärmen.

På detta vis borde du kunna komma fram till vad som behöver andras.

Hmm, juste. Jag försöker ju att inte sätta in null, utan vill ju att vehicles ska få ett parkingspaceID när fordon läggs till. Men felmeddelande blir att "Can not insert value null to ParkingSpaceID" för att jag har den som NOT NULL, har svårt att gå vidare med mina andra metoder när jag inte kan joina dom för att få ut information

Permalänk
Medlem
Skrivet av PapaDiouf:

Hmm, juste. Jag försöker ju att inte sätta in null, utan vill ju att vehicles ska få ett parkingspaceID när fordon läggs till. Men felmeddelande blir att "Can not insert value null to ParkingSpaceID" för att jag har den som NOT NULL, har svårt att gå vidare med mina andra metoder när jag inte kan joina dom för att få ut information

Det går att göra på många olika sätt. Jag tänker mig att jag hade försökt att modellera det lite mer som den riktiga världen ser ut:
En tabell med fordon, en tabell med platser i garaget och en kopplingstabell där emellan med data från fordonen (ID) och data från garaget (P-platsnummer) och sedan lite loggdata för parkeringen start och slut.

Men nu är det som det är. Detta är ett försök till lösning så som du har gjort det. Jag har inte testat det.
Det hela går ut på att hantera bilar och motorcyklar på olika sätt. Bilarna fungerar ju redan och för motorcykel så försöker jag ta fram nästa parkeringsplats som har en del av en plats ledig först och finns det ingen sådan så används nästa lediga hela plats på samma sätt som för bilar.

CREATE PROCEDURE spAddVehicle @VehicleType NVARCHAR(10), @VehicleRegNumber NVARCHAR(10), @VehicleArrivalTime DATE, @PSpaceSize INT, @PSpacesRemaining INT AS BEGIN INSERT INTO Vehicles(VehicleType , VehicleRegNumber, VehicleArrivalTime) VALUES (@VehicleType, @VehicleRegNumber, GETDATE()) DECLARE @PSpaceNumber INT IF @VehicleType = 'Car' BEGIN SET @PSpaceNumber = (SELECT COUNT(*) FROM ParkingSpace) + 1 INSERT INTO ParkingSpace(PSpaceNumber, PSpaceSize, PSpacesRemaining) VALUES (@PSpaceNumber, @PSpaceSize, @PSpacesRemaining) END ELSE -- 'TypeMotorBike' BEGIN SET @PSpaceNumber = ISNULL((SELECT TOP 1 PSpaceNumber FROM ParkingSpace WHERE PSpacesRemaining > 1), 0) -- Find next available space for motorbike IF @PSpaceNumber = 0 -- If no one found, just use next whole space like for car SET @PSpaceNumber = (SELECT COUNT(*) FROM ParkingSpace) + 1 ELSE BEGIN SET @PSpacesRemaining = SELECT PSpacesRemaining FROM ParkingSpace WHERE PSpaceNumber = @PSpaceNumber SET @PSpacesRemaining = @PSpacesRemaining - 1 -- Remove one more 'slot' for that space END INSERT INTO ParkingSpace(PSpaceNumber, PSpaceSize, PSpacesRemaining) VALUES (@PSpaceNumber, @PSpaceSize, @PSpacesRemaining) END RETURN @PSpaceNumber END

Nu har du något att jobba vidare med hoppas jag. Du behöver åtminstone fixa till if-satsen som kontrollerar typ av fordon.

Permalänk
Skrivet av MickeBoy:

Det går att göra på många olika sätt. Jag tänker mig att jag hade försökt att modellera det lite mer som den riktiga världen ser ut:
En tabell med fordon, en tabell med platser i garaget och en kopplingstabell där emellan med data från fordonen (ID) och data från garaget (P-platsnummer) och sedan lite loggdata för parkeringen start och slut.

Men nu är det som det är. Detta är ett försök till lösning så som du har gjort det. Jag har inte testat det.
Det hela går ut på att hantera bilar och motorcyklar på olika sätt. Bilarna fungerar ju redan och för motorcykel så försöker jag ta fram nästa parkeringsplats som har en del av en plats ledig först och finns det ingen sådan så används nästa lediga hela plats på samma sätt som för bilar.

CREATE PROCEDURE spAddVehicle @VehicleType NVARCHAR(10), @VehicleRegNumber NVARCHAR(10), @VehicleArrivalTime DATE, @PSpaceSize INT, @PSpacesRemaining INT AS BEGIN INSERT INTO Vehicles(VehicleType , VehicleRegNumber, VehicleArrivalTime) VALUES (@VehicleType, @VehicleRegNumber, GETDATE()) DECLARE @PSpaceNumber INT IF @VehicleType = 'Car' BEGIN SET @PSpaceNumber = (SELECT COUNT(*) FROM ParkingSpace) + 1 INSERT INTO ParkingSpace(PSpaceNumber, PSpaceSize, PSpacesRemaining) VALUES (@PSpaceNumber, @PSpaceSize, @PSpacesRemaining) END ELSE -- 'TypeMotorBike' BEGIN SET @PSpaceNumber = ISNULL((SELECT TOP 1 PSpaceNumber FROM ParkingSpace WHERE PSpacesRemaining > 1), 0) -- Find next available space for motorbike IF @PSpaceNumber = 0 -- If no one found, just use next whole space like for car SET @PSpaceNumber = (SELECT COUNT(*) FROM ParkingSpace) + 1 ELSE BEGIN SET @PSpacesRemaining = SELECT PSpacesRemaining FROM ParkingSpace WHERE PSpaceNumber = @PSpaceNumber SET @PSpacesRemaining = @PSpacesRemaining - 1 -- Remove one more 'slot' for that space END INSERT INTO ParkingSpace(PSpaceNumber, PSpaceSize, PSpacesRemaining) VALUES (@PSpaceNumber, @PSpaceSize, @PSpacesRemaining) END RETURN @PSpaceNumber END

Nu har du något att jobba vidare med hoppas jag. Du behöver åtminstone fixa till if-satsen som kontrollerar typ av fordon.

Vilken hjälte du är, fan nu fick jag äntligen till det, nu kommer resten av programmet gå hyfsat smidigt hoppas jag Tack snälla!
Enda som hemsöker mig nu är den jäkla foreign key som inte får något värde

Permalänk
Medlem
Skrivet av PapaDiouf:

Vilken hjälte du är, fan nu fick jag äntligen till det, nu kommer resten av programmet gå hyfsat smidigt hoppas jag Tack snälla!
Enda som hemsöker mig nu är den jäkla foreign key som inte får något värde

Ja, men har du ändrat strukturen då?

När du ska sätta in någonting i din tabell Vehicle, så vill du att raden för ditt fordon refererar till en specifik rad i tabellen parkeringsplats. Är det inte så du tänkt?

Så som din lagrade procedur nu är skapad så sätter du ju in raden i tabellen Vehicle först och sedan räknar du fram värden för parkeringsplatsen och därefter sker insättningen i tabellen ParkingSpace. Och just denna rad är den som du vill referera till?

Med en sådan ordning så kan du väl omöjligen få ihop det?

Jag tänker att du skulle byta ordning på sakerna i din lagrade procedur så att du först letar fram platsen och när insättningen till ParkingSpace har gjorts så sparar du värdet du vill ha i en variabel i din lagrade procedur och använder det för insättningen i tabellen Vehicle.