Проблемы с последней вставленной идентификацией записи с использованием типизированных DataSet и DataGridView
Я использую следующие для простого приложения базы данных:
- SQL Server Compact Edition.sdf файл в качестве базы данных с идентификаторами первичных ключей int.
- Типизированные DataSet и BindingSource в качестве уровня доступа к данным
- DataGridView для отображения данных.
Моя проблема в том, что у меня проблемы с последним вставленным идентификатором записи / строки. Когда я добавляю строку в представление данных с помощью кнопки "Добавить" компонента навигатора, идентификатор новой записи / строки равен -1. Это все еще -1, даже после сохранения данных в базу данных, используя TableAdapter.Update(). Я знаю, что могу получить последний идентификатор с помощью отдельного запроса с @@identity или scope_identity(), но не совсем правильно, что вам просто нужно использовать другой запрос для обновления ваших данных, причем вручную. Я что-то здесь упускаю? Существует ли автоматический способ обновления ваших данных после сохранения в базе данных и получения идентификатора только что вставленной записи?
Кроме того, я видел опцию "обновить данные" в конструкторе набора данных -> конфигурация адаптера таблицы -> расширенное окно, но по некоторым причинам он отключен. Но я не знаю, связано ли это..
Буду признателен за любую помощь с этим..
6 ответов
Спасибо за оба ответа. Я нашел источник проблемы, к сожалению, нет решения по моему вкусу. Проблема в SQL Server Compact Edition. Так как он не поддерживает хранимые процедуры или множественный активный набор результатов (MARS), вы не можете запустить более одного SQL в одном запросе. Поэтому опция "обновить данные" отключена, что приведет к обновлению значения идентификатора фактическим значением, если оно не будет отключено. Я собираюсь изменить значение моего идентификатора первичного ключа с int на Guid, обработать событие RowInit объекта DataGridView и дать идентификатор Guid новым строкам вручную.
Вы также можете попытаться объявить свой столбец идентификаторов в качестве параметра OUTPUT в вашей хранимой процедуре.
CREATE PROCEDURE YourSP
(@ID int OUTPUT, ...
Я думаю, что вам придется вызывать databind() в вашем gridview после обновления базы данных, если вы зависите от базы данных для автоматической генерации ключа для вновь вставленной записи.
Установите IdentitySeed и IdentityIncrement в 1, и все работает.
Я нашел это в документации к Microsoft SQL Server Compact Edition:
вернуть последнюю вставленную личность:
ВЫБЕРИТЕ @@IDENTITY или ВЫБЕРИТЕ @@IDENTITY AS 'TEMPNAME'
То, что я обычно делаю с моим DTO - это что-то похожее на vb ниже
Public Sub InsertSupplier(ByVal SupplierObject As Supplier) Implements ISupplierRepository.InsertSupplier
SupplierObject.SupplierID = MyBase.ExecuteNonQueryWithReturnValue("usp_Northwind_InsertSupplier", SupplierObject.CompanyName)
End Sub
С моей хранимой процедурой, аналогичной приведенной ниже
USE [Northwind]
GO
/****** Object: StoredProcedure [dbo].[usp_Northwind_InsertSupplier] Script Date: 1/1/2009 10:59:01 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[usp_Northwind_InsertSupplier]
@CompanyName nvarchar(40)
AS
INSERT INTO dbo.Suppliers
VALUES (@CompanyName)
RETURN @@Identity
Просто чтобы уточнить, что делает мой 1 вкладыш в базовом классе (используя библиотеку Fyi)
Public Function ExecuteNonQueryWithReturnValue(ByVal storedProcedureName As String, ByVal ParamArray parameterValues() As Object) As Object Implements Interfaces.IRepository(Of T).ExecuteNonQueryWithReturnValue
Dim Output As Object
Dim db As Database = DatabaseFactory.CreateDatabase()
Dim dbCommand As Common.DbCommand = db.GetStoredProcCommand(storedProcedureName, parameterValues)
db.ExecuteNonQuery(dbCommand)
Output = CType(db.GetParameterValue(dbCommand, "@RETURN_VALUE"), Object)
Return Output
End Function