【问题标题】:Using linq to update a composite key field使用 linq 更新复合键字段
【发布时间】: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 文件来清理代码。这些方法只是将模型对象传递给它(ZipCodeTerritory model)。
  • 这也是上下文每次使用时都会调用构造函数的原因。我们希望确保我们每次都从头开始,而不是之前的交易。
  • 如果你想从头开始工作,你应该在方法范围内创建上下文并处理它。
  • 对帖子进行了编辑,显示了我尝试使用的方法。不幸的是,这也不起作用。

标签: c# .net asp.net-mvc-3 linq entity-framework


【解决方案1】:

试试这个:

public static void RemoveRecord(ZipCodeTerritory zipCode)
{
    using(var _newdb = new AgentResources())
    {
        ZipCodeTerritory zipCodeRemove = new ZipCodeTerritory();
        zipCodeRemove.channelCode = zipCode.channelCode;
        zipCodeRemove.stateCode = zipCode.stateCode;
        zipCodeRemove.zipCode= zipCode.zipCode;
        zipCodeRemove.endDate = zipCode.endDate;

        _newdb.ZipCodeTerritory.Attach(zipCodeRemove);
        _newdb.ZipCodeTerritory.Remove(zipCodeRemove);
        //((IObjectContextAdapter)_newdb).ObjectContext.Refresh(
                                                    // RefreshMode.ClientWins
                                                    //, zipCode);
        _newdb.SaveChanges();
    }
}

【讨论】:

  • Visual Studio 无法识别 .Refresh 方法或 RefreshMode 枚举(我认为?)。我需要一个命名空间吗?
  • System.Data.Entity 程序集 - msdn.microsoft.com/en-us/library/bb896255.aspx
  • 很奇怪,如果我添加System.Data.Objects,我会得到RefreshMode,但如果我添加System.Data.Entity,则什么也得不到。 $#&%^*@微软......
  • System.Data.Objects 是命名空间。 System.Data.Entity 是框架组件。 .Net 中的 Microsoft 命名并不总是很好,尤其是对于较新的框架类。那么这行得通吗?
  • 不,即使使用System.Data.Entity,我也无法让VS识别.Refresh。我也试过System.Linq,正如MSDN所说,它包含DbContext.Refresh(),但没有运气。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
相关资源
最近更新 更多