Dapper を使用して、ASP.NET MVC 3(.NET 4.0)アプリケーションからSQL Server 2008 R2 Expressインスタンスに対して次のクエリを実行しています。
_INSERT INTO Customers (
Type, Name, Address, ContactName,
ContactNumber, ContactEmail, Supplier)
VALUES (
@Type, @Name, @Address, @ContactName,
@ContactNumber, @ContactEmail, @Supplier)
SELECT @@IDENTITY
_
connection.Query<int>(sql, ...)
を呼び出すと、無効なキャスト例外がスローされます。私はそれをデバッグしました、そしてそれはDapperが返されたGetValue
でSqlDataReader
を呼び出す時点です。
GetValue
の戻り値の型はObject
であり、デバッガーショーで検査すると、ボックス化された10進数です。
SelectをSELECT CAST(@@IDENTITY as int)
に変更すると、GetValueの戻り値はボックス化されたintになり、例外はスローされません。
Id列は間違いなくint型です。 なぜ_SELECT @@IDENTITY
_は小数を返すのですか?
いくつかの追加情報:
私のテーブル定義は
_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]
_
@@ identityは数値(38,0) を返します。 intにするには、キャストする必要があります。
SELECT CAST(@@ identity AS INT)
また、代わりにscope_identityを使用してみてください。 Customersテーブルにトリガーがある場合、別のテーブルから最後のIDを取得する可能性があります。
最後に、 dapper を使用しているので、すべてをストアドプロシージャ内にラップして、同じバッチでIDの挿入と選択の実行が保証されるようにします。
理論的には、ほとんどの場合、両方を単独で実行することで機能します。ただし、データベースに2回アクセスする必要がある場合は、問題が発生する可能性があります。 (たとえば、これは接続プーリングでどのように機能しますか?ドロップされた接続はどうですか?など)ストアドプロシージャですべてをスローするだけであれば、将来の余分な労力について心配する必要はありません。
テーブルの作成 は言う:
"[〜#〜] identity [〜#〜]
新しい列がID列であることを示します。新しい行がテーブルに追加されると、Microsoft®SQL Server™は列に一意の増分値を提供します。 ID列は通常、PRIMARY KEY制約と組み合わせて使用され、テーブルの一意の行識別子として機能します。 IDENTITYプロパティは、tinyint、smallint、int、bigint、decimal(p、0)、またはnumeric(p、0)列に割り当てることができます。のみテーブルごとに1つのID列を作成できます。バインドされたデフォルトとDEFAULT制約は、ID列では使用できません。シードと増分の両方を指定するか、どちらも指定しないでください。どちらも指定されていない場合、デフォルトは(1,1)です。
シード
テーブルにロードされる最初の行に使用される値です。
増分
ロードされた前の行のID値に追加された増分値ですか?」
したがって、システム関数@@ identityは、最もカバーするタイプに対応する必要があります。
「SELECT @@ IDENTITYが10進数を返す理由」
大きすぎてint
に収まらない可能性があるため、ID列のタイプとは一致しませんが、Richardが言うように、numeric(38,0)(numeric
およびdecimal
同義語です )