2017-01-29 6 views
1

エンティティフレームワークを最初に使用してデータベース内の単一の値を更新しようとしています。Entity Frameworkを使用して単一行を更新する - エンティティマッピングを使用する場合

それは次のエラーを投げ

Attaching an entity of type 'WarehouseAPI.Core.DataEntities.Models.TaskDetail' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

これには2つの方法が、あり
[Table("tblTaskDetail")] 
public partial class tblTaskDetail 
{ 
    [Key] 
    public int TaskDetailID { get; set; } 

    public int? ScheduleId { get; set; } 

    [Required] 
    [StringLength(50)] 
    public string RobotID { get; set; } 

    public Guid? SessionID { get; set; } 

    [Required] 
    [StringLength(50)] 
    public string TaskStatus { get; set; } 

    [Column(TypeName = "datetime2")] 
    public DateTime? TaskScheduledOn { get; set; } 

    [StringLength(250)] 
    public string TaskSummary { get; set; } 

    [Column(TypeName = "datetime2")] 
    public DateTime? TaskStartedOnUtc { get; set; } 

    [Column(TypeName = "datetime2")] 
    public DateTime? TaskCompletedOnUtc { get; set; } 
} 

public class TaskDetail 
{ 
    public int TaskDetailID { get; set; } 
    public int? ScheduleId { get; set; } 
    public string RobotID { get; set; } 
    public Guid? SessionID { get; set; } 
    public string TaskStatus { get; set; } 
    public DateTime TaskScheduledOn { get; set; } 
    public string TaskSummary { get; set; } 
    public DateTime TaskStartedOnUtc { get; set; } 
    public DateTime TaskCompletedOnUtc { get; set; } 
} 

public class TaskDetailMapper:EntityTypeConfiguration<TaskDetail> 
{ 
    public TaskDetailMapper() 
    { 
     this.ToTable("tblTaskDetail"); 
     this.HasKey(hk => hk.TaskDetailID); 
     this.Property(o => o.RobotID).HasColumnName("RobotID"); 
     this.Property(o => o.ScheduleId).HasColumnName("ScheduleId"); 
     this.Property(o => o.SessionID).HasColumnName("SessionID"); 
     this.Property(o => o.TaskCompletedOnUtc).HasColumnName("TaskCompletedOnUtc"); 
     this.Property(o => o.TaskDetailID).HasColumnName("TaskDetailID"); 
     this.Property(o => o.TaskScheduledOn).HasColumnName("TaskScheduledOn"); 
     this.Property(o => o.TaskStartedOnUtc).HasColumnName("TaskStartedOnUtc"); 
     this.Property(o => o.TaskStatus).HasColumnName("TaskStatus"); 
     this.Property(o => o.TaskSummary).HasColumnName("TaskSummary"); 
    } 
} 

public partial class WarehouseAPIContext : DbContext 
{ 
    public WarehouseAPIContext() : base("name=WarehouseAPIContext") 
    { 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new TaskDetailMapper()); 
    } 
} 

public class TaskDetailRepository:APIRepository<TaskDetail> 
{ 
    WarehouseAPIContext _context; 

    public TaskDetailRepository(WarehouseAPIContext context):base(context) 
    { 
     _context = context; 
    } 

    public TaskDetail UpdateTaskStartingTime(TaskDetail entity) 
    { 
     try 
     { 
      var taskDetail = new TaskDetail() { TaskStartedOnUtc = entity.TaskStartedOnUtc, TaskStatus = entity.TaskStatus,SessionID = entity.SessionID, TaskDetailID = entity.TaskDetailID }; 

      dbSet.Attach(taskDetail); // THROWS THE ERROR 
      _context.Entry(taskDetail).Property(x => x.TaskStartedOnUtc).IsModified = true; 
      _context.SaveChanges(); 

      return entity; 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 
} 

public class APIRepository<T> where T:class 
{ 
     internal WarehouseAPIContext wContext; 
     internal DbSet<T> dbSet; 

     public APIRepository(WarehouseAPIContext context) 
     { 
      wContext = context; 
      dbSet = context.Set<T>(); 
     } 

     public virtual T Update(T entity) 
     { 
      try 
      { 
       var entry = wContext.Entry(entity); 
       dbSet.Attach(entity); 
       entry.State = EntityState.Modified; 
       wContext.SaveChanges(); 
       return entity; 
      } 
      catch (Exception ex) 
      { 
       //ExceptionHandler.Handle(ex); 
       return null; 
      } 
     } 
} 
+0

このエンティティはコンテキストキャッシュですでに使用できますか?同じコンテキスト内の別の場所にあるデータベースからそのエンティティをロードしていますか?なぜ2つのコンテキストオブジェクト - なぜなら、 'dbSet'と' _context'です。私は '.Entry'を使うと' .Attach'パーツをスキップすることができると思います – Developer

答えて

1

いずれかの最初のロード私は好むあなたがこのエンティティへの変更をコピーして更新し、変更内容を保存するエンティティ、 2番目の方法は、更新したいエンティティを読み込んだ後に添付して戻し、最後にコンテキストの変更を保存することです。

既に添付されているエンティティを追加することはできません。オブジェクトを再度挿入します。

関連する問題