0
我有创建/更新实体和“改为插入,更新触发器”的函数。这个错误发生在我创建新的实体时,但更新它的确定并直接在数据库中添加也可以完美地与这个触发器一起工作。实体框架6:DbUpdateConcurrencyException
我使用:
- .NET框架4.5
- 实体框架6.1.3
- MS SQL Server Express的2016
商店更新,插入或删除语句影响了意外的行数(0)。自实体加载后,实体可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=472540。
我已经尝试过:
catch (DbUpdateConcurrencyException ex) { var ctx = ((IObjectContextAdapter)db).ObjectContext; ctx.Refresh(RefreshMode.ClientWins, db.Plannings); db.SaveChanges(); return new SaveResult(true); }
带和不带SET NOCOUNT ON;
功能:
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);
}
}
}
型号:
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; }
}
触发:
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
在触发使用标量函数:
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