【问题标题】:Remove/Add items from a record's child collection when updating更新时从记录的子集合中删除/添加项目
【发布时间】:2016-05-17 11:26:19
【问题描述】:

我使用实体框架 6 ORM 开发了一个 Web 应用程序。我遇到了一个问题,希望能得到帮助。

假设我的表格中有以下模型:

public class Letter
{
   public int Id {get; set;}

   public string Topic {get; set;}

   public string content {get; set;}

   public List<Destination> Destinations {get; set;}
}

public class Destination 
{
   public int Id {get; set;}

   public string Name {get; set;}
}

在这种方法中,我收到了一封来自客户表格的信。这封信包含一个 Id 并在我的数据库中找到,但它的所有属性以及 导航属性 - 目的地可能已经改变(客户决定将这封信发送到比以前更多或更少的目的地 -列表大小可以更改,但不能更改每个目的地的上下文)。 我根据客户提供的 ID 填写目的地列表。这意味着目的地由上下文跟踪。

public void UpdateLetter(Letter updatedLetter, List<int> destinationsIds)
{
    updatedLetter.Destinations = context.Set<Destination>().Where(x => destinationsIds.Contains(x => x.Id)).ToList();

    context.Set<Letter>().Attach(updatedLetter);

    context.Entry(updatedLetter).State = EntityState.Modified;

    context.SaveChanges();
}

以上代码仅适用于标量属性。为了根据客户提供给我的 ID 更新目的地列表,我应该进行哪些更改?

如何告诉实体框架目的地列表已更改? (可以添加或删除项目)?

我的问题是保存更改时,只有简单的属性正确更新,但列表没有改变

我的意思是更新示例:

假设我的数据库中有这些目的地:

dest1 : Id = 1, Name = "Destination1"
dest2 : Id = 2, Name = "Destination2"
dest3 : Id = 3, Name = "Destination3"
dest4 : Id = 4, Name = "Destination4"


var listBeforeUpdate = new List<Destination>
{
    dest1,
    dest2,
    dest3
}

现在,更新一封信后:

var listAfterUpdate = new List<Destination>
{
    dest1,
    dest3,
    dest4
}

我怎样才能做到这一点? 谢谢

【问题讨论】:

  • 为什么?是因为你自动想发出一封新信吗?变化是一个事件。所以你想创建一个新事件。然后,当发生更改时,List 类将触发事件。您还需要注册一个方法来调用像 UpdateLetter() 来处理事件。
  • 我不关注。客户为自己保存了一封稍后发送的信。然后他决定更改目的地/标题/内容等。由于将状态更改为已修改,所有常规属性都会更新,但我不知道如何相应地设置新目的地
  • 您应该能够更改目标的“名称”属性。目的地是一个 List 对象,因此您需要一个索引 Destinations[0].Name
  • 我猜你还没有完全理解。我不是想改变目的地的内部属性。我想更改信件的目的地。意思是添加另一个目的地或删除目的地。
  • 您要更改以下内容: public List Destinations {get;放;}。该实例是 newLetter,因此您正在更改 newLetter.Destinations[0].Name。目的地是一个 List 对象,可以添加、删除或修改。

标签: c# entity-framework asp.net-web-api entity-framework-6


【解决方案1】:

代码看起来像下面的代码。在这种情况下,只需将所有目的地替换为数据库中的结果即可。我假设对数据库的查询将填充数据表。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication93
{
    class Program
    {
        static void Main(string[] args)
        {
            Letter newLetter = new Letter();

            DataTable dt = new DataTable();
            dt.Columns.Add("Id", typeof(int));
            dt.Columns.Add("Name", typeof(string));

            dt.Rows.Add(new object[] {1,"Destination1"});
            dt.Rows.Add(new object[] {2,"Destination2"});
            dt.Rows.Add(new object[] {3,"Destination3"});
            dt.Rows.Add(new object[] {4,"Destination4"});

            newLetter.Destinations = dt.AsEnumerable().Select(x => new Destination()
            {
                Id = x.Field<int>("Id"),
                Name = x.Field<string>("Name")
            }).ToList();
        }
    }
    public class Letter
    {
        public int Id { get; set; }

        public string Topic { get; set; }

        public string content { get; set; }

        public List<Destination> Destinations { get; set; }
    }

    public class Destination
    {
        public int Id { get; set; }

        public string Name { get; set; }
    }

}

【讨论】:

  • 我不太明白它是如何关联的。我正在使用实体框架 6
  • 你是如何查询数据库的?结果是否使用 DataAdapter? DataAdapter 具有创建 DataTable 的填充方法。因此,我将您的示例查询结果放入数据表中,使其看起来与 DataAdapter 的结果完全相同,然后将目的地添加到您的 Letter。
  • 我正在使用 LINQ,希望我能坚持下去
  • 我也在使用 linq:dt.AsEnumerable() 其中 dt 是从数据库查询返回的数据表。
猜你喜欢
  • 1970-01-01
  • 2012-09-05
  • 2010-11-02
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多