使用实体框架更新单行 - 使用实体映射时

时间:2017-01-29 23:36:23

标签: c# asp.net entity-framework

我尝试使用Entity Framework代码优先更新数据库中的单个值。

它引发了以下错误:

  

附加类型的实体   ' WarehouseAPI.Core.DataEntities.Models.TaskDetail'失败是因为   另一个相同类型的实体已经拥有相同的主键   值。使用'附加'方法或设置   一个实体的状态为“未变”'或者'修改'如果有任何实体   图表具有冲突的键值。这可能是因为某些实体   是新的,尚未收到数据库生成的键值。在   这种情况使用'添加'方法或“添加”#39;实体状态跟踪   图表然后将非新实体的状态设置为“未更改”。要么   '变形'酌情。

[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;
            }
        }
}

1 个答案:

答案 0 :(得分:1)

有两种方法可以执行此操作,首先加载要更新的实体,将更改复制到此实体并保存更改,我更喜欢,第二个选项是加载要更新的实体,然后de attach它,并将其附加回来,最后保存上下文更改。

您无法附加已经附加的实体,EF会再次插入该对象