Warum gibt `select @@ Identity` eine Dezimalzahl zurück?
-
16-10-2019 - |
Frage
Ich benutze Dapper Um die folgende Abfrage gegen eine SQL Server 2008 R2 Express -Instanz aus einer ASP.NET MVC 3 (.NET 4.0) -Anwendung auszuführen.
INSERT INTO Customers (
Type, Name, Address, ContactName,
ContactNumber, ContactEmail, Supplier)
VALUES (
@Type, @Name, @Address, @ContactName,
@ContactNumber, @ContactEmail, @Supplier)
SELECT @@IDENTITY
Der Anruf an connection.Query<int>(sql, ...)
Wirft eine ungültige Ausnahme aus. Ich habe es debuggen und es ist an dem Punkt, an dem Dapper anruft GetValue
auf die zurückgekehrte SqlDataReader
.
Die Rückgabeart von GetValue
ist Object
, um es in der Debugger -Show zu inspizieren, ist ein Box -Dezimal.
Wenn ich die Auswahl an ändere, um SELECT CAST(@@IDENTITY as int)
, Die Rückkehr von GetValue ist ein Boxed INT und die Ausnahme wird nicht ausgelöst.
Die ID -Spalte ist definitiv vom Typ int; Warum sollte SELECT @@IDENTITY
eine Dezimalzahl zurückgeben?
Einige zusätzliche Informationen:
- Die Datenbank ist brandneu.
- Die Kundentabelle ist das einzige Objekt, das ich hinzugefügt habe. In der Datenbank gibt es keine anderen (Benutzer-) Tabellen, Ansichten, Auslöser oder gespeicherten Prozeduren.
- Es gibt 10 Zeilen in der Datenbank, es gibt IDs 1,2,3,4,5,6,7,8,9,10 (dh die Spalte liegt nicht über die Grenzen eines INT).
Meine Tabellendefinition ist
CREATE TABLE [dbo].[Customers](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Type] [int] NOT NULL,
[Name] [nvarchar](255) NOT NULL,
[Address] [nvarchar](1000) NOT NULL,
[ContactName] [nvarchar](255) NOT NULL,
[ContactNumber] [nvarchar](50) NOT NULL,
[ContactEmail] [nvarchar](255) NOT NULL,
[Supplier] [nvarchar](255) NOT NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Lösung
@@ Identity gibt einen numerischen zurück (38,0). Du musst es werfen, um es einem int zu bringen.
Wählen Sie Cast (@@ Identity als int) aus
Versuchen Sie stattdessen auch Scope_identity. Wenn Sie Auslöser auf dem Tisch der Kunden haben, erhalten Sie möglicherweise die letzte Identität aus einer anderen Tabelle.
Schließlich, da Sie verwenden Dapper, Sie möchten all das in eine gespeicherte Prozedur einwickeln, damit Sie garantiert den Einsatz und dann die Auswahl der Identität in derselben Stapel ausführen.
Theoretisch sollte es die meiste Zeit funktionieren, beide selbst auszuführen. Es können jedoch Probleme auftreten, wenn Sie zweimal in die Datenbank gehen müssen. (ZB Wie funktioniert das mit Verbindungspooling? Was ist mit fallengelassenen Verbindungen?
Andere Tipps
Tabelle erstellen sagt:
"IDENTITÄT
Zeigt an, dass die neue Spalte eine Identitätsspalte ist. Wenn eine neue Zeile zur Tabelle hinzugefügt wird, bietet Microsoft® SQL Server ™ einen eindeutigen, inkrementellen Wert für die Spalte. Identitätsspalten werden üblicherweise in Verbindung mit Primärschlüsselbeschränkungen verwendet, um als eindeutige Zeilenkennung für die Tabelle zu dienen. Die Identitätseigenschaft kann Tinyint, Smallint, INT, Bigint, Decimal- (P, 0) oder numerischen (p, 0) Spalten zugeordnet werden. Es kann nur eine Identitätsspalte pro Tabelle erstellt werden. Gebundene Standard- und Standardbeschränkungen können nicht mit einer Identitätsspalte verwendet werden. Sie müssen sowohl den Saatgut als auch das Inkrement oder beide angeben. Wenn auch nicht angegeben ist, ist der Standard (1,1).
Samen
Ist der Wert, der für die allererste Zeile in die Tabelle geladen wird.
Zuwachs
Ist der inkrementelle Wert, der dem Identitätswert der vorherigen Zeile hinzugefügt wurde. "
Die Systemfunktion @@ Identity muss also mit dem am meisten abdeckenden Typ fertig werden.
"Warum sollte @@ Identity eine Dezimalzahl zurückgeben?"
Weil es zu groß sein könnte, um in eine zu passen int
- Es stimmt nicht mit der Art der Identitätsspalte überein, aber wie Richard sagt, gibt ein numerisches (38,0) zurück (numeric
und decimal
sind Synonyme)