[英]Entity Framework 6: DbUpdateConcurrencyException
I have function to create/update entity and "instead insert, update trigger". 我具有创建/更新实体和“代替插入,更新触发器”的功能。 This error occurs when I'm creating new entity, but with updating it's OK and adding directly in database also works perfectly with this trigger. 当我创建新实体时会发生此错误,但是通过更新就可以了,直接在数据库中添加也可以与此触发器完美配合。
I'm using: 我正在使用:
Store update, insert, or delete statement affected an unexpected number of rows (0). 存储更新,插入或删除语句影响了意外的行数(0)。 Entities may have been modified or deleted since entities were loaded. 自加载实体以来,实体可能已被修改或删除。 See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions. 有关了解和处理乐观并发异常的信息,请参见http://go.microsoft.com/fwlink/?LinkId=472540 。
What I already tried: 我已经尝试过的
catch (DbUpdateConcurrencyException ex) { var ctx = ((IObjectContextAdapter)db).ObjectContext; ctx.Refresh(RefreshMode.ClientWins, db.Plannings); db.SaveChanges(); return new SaveResult(true); }
With and without SET NOCOUNT ON; 有和没有SET NOCOUNT ON;
Function: 功能:
public SaveResult Save(PlanningSaveModel model)
{
using (var db = new RTPContext())
{
try
{
var entity = GetOrCreateEntity(db.Plannings, x => x.Id == model.Id).Item2;
int totalDays = (model.EndDate.Value - model.StartDate.Value).Days + 1;
if (totalDays <= 0)
{
throw new Exception("Дата начала не может быть больше даты окончания");
}
entity.DocumentNumber = model.DocumentNumber;
entity.DocumentEndDate = model.DocumentEndDate.Value;
entity.UnitId = model.UnitId;
entity.UnitMarkId = model.UnitMarkId;
entity.Value = model.Value;
entity.MeasureUnitId = model.MeasureUnitId;
entity.StartDate = model.StartDate.Value;
entity.EndDate = model.EndDate.Value;
entity.CalendarWorkId = model.CalendarWorkId;
//entity.PerDayValue = (int)Math.Round(Decimal.Divide(model.Value, totalDays));
db.SaveChanges();
return new SaveResult(true);
}
catch (Exception ex)
{
var errorMessage = ex.GetBaseException().Message;
return new SaveResult(false, errorMessage);
}
}
}
Model: 模型:
public abstract class PlanningModel
{
[Key]
public long? Id { get; set; }
[Required]
[Display(Name = "Document_Number", ResourceType = typeof(SharedStrings))]
public string DocumentNumber { get; set; }
[Required]
[Display(Name = "Document_End_Date", ResourceType = typeof(SharedStrings))]
public DateTime? DocumentEndDate { get; set; }
[Required]
[Display(Name = "Planning_Value", ResourceType = typeof(SharedStrings))]
public int Value { get; set; }
[Required]
[Display(Name = "Date_Start", ResourceType = typeof(SharedStrings))]
public DateTime? StartDate { get; set; }
[Required]
[Display(Name = "Date_End", ResourceType = typeof(SharedStrings))]
public DateTime? EndDate { get; set; }
}
public class PlanningSaveModel : PlanningModel
{
[Required]
[Display(Name = "Unit_Name", ResourceType = typeof(SharedStrings))]
public long UnitId { get; set; }
[Required]
[Display(Name = "Unit_Mark_Name", ResourceType = typeof(SharedStrings))]
public long UnitMarkId { get; set; }
[Required]
[Display(Name = "Measure_Unit_Name", ResourceType = typeof(SharedStrings))]
public long MeasureUnitId { get; set; }
[Required]
[Display(Name = "Calendar_Work_Name", ResourceType = typeof(SharedStrings))]
public long CalendarWorkId { get; set; }
}
Trigger: 触发:
ALTER TRIGGER [dbo].[CalculatePerDayValue]
ON [dbo].[Planning]
INSTEAD OF INSERT, UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM deleted) BEGIN
UPDATE dbo.Planning
SET DocumentNumber = i.DocumentNumber,
DocumentEndDate = i.DocumentEndDate,
UnitId = i.UnitId,
UnitMarkId = i.UnitMarkId,
MeasureUnitId = i.MeasureUnitId,
[Value] = i.[Value],
StartDate = i.StartDate,
EndDate = i.EndDate,
CalendarWorkId = i.CalendarWorkId,
PerDayValue = dbo.WorkDays(i.StartDate, i.EndDate, i.CalendarWorkId, i.Value),
ModifierId = i.ModifierId,
ModifyDate = i.ModifyDate,
IsDeleted = i.IsDeleted,
HVersion = i.HVersion
FROM inserted i
WHERE dbo.Planning.Id = i.Id
END
ELSE BEGIN
INSERT INTO dbo.Planning
SELECT [DocumentNumber]
,[DocumentEndDate]
,[UnitId]
,[UnitMarkId]
,[MeasureUnitId]
,[Value]
,[StartDate]
,[EndDate]
,[CalendarWorkId]
,dbo.WorkDays(StartDate, EndDate, CalendarWorkId, Value)
,[ModifierId]
,[ModifyDate]
,[IsDeleted]
,[HVersion] FROM inserted
END
END
Scalar function used in trigger: 触发器中使用的标量函数:
ALTER FUNCTION [dbo].[WorkDays]
(
@Start datetime,
@End datetime,
@CalendarId bigint,
@Value int
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE @WorkDays int
-- Add the T-SQL statements to compute the return value here
SELECT @WorkDays = CASE @CalendarId WHEN 1
THEN
(DATEDIFF(dd, @Start, @End) + 1) - (DATEDIFF(wk, @Start, @End) * 2)
- (case when DATEPART(dw, @Start) IN (6, 7) then 1 else 0 end)
- (case when DATEPART(dw, @End) IN (6, 7) then 1 else 0 end)
- (select count(*) from dbo.CalendarHoliday where [Date] between @Start and @End and DATEPART(dw, [Date]) NOT IN (6, 7))
ELSE
(DATEDIFF(dd, @Start, @End) + 1)
- (select count(*) from dbo.CalendarHoliday where [Date] between @Start and @End)
END
-- Return the result of the function
RETURN @Value/@WorkDays
END
I found an answer here: Entity Framework, view and instead of insert trigger. 我在这里找到了答案: 实体框架,而不是插入触发器。 Can't insert a row into the view 无法在视图中插入行
Just added SELECT Id FROM dbo.Planning where @@ROWCOUNT > 0 AND Id = SCOPE_IDENTITY()
into insert statement in the trigger 刚刚在SELECT Id FROM dbo.Planning where @@ROWCOUNT > 0 AND Id = SCOPE_IDENTITY()
添加了SELECT Id FROM dbo.Planning where @@ROWCOUNT > 0 AND Id = SCOPE_IDENTITY()
到触发器的插入语句中
So Trigger looks like that: 所以触发器看起来像这样:
ALTER TRIGGER [dbo].[CalculatePerDayValue]
ON [dbo].[Planning]
INSTEAD OF INSERT, UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM deleted) BEGIN
UPDATE dbo.Planning
SET DocumentNumber = i.DocumentNumber,
DocumentEndDate = i.DocumentEndDate,
UnitId = i.UnitId,
UnitMarkId = i.UnitMarkId,
MeasureUnitId = i.MeasureUnitId,
[Value] = i.[Value],
StartDate = i.StartDate,
EndDate = i.EndDate,
CalendarWorkId = i.CalendarWorkId,
PerDayValue = dbo.WorkDays(i.StartDate, i.EndDate, i.CalendarWorkId, i.Value),
ModifierId = i.ModifierId,
ModifyDate = i.ModifyDate,
IsDeleted = i.IsDeleted,
HVersion = i.HVersion
FROM inserted i
WHERE dbo.Planning.Id = i.Id
END
ELSE BEGIN
INSERT INTO dbo.Planning
SELECT [DocumentNumber]
,[DocumentEndDate]
,[UnitId]
,[UnitMarkId]
,[MeasureUnitId]
,[Value]
,[StartDate]
,[EndDate]
,[CalendarWorkId]
,dbo.WorkDays(StartDate, EndDate, CalendarWorkId, Value)
,[ModifierId]
,[ModifyDate]
,[IsDeleted]
,[HVersion] FROM inserted
-- FOR ENTITY FRAMEWORK CONCURRENCY EXCEPTION HANDLING
SELECT Id FROM dbo.Planning where @@ROWCOUNT > 0 AND Id = SCOPE_IDENTITY()
END
END
I had this error because the table which i tried to insert into in database have no primary key. 我有此错误,因为我尝试插入数据库中的表没有主键。 Added primary key for the table fix this exception for me. 为表添加了主键,为我解决了此异常。 I think you have the same problem because your Planning table have no primary key, that why your data model have these lines: 我认为您有同样的问题,因为您的Planning表没有主键,这就是为什么您的数据模型具有以下几行:
[Key]
public long? Id { get; set; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.