INSTEAD OF INSERT 设置的主键在实体框架中抛出错误(ASP.NET 框架 c#)
Posted
技术标签:
【中文标题】INSTEAD OF INSERT 设置的主键在实体框架中抛出错误(ASP.NET 框架 c#)【英文标题】:primary key set by INSTEAD OF INSERT throwing error in entity framework (ASP.NET framework c#) 【发布时间】:2021-11-06 02:34:05 【问题描述】:我刚开始使用 .NET 并一直在尝试对表执行 CRUD 操作。该表上有一个触发器,用于设置主键。现在,读取、更新和删除操作可以顺利进行。我的问题在于创建操作。
这是触发器
create or alter trigger dbo.CreateEmpID on dbo.Employee instead of insert
as
begin
declare @NextId varchar(20)
declare @EmpName varchar(50)
declare @cur cursor
set @cur = cursor for select EmpName from inserted
open @cur
fetch next from @cur into @EmpName
while @@FETCH_STATUS = 0
begin
select @NextId = 'EMP' + convert(varchar(20), isNull(max(convert(int, substring(EmpID, 4, len(EmpID)-3))),0)+1) from Employee
insert into Employee(EmpID, EmpName) values (@NextId, @EmpName)
fetch next from @cur into @EmpName
end
close @cur
deallocate @cur
end
这是创建新员工的代码部分
//POST: Create
[HttpPost]
public ActionResult Create(Employee Emp)
DB.Employees.Add(Emp);
DB.SaveChanges();
return RedirectToAction("Index");
这是我不断收到的错误
System.Data.Entity.Validation.DbEntityValidationException: 'Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.'
我还对另一件事感到困惑。在同一个表上还有另一个触发器在删除后工作,它将删除的员工复制到另一个表。那么是只有 INSTEAD OF 触发器有问题还是代码有问题。
感谢任何帮助。
编辑:
我将表格更改为使用第一个答案中提到的序列,但它仍然给我错误。这也是详细的错误
System.Data.Entity.Validation.DbEntityValidationException
HResult=0x80131920
Message=Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
Source=EntityFramework
StackTrace:
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at Test.Controllers.HomeController.Index() in E:\vs\projects\Test\Test\Controllers\HomeController.cs:line 18
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c.<BeginInvokeSynchronousActionMethod>b__9_0(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass11_0.<InvokeActionMethodFilterAsynchronouslyRecursive>b__0()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2()
【问题讨论】:
您可以按照异常消息的指示检查EntityValidationErrors
。我们不可以。请查看这些详细信息并将其添加到问题中。
旁注,TRIGGER
和 WHILE
将远非高效。即使是几千行,它也会非常缓慢。为什么不使用基于集合的方法?
再次查看触发器,我强烈建议只存储由IDENTITY
或序列生成的整数,然后将EMP
前缀应用为计算列,甚至仅在表示层。不要将表示问题与您应该存储在数据库中的 data 混淆。通过混入演示文稿前缀,您已经使您的工作变得比需要的困难得多。
您的触发代码有缺陷,并发插入时可能会违反 PK。
考虑前缀是静态的,我个人认为不需要在数据库层添加。如果它来自另一列,则可能需要考虑。
【参考方案1】:
这里可能会出现很多问题,但不值得进行故障排除,因为您永远不应该通过从目标表中查询 max(id)+1
来生成密钥。它无法扩展并且容易产生死锁。
如果你想要一个像EMP1234
这样的密钥,你可以用一个SEQUENCE 和一个DEFAULT 来生成它,参见例如和How to generate unique incremental employee code(pattern: E0001, E0002, E0003, ... ) in the INSERT stored procedure in SQL Server?
但通常您只需使用 SEQUENCE 或 IDENTITY COLUMN 并继续前进。
【讨论】:
我尝试按照帖子中提到的顺序进行操作,但在 Visual Studio 中仍然遇到同样的错误 我在没有序列的情况下尝试了它,只是一个由身份设置的主键的 int。它工作得很好,但为什么不能工作? @PrithviEmmanuelMachado - 相同的错误 - 但我们不知道详细信息,因为错误显示“发生了一些错误,请在此处查看详细信息”,或者您没有看过那里,或者如果您有,您还没有更新问题来告诉我们详情。 我发布了详细的错误。我无法弄清楚它在说什么。看看能不能找到问题 您需要“查看 'EntityValidationErrors'”,这是 DbEntityValidationException 下的一个集合。以上是关于INSTEAD OF INSERT 设置的主键在实体框架中抛出错误(ASP.NET 框架 c#)的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server INSTEAD OF INSERT 触发器失败
oracle 中查看一张表是不是有主键,主键在哪个字段上的语句怎么查如要查aa表,请写两句分别回答
sql - INSTEAD OF INSERT 触发器 - 插入前清除值