【问题标题】:Entity Framework not tracking List实体框架不跟踪列表
【发布时间】:2020-06-15 10:17:39
【问题描述】:

我在 ASP.Net 中使用 EF6。我正在尝试将项目添加到以下模型中的作业列表:

编辑:

我的目标是通过 PUT 方法保存我对 Timecards.Jobs 列表所做的更改,以便我可以通过 GET 方法检索它们。

public class Timecard
    {
        [Key]
        public long TimecardID { get; set; }
        [Required]
        public DateTime StartDate { get; set; }
        [Required]
        public DateTime EndDate { get; set; }
        [Required]
        public long EmployeesID { get; set; }
        [Required]
        public decimal Hours { get; set; }
        [Required]
        public  ICollection<int> Jobs { get; set; } = new List<int>();

        public List<DateTime> Days { get; set; } = new List<DateTime>();
    }

我相信我正在这样做,我正在检查我的 PUT 方法中的状态变化:


    // PUT: api/TimecardsAPI/5
            [ResponseType(typeof(void))]
            public IHttpActionResult PutTimecard(int id, Job job)
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState);
                }

                try
                {                
                    Timecard card = db.Timecards.Where(x => x.TimecardID == id).First();
                    var state = db.Entry(card).State;                
                    db.Timecards.Attach(card);
                    state = db.Entry(card).State;
                    card.Jobs.Add((int)job.JobID);
                    db.Entry(card).State = EntityState.Modified;
                    state = db.Entry(card).State;
                    var result = db.SaveChanges();
                    state = db.Entry(card).State;
                    var change = db.Timecards.Where(x => x.TimecardID == id).First().Jobs;
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!TimecardExists(id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return StatusCode(HttpStatusCode.NoContent);

            }

在从 put 方法返回之前,我有一个 var 更改,以便在我完成工作后检查 Jobs 列表的结果。在我离开 put 方法之前,对 Jobs 列表的更改是准确的。但是,当我进行获取时,我得到了除列表之外的所有正确数据。它以 0 长度列表的形式返回。这是我的 get 方法,它也有一个变量中的作业列表。这是列表以 0 大小返回的地方:

// GET: api/TimecardsAPI
        public IQueryable<Timecard> GetTimecards()
        {
            var change = db.Timecards.Where(x => x.TimecardID == 6).First().Jobs;
            //In this example, six is the id of the timecard in question. Only hardcoded here
            //for debugging.
            return db.Timecards;
        }

还有我的 dbcontext:



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

            public DbSet<Job> Jobs { get; set; }

            public System.Data.Entity.DbSet<ClockedWeb.Models.PayPeriod> PayPeriods { get; set; }

            public System.Data.Entity.DbSet<ClockedWeb.Models.Employee> Employees { get; set; }

            public System.Data.Entity.DbSet<ClockedWeb.Models.Timecard> Timecards { get; set; }
}

关于 SO 有很多类似的问题,但我还没有找到帮助我解决问题的信息。我不知道我做错了什么,但我已经为此浪费了几天时间,我真的可以使用一些帮助。谢谢。

【问题讨论】:

    标签: asp.net asp.net-mvc entity-framework orm entity-framework-6


    【解决方案1】:

    通常在列中存储多个值表示数据库设计不佳。关系数据库专门设计用于为每个行/列组合存储一个值。为了存储多个值,您必须将列表序列化为单个值进行存储,然后在检索时对其进行反序列化,或者您可以使用多对一关系,然后您应该使用具有外键约束的额外表。在 RDMS 中没有其他方法可以做到这一点。

    如果你使用序列化方法,那么你的模型看起来像--

        public class Timecard
        {
            [Key]
            public long TimecardID { get; set; }
            [Required]
            public DateTime StartDate { get; set; }
            [Required]
            public DateTime EndDate { get; set; }
            [Required]
            public long EmployeesID { get; set; }
            [Required]
            public decimal Hours { get; set; }        
            [NotMapped]
            public  List<int> JobList { get; set; } = new List<int>();
            [Required]
            public string Jobs
            {
                get => string.Join(",", JobList);
                set
                {
                    if (string.IsNullOrEmpty(value)) JobList = new List<int>();
                    else
                    {
                        JobList = !string.IsNullOrWhiteSpace(value) && value.Contains(",")
                            ? value.Split(',').Select(s => Convert.ToInt32(s.Trim())).ToList()
                            : !string.IsNullOrWhiteSpace(value) && !value.Contains(",")
                                ? new List<int>()
                                : new List<int>();
                    }
                }
            }
            //have to change also
            public List<DateTime> Days { get; set; } = new List<DateTime>();//Follow previous technique
        }
    

    然后你可以像你一样做你的操作。只是将数据作为逗号分隔的字符串插入。

    【讨论】:

    • 这有点道理,但你能解释一下 JobList = 实际上在做什么吗?我不确定为什么会这样?新列表:新列表。它不只是返回一个新列表吗?
    • @KellyVM JobList 只是将逗号分隔的字符串值转换为列表(也反转)。因此,当您将列表项(在 JobList 中)转换为逗号分隔的字符串并保存在数据库(作业)中时。当从数据库中获取数据时,您会从(作业)中获取一个列表项。没事吧?
    • 啊,是的!数据终于转移到应用程序了!这是朝着正确方向迈出的一大步,非常感谢您。在接收端,当我尝试使用 var content = await response.Content.ReadAsStringAsync(); 反序列化对象时出现异常List timecards = JsonConvert.DeserializeObject>(content);现在知道如何正确反序列化了吗?
    • 糟糕,序列化问题是一个愚蠢的错误——我不得不更新应用端的模型以匹配 Web 端的模型。我非常感谢你的帮助。
    【解决方案2】:

    我没有正确理解您,但是如果您在更改实体后没有收到更新,那么您可以添加以下行

    db.savechanges();
    

    【讨论】:

    • 我已经在我的 PUT 方法的 try / catch 块中拥有它
    猜你喜欢
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    相关资源
    最近更新 更多