Ich verwende Dapper , um die folgende Abfrage für eine SQL Server 2008 R2 Express-Instanz aus einer ASP.NET MVC 3-Anwendung (.NET 4.0) auszuführen.
INSERT INTO Customers (
Type, Name, Address, ContactName,
ContactNumber, ContactEmail, Supplier)
VALUES (
@Type, @Name, @Address, @ContactName,
@ContactNumber, @ContactEmail, @Supplier)
SELECT @@IDENTITY
Der Aufruf von connection.Query<int>(sql, ...)
löst eine ungültige Besetzungsausnahme aus. Ich habe es ausgetestet und es ist an der Stelle , wo Dapper Anrufe GetValue
auf die zurück SqlDataReader
.
Der Rückgabetyp von GetValue
ist Object
, es in der Debugger-Show zu überprüfen, es ist eine Boxed Decimal.
Wenn ich die Auswahl auf SELECT CAST(@@IDENTITY as int)
ändere, ist die Rückgabe von GetValue ein Boxed Int und die Ausnahme wird nicht geworfen.
Die ID-Spalte ist definitiv vom Typ int. Warum sollte SELECT @@IDENTITY
eine Dezimalzahl zurückgegeben werden?
Einige zusätzliche Informationen:
- Die Datenbank ist brandneu.
- Die Customers-Tabelle ist das einzige Objekt, das ich hinzugefügt habe. Die Datenbank enthält keine anderen (Benutzer-) Tabellen, Ansichten, Trigger oder gespeicherten Prozeduren.
- Die Datenbank enthält 10 Zeilen, die IDs sind 1,2,3,4,5,6,7,8,9,10 (dh die Spalte überschreitet nicht 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]
quelle
Antworten:
@@ identity gibt eine Zahl (38,0) zurück . Sie müssen es wirken, um es zu einem int zu bekommen.
SELECT CAST (@@ Identität AS INT)
Verwenden Sie stattdessen auch scope_identity. Wenn die Customers-Tabelle Auslöser enthält, wird möglicherweise die letzte Identität von einer anderen Tabelle abgerufen.
Da Sie dapper verwenden , sollten Sie all das in eine gespeicherte Prozedur einschließen , damit Sie garantiert die Einfügung ausführen und dann die Identität im selben Stapel auswählen können.
Theoretisch sollte es die meiste Zeit funktionieren, beide alleine auszuführen. Es können jedoch Probleme auftreten, wenn Sie zweimal zur Datenbank gehen müssen. (ZB wie funktioniert das mit dem Verbindungspooling? Was ist mit unterbrochenen Verbindungen? Usw.) Wenn Sie einfach alles in eine gespeicherte Prozedur werfen, müssen Sie sich später nicht mehr um diesen zusätzlichen Aufwand kümmern.
quelle
Tabelle erstellen sagt:
" IDENTITÄT
Gibt an, dass die neue Spalte eine Identitätsspalte ist. Wenn der Tabelle eine neue Zeile hinzugefügt wird, stellt Microsoft® SQL Server ™ einen eindeutigen inkrementellen Wert für die Spalte bereit. Identitätsspalten werden häufig in Verbindung mit PRIMARY KEY-Einschränkungen verwendet, um als eindeutige Zeilenbezeichnung für die Tabelle zu dienen. Die IDENTITY-Eigenschaft kann den Spalten tinyint, smallint, int, bigint, decimal (p, 0) oder numeric (p, 0) zugewiesen werden. Pro Tabelle kann nur eine Identitätsspalte erstellt werden. Gebundene Standardwerte und DEFAULT-Einschränkungen können nicht mit einer Identitätsspalte verwendet werden. Sie müssen sowohl den Startwert als auch das Inkrement oder keines angeben. Wenn keines angegeben ist, ist der Standardwert (1,1).
Samen
Wird der Wert für die allererste in die Tabelle geladene Zeile verwendet.
Zuwachs
Wird der inkrementelle Wert zum Identitätswert der vorherigen geladenen Zeile addiert? "
Die Systemfunktion @@ identity muss sich also mit dem umfassendsten Typ auseinandersetzen.
quelle
numeric
da es die größte Reichweite hat. Vielen Dank"Warum sollte SELECT @@ IDENTITY eine Dezimalzahl zurückgeben?"
Da es möglicherweise zu groß ist, um in eine zu passen
int
, stimmt es nicht mit dem Typ der Identitätsspalte überein, gibt aber, wie Richard sagt, eine Zahl (38,0) zurück (numeric
unddecimal
sind Synonyme ).quelle