Estou usando o Dapper para executar a seguinte consulta em uma instância do SQL Server 2008 R2 Express de um aplicativo 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
A chamada para connection.Query<int>(sql, ...)
está lançando uma exceção de conversão inválida. Eu depurei e é no ponto em que Dapper chama GetValue
o retornado SqlDataReader
.
O tipo de retorno GetValue
é Object
: inspecionando-o no programa de depuração, é um decimal em caixa.
Se eu alterar o select para SELECT CAST(@@IDENTITY as int)
, o retorno de GetValue será um int em caixa e a exceção não será lançada.
A coluna Id é definitivamente do tipo int; Por que SELECT @@IDENTITY
retornaria um decimal?
Algumas informações adicionais:
- O banco de dados é novo em folha.
- A tabela Customers é o único objeto que eu adicionei a ela. Não há outras tabelas (usuários), visualizações, gatilhos ou procedimentos armazenados no banco de dados.
- Existem 10 linhas no banco de dados, existem IDs 1,2,3,4,5,6,7,8,9,10 (ou seja, a coluna não está além dos limites de um int).
Minha definição de tabela é
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
fonte
fonte
Respostas:
@@ identity retorna um numérico (38,0) . Você precisará convertê-lo para obter um int.
SELECIONAR CAST (@@ identidade AS INT)
Além disso, tente usar scope_identity. Se houver algum gatilho na tabela Customers, você poderá obter a última identidade de outra tabela.
Por fim, como você está usando o dapper , deseje agrupar tudo isso em um procedimento armazenado para garantir a execução da inserção e a seleção na identidade no mesmo lote.
Teoricamente, deve funcionar a maior parte do tempo para executar os dois por conta própria. Mas podem surgir problemas se você precisar acessar o banco de dados duas vezes. (Por exemplo, como isso funciona com o pool de conexões? E quanto às conexões perdidas? Etc.) Se você simplesmente jogar tudo em um procedimento armazenado, não precisará se preocupar com esse esforço extra no futuro.
fonte
Criar tabela diz:
" IDENTIDADE
Indica que a nova coluna é uma coluna de identidade. Quando uma nova linha é adicionada à tabela, o Microsoft® SQL Server ™ fornece um valor incremental exclusivo para a coluna. As colunas de identidade são comumente usadas em conjunto com as restrições PRIMARY KEY para servir como o identificador de linha exclusivo da tabela. A propriedade IDENTITY pode ser atribuída às colunas tinyint, smallint, int, bigint, decimal (p, 0) ou numérico (p, 0). Somente uma coluna de identidade pode ser criada por tabela. Padrões limitados e restrições DEFAULT não podem ser usados com uma coluna de identidade. Você deve especificar a semente e o incremento ou nenhum. Se nenhum for especificado, o padrão é (1,1).
semente
É o valor usado para a primeira linha carregada na tabela.
incremento
O valor incremental adicionado ao valor de identidade da linha anterior foi carregado. "
Portanto, a função do sistema @@ identity terá que lidar com o tipo de cobertura mais alto.
fonte
numeric
como tem a maior variedade ..? Obrigado"Por que SELECT @@ IDENTITY retornaria um decimal"
Como pode ser muito grande para caber em um
int
- ele não corresponde ao tipo da coluna de identidade, mas, como Richard diz, retorna um numérico (38,0) (numeric
edecimal
é sinônimo )fonte