如何在带有实体框架的SQL中使用自定义标识列
我正在尝试使用实体框架在表中使用自定义标识列。我拥有的是一个表,用于控制下一个可用于每个表的可用Id如何在带有实体框架的SQL中使用自定义标识列,sql,entity-framework,dbcontext,Sql,Entity Framework,Dbcontext,我正在尝试使用实体框架在表中使用自定义标识列。我拥有的是一个表,用于控制下一个可用于每个表的可用Id CREATE TABLE [dbo].[SystemNumbers]( [SystemNumberDesc] [varchar](30) NOT NULL, [LastId] [Int] NOT NULL CONSTRAINT [PK__SystemNumbers] PRIMARY KEY CLUSTERED ( [SystemNumberDesc] ASC )WIT
CREATE TABLE [dbo].[SystemNumbers](
[SystemNumberDesc] [varchar](30) NOT NULL,
[LastId] [Int] NOT NULL
CONSTRAINT [PK__SystemNumbers] PRIMARY KEY CLUSTERED
(
[SystemNumberDesc] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO
包含表的行计数器的行,插入方式如下
INSERT INTO SystemNumbers VALUES ('WS', 0)
CREATE TRIGGER WSId
ON WS AFTER INSERT
AS BEGIN
DECLARE @LastId INT
DECLARE @TableName VARCHAR(100)
DECLARE @INSERTID INT
SET @TableName = 'WS'
SET NOCOUNT ON
SELECT @INSERTID = SystemID, @CREATETS = SystemTS, @StoreId = StoreId FROM Inserted
IF (@INSERTID = 0) BEGIN
SELECT @LastId = LastId + 1 FROM SystemNumbers WHERE SystemNumberDesc = @TableName
UPDATE SystemNumbers SET LastId = @LastId WHERE SystemNumberDesc = @TableName
UPDATE WS SET SystemId = @LastId, WorkstationID=@LastId WHERE SystemId = @INSERTID
END
END
然后创建要使用的表
CREATE TABLE [dbo].[WS](
[WorkstationID] INT NOT NULL,
[WorkstationName] [varchar](50) NULL,
[WSTS] TIMESTAMP,
CONSTRAINT [PK_WS] PRIMARY KEY CLUSTERED
(
[WorkstationID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO
然后创建触发器,从SystemCounters
表中获取下一个Id,并按如下方式更新Id
INSERT INTO SystemNumbers VALUES ('WS', 0)
CREATE TRIGGER WSId
ON WS AFTER INSERT
AS BEGIN
DECLARE @LastId INT
DECLARE @TableName VARCHAR(100)
DECLARE @INSERTID INT
SET @TableName = 'WS'
SET NOCOUNT ON
SELECT @INSERTID = SystemID, @CREATETS = SystemTS, @StoreId = StoreId FROM Inserted
IF (@INSERTID = 0) BEGIN
SELECT @LastId = LastId + 1 FROM SystemNumbers WHERE SystemNumberDesc = @TableName
UPDATE SystemNumbers SET LastId = @LastId WHERE SystemNumberDesc = @TableName
UPDATE WS SET SystemId = @LastId, WorkstationID=@LastId WHERE SystemId = @INSERTID
END
END
去
使用SQL来执行插入操作,效果很好。然后,我将ADO.Net实体框架添加到我的项目中,并尝试插入一条记录
这给了我一个初始问题,即列定义为Computed,需要更改为Identity。我把这个换了,然后得到
EntityFramework.dll中发生类型为“System.Data.Entity.Infrastructure.DbUpdateConcurrencyException”的未处理异常
其他信息:Store update、insert或delete语句影响了意外的行数(0)。自加载实体后,实体可能已被修改或删除。刷新ObjectStateManager条目
我怀疑这是因为它插入了记录,然后试图重新加载它以获得诸如时间戳之类的Db值
我已经跟随了许多线索,但只是在一个圆圈结束。我需要从表中设置列,因为它是多存储的,因此标识字段将不起作用。您的触发器有一个巨大的缺陷,您似乎认为每行调用一次触发器-SQL Server不是这种情况。如果
INSERT
或UPDATE
影响多行,则每个语句将调用一次触发器,并且插入的和删除的伪表可以包含多行。因此,在执行select@id1=i.id from inserted i时,您将选择这些行中的哪一行代码>???它没有定义-您得到一行,任意行和所有其他行被忽略。。。。您需要重新写入触发器以处理插入的和删除的中的多行!我将在最终版本中考虑这一点,因为我在更新的WHERE子句中使用了一个Timestamp列。目前表是空的,我可以确信只有1条记录被插入。-干杯,马克,我不认为你能解决这个问题。一些替代方案:,没有什么可以解决的。查看代码,您试图基于表名生成一系列唯一的整数值。你也可以为这些表创建一个标识键,让系统为你做所有的工作。我需要生成Id,因为在某个阶段将有2个数据库合并在一起,所以当您合并数据时,Id开始创建间隙。作为其中的一部分,有一个DbId作为Id的前缀,以确保它是唯一的。