在ASP.NET中支持实体框架和SQL Server 2014作为数据库引擎的RESTful服务时,我遇到了一些意想不到的障碍。
我准备了一些虚拟案例,它准确地解释了我现在遇到的问题。
我在SQL Server中有一个名为“dummy_database”的数据库。它只包含一个表 - Person - 和一个触发器 - TR_Person_Insert - 它负责在将记录添加到“Person”表之前,将一些额外数据(在这种特定情况下的当前日期和时间)添加到每个记录。数据库结构代码包括在下面:
USE dummy_database;
GO
IF EXISTS (SELECT * FROM sys.tables WHERE name LIKE 'person')
DROP TABLE [person];
GO
IF EXISTS (SELECT * FROM sys.triggers WHERE name LIKE 'TR_Person_Insert')
DROP TRIGGER [TR_Person_Insert];
GO
CREATE TABLE [dbo].[person]
(
[id] INT IDENTITY(1, 1),
[name] NVARCHAR(256) NOT NULL,
[surname] NVARCHAR(256) NOT NULL,
[age] INT NOT NULL,
[valid_from] DATETIME2 (7),
CONSTRAINT PK_Person_ID PRIMARY KEY ([id])
)
GO
CREATE TRIGGER TR_Person_Insert ON [dbo].[person]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO [dbo].[person] ([name], [surname], [age], [valid_from])
SELECT i.[name], i.[surname], i.[age], GETDATE()
FROM inserted i
END
GO
然后我使用ASP.NET创建了虚拟RESTful服务,并添加了Entity Framework和Database First方法。该服务的唯一现有方法的代码如下:
[RoutePrefix("api/person")]
public class DummyController : ApiController
{
[HttpPost, Route("")]
public IHttpActionResult AddPerson(PersonDto data)
{
using (var ctx = new DummyDatabaseModel())
{
var person = new person
{
name = data.Name,
surname = data.Surname,
age = data.Age
};
ctx.people.Add(person);
ctx.SaveChanges();
}
return Ok();
}
}
问题在于在数据库的上下文中调用保存更改方法。此方法抛出DBUpdateConcurrencyException异常,并提供以下附加信息:
An exception of type 'System.Data.Entity.Infrastructure.DbUpdateConcurrencyException' occurred in EntityFramework.dll but was not handled in user code
Additional information: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded.
我知道这个异常是由触发器引起的,触发器在数据库端被触发而不是常规的'insert'例程。
我问的问题是 - 如何在不放弃数据库触发器的情况下摆脱这种异常。如果您在过去遇到同样的问题,我会缺乏想法并坦率地说 - 我依靠您的提示或解决方案。
感谢您的帮助。