【发布时间】:2013-10-30 21:22:33
【问题描述】:
在我们的 SQL 数据库中,我们有一个带有复合键的表,其中包含我们需要不时更新的字段。据我了解,由于我们使用的是实体框架,因此我需要先从数据库中删除记录,然后再将行添加回表中。
以下是我创建的用于处理“更新”的简单方法,因为有许多方法可以执行此操作。但是,一旦在.Remove 之后调用.SaveChanges() 方法,我就会得到DbUpdateConcurrencyException:
Store update, insert, or delete statement affected an unexpected number of
rows (0). Entities may have been modified or deleted since entities were loaded.
Refresh ObjectStateManager entries.
不确定我做错了什么,因为我正在尝试删除记录,然后执行更新,然后重新添加记录。
这是调用删除/编辑方法的方法。调用此方法时,记录尚未以任何方式更改形状或形式。
private static void ProcessAllChanges(ZipCodeIndex information, ZipCodeTerritory zipToUpdate)
{
try
{
RemoveRecord(zipToUpdate);
if (!string.IsNullOrWhiteSpace(information.newTerritory)) zipToUpdate.IndDistrnId = information.newTerritory;
if (!string.IsNullOrWhiteSpace(information.newStateCode)) zipToUpdate.StateCode = information.newStateCode;
if (!string.IsNullOrWhiteSpace(information.newDescription)) zipToUpdate.DrmTerrDesc = information.newDescription;
if (!string.IsNullOrWhiteSpace(information.newChannelCode)) zipToUpdate.ChannelCode = information.newChannelCode;
if (zipToUpdate.EndDate == DateTime.MinValue) zipToUpdate.EndDate = DateTime.MaxValue;
EditRecord(zipToUpdate);
_updated++;
}
catch (DbEntityValidationException dbEx)
{
_msg += "Error during update; ";
EventLog.WriteEntry("Monet", "Error during ProcessAllChanges: " + zipToUpdate.ToString() + " |EX| " + dbEx.Message);
}
catch (Exception ex)
{
_msg += "Error during update; ";
EventLog.WriteEntry("Monet", "Error during ProcessAllChanges: " + zipToUpdate.ToString() + " |MESSAGE| " + ex.Message);
}
}
这里有两个被调用的辅助方法
public static void RemoveRecord(ZipCodeTerritory zipCode)
{
_db = new AgentResources();
_db.ZipCodeTerritory.Attach(zipCode);
_db.ZipCodeTerritory.Remove(zipCode);
_db.SaveChanges();
}
public static void EditRecord(ZipCodeTerritory zipCode)
{
_db = new AgentResources();
_db.ZipCodeTerritory.Add(zipCode);
_db.SaveChanges();
}
编辑
基于下面的几个 cmets,我尝试创建上下文对象的单独实例,但是使用此方法我收到了相同的错误:
public static void RemoveRecord(ZipCodeTerritory zipCode)
{
using (AgentResources deleteMe = new AgentResources())
{
deleteMe.ZipCodeTerritory.Attach(zipCode);
deleteMe.ZipCodeTerritory.Remove(zipCode);
deleteMe.SaveChanges();
}
}
二次编辑
这是调用我在上面发布的ProcessAllChanges 方法的最上面的方法。
public static string TerritoryOnly(ZipCodeIndex updateZip)
{
if (!string.IsNullOrWhiteSpace(updateZip.newEffectiveDate) || !string.IsNullOrWhiteSpace(updateZip.newEndDate))
{
return "Neither effective or end date can be present if updating Territory Code only; ";
}
RefreshProperties();
foreach (var zipCode in updateZip.displayForPaging.Where(x => x.Update))
{
ProcessAllChanges(updateZip, zipCode);
}
_msg += _updated + " record(s) updated; ";
return _msg;
}
第三次修改
这里的每个请求是 AgentResources 的完整类定义,我们的 DbContext 对象
namespace Monet.Models
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class AgentResources : DbContext
{
public AgentResources()
: base("name=AgentResources")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<AgentContEd> AgentContEd { get; set; }
public DbSet<ContEdCourse> ContEdCourse { get; set; }
public DbSet<Course> Course { get; set; }
public DbSet<CourseToProduct> CourseToProduct { get; set; }
public DbSet<Product> Product { get; set; }
public DbSet<ProcessControl> ProcessControl { get; set; }
public DbSet<AgentIdToTradingPartner> AgentIdToTradingPartner { get; set; }
public DbSet<TradingPartner> TradingPartner { get; set; }
public DbSet<Notes> Notes { get; set; }
public DbSet<CourseMaterials> CourseMaterials { get; set; }
public DbSet<TransactionLog> TransactionLog { get; set; }
public DbSet<Agent> Agent { get; set; }
public DbSet<AgentIdentification> AgentIdentification { get; set; }
public DbSet<BatchDashboard> BatchDashboard { get; set; }
public DbSet<BatchPrograms> BatchPrograms { get; set; }
public DbSet<FollowUpItems> FollowUpItems { get; set; }
public DbSet<sysdiagrams> sysdiagrams { get; set; }
public DbSet<AgentProductTraining> AgentProductTraining { get; set; }
public DbSet<Channel> Channel { get; set; }
public DbSet<RelationshipCodes> RelationshipCodes { get; set; }
public DbSet<DropDownValues> DropDownValues { get; set; }
public DbSet<QueueUpdates> QueueUpdates { get; set; }
public DbSet<MarketingLookup> MarketingLookup { get; set; }
public DbSet<TransmissionHistory> TransmissionHistory { get; set; }
public DbSet<AgentTransmission> AgentTransmission { get; set; }
public DbSet<ZipCodeTerritory> ZipCodeTerritory { get; set; }
}
}
这是ZipCodeTerritory 类
public partial class ZipCodeTerritory
{
public string ChannelCode { get; set; } //Composite key field
public string DrmTerrDesc { get; set; }
public string IndDistrnId { get; set; }
public string StateCode { get; set; } //Composite key field
public string ZipCode { get; set; } //Composite key field
public System.DateTime? DisplayEndDate { get; set; }
public System.DateTime EndDate { get; set; } //Composite key field
public System.DateTime EffectiveDate { get; set; }
public string LastUpdateId { get; set; }
public Nullable<System.DateTime> LastUpdateDate { get; set; }
}
【问题讨论】:
-
看起来你正在打开你的上下文
_db,但是每次都在你的帮助方法中调用构造函数_db = new AgentResources();你为什么这样做?很难说,因为您遗漏了大部分代码。你所展示的一切都是在同一个班级里吗?为什么方法是static? -
这些方法是静态的,因为它们是公共助手类的一部分。网页上可能会发生许多更新,因此我们决定使用单独的 .cs 文件来清理代码。这些方法只是将模型对象传递给它(
ZipCodeTerritorymodel)。 -
这也是上下文每次使用时都会调用构造函数的原因。我们希望确保我们每次都从头开始,而不是之前的交易。
-
如果你想从头开始工作,你应该在方法范围内创建上下文并处理它。
-
对帖子进行了编辑,显示了我尝试使用的方法。不幸的是,这也不起作用。
标签: c# .net asp.net-mvc-3 linq entity-framework