J'utilise Dapper pour exécuter la requête suivante sur une instance SQL Server 2008 R2 Express à partir d'une application ASP.NET MVC 3 (.NET 4.0).
INSERT INTO Customers (
Type, Name, Address, ContactName,
ContactNumber, ContactEmail, Supplier)
VALUES (
@Type, @Name, @Address, @ContactName,
@ContactNumber, @ContactEmail, @Supplier)
SELECT @@IDENTITY
L'appel à connection.Query<int>(sql, ...)
lève une exception de distribution non valide. Je l'ai débogué et c'est au point où Dapper appelle GetValue
les retournés SqlDataReader
.
Le type de retour de GetValue
est Object
, l'inspectant dans le programme de débogage, c'est une décimale encadrée.
Si je change la sélection en SELECT CAST(@@IDENTITY as int)
, le retour de GetValue est un entier encadré et l'exception n'est pas levée.
La colonne Id est définitivement de type int; Pourquoi SELECT @@IDENTITY
retournerait une décimale?
Quelques informations supplémentaires:
- La base de données est toute neuve.
- La table Customers est le seul objet que je lui ai ajouté. Il n'y a aucune autre table (utilisateur), vue, déclencheur ou procédure stockée dans la base de données.
- Il y a 10 lignes dans la base de données, les ID sont 1,2,3,4,5,6,7,8,9,10 (c'est-à-dire que la colonne n'est pas au-delà des limites d'un int).
Ma définition de table est
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]
sql-server
t-sql
ado.net
Greg B
la source
la source
Réponses:
@@ identity renvoie un numérique (38,0) . Vous aurez besoin de le lancer pour le mettre à un int.
SELECT CAST (@@ identity AS INT)
Essayez également d'utiliser scope_identity à la place. Si vous avez des déclencheurs sur la table Customers, vous pouvez finir par obtenir la dernière identité d'une autre table.
Enfin, étant donné que vous utilisez dapper , vous souhaiterez envelopper tout cela dans une procédure stockée afin de garantir l'exécution de l'insertion, puis la sélection de l'identité dans le même lot.
Théoriquement, cela devrait fonctionner la plupart du temps pour exécuter les deux seuls. Mais des problèmes peuvent survenir si vous devez accéder à la base de données deux fois. (Par exemple, comment cela fonctionne-t-il avec le regroupement de connexions? Qu'en est-il des connexions interrompues? Etc.) Si vous jetez tout cela dans une procédure stockée, vous n'aurez pas à vous soucier de cet effort supplémentaire en cours de route.
la source
Créer une table dit:
" IDENTITÉ
Indique que la nouvelle colonne est une colonne d'identité. Lorsqu'une nouvelle ligne est ajoutée au tableau, Microsoft® SQL Server ™ fournit une valeur incrémentielle unique pour la colonne. Les colonnes d'identité sont couramment utilisées conjointement avec les contraintes PRIMARY KEY pour servir d'identifiant de ligne unique pour la table. La propriété IDENTITY peut être affectée aux colonnes tinyint, smallint, int, bigint, décimal (p, 0) ou numérique (p, 0). Une seule colonne d'identité peut être créée par table. Les valeurs par défaut liées et les contraintes DEFAULT ne peuvent pas être utilisées avec une colonne d'identité. Vous devez spécifier à la fois la valeur de départ et l'incrément ou aucun. Si aucun n'est spécifié, la valeur par défaut est (1,1).
la graine
Est la valeur utilisée pour la toute première ligne chargée dans la table.
incrément
La valeur incrémentielle ajoutée à la valeur d'identité de la ligne précédente est-elle chargée. "
La fonction système @@ identity devra donc faire face au type le plus couvrant.
la source
numeric
car il a la gamme la plus large ..? Merci"Pourquoi SELECT @@ IDENTITY renverrait-il une décimale"
Parce qu'il peut être trop grand pour tenir dans un
int
- il ne correspond pas au type de la colonne d'identité mais comme Richard le dit renvoie un numérique (38,0) (numeric
etdecimal
sont des synonymes )la source