保存多对多关系 - 实体框架

use*_*746 5 entity-framework

我有以下课程:

    public class item
    {
        public int NodeID
        {
            get ;
            set ;
        }
        public int Weight
        {
            get ;
            set ;
        }
        public int Category
        {
            get ;
            set ;
        }
    }
   public class Recipients
    {
        public int RecipientID
        {
            get ; set;
        }
    }

    public class Nodes
    {
        public List<int> RecipientList
        {
            get ;
            set ;
        }
        public item Item
        {
            get ; set;
        }
        public int Capacity
        {
            get ; set;
        }
        public int NodeID
        {
            get ; set;
        }
        public int Weight
        {
            get ; set;
        }
        public int Category
        {
            get ; set;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我尝试将其保存在具有以下表格的现有数据库中:

1) Category
2) Items
3) Nodes (Node and Items has 1-1 relationship)
4) Recipients
5) NodeRecipients (This table show the many to many relationship between Nodes and Recipients)
Run Code Online (Sandbox Code Playgroud)

我使用VS2012创建EF模型,如下图所示(请注意,节点源自EF中的项目)

在此输入图像描述

我有一个方法,试图保存节点及其收件人

   public void SaveNodeAndRecipient(List<Nodes> MyNodes)
    {
        using (var db = new MyEntities())
        {
            foreach (var n in MyNodes)
            {
                Node n1 = new Node() { NodeID = n.NodeID, categoryID = n.Category, Capacity = n.Capacity };
                db.Items.Add(n1);
                foreach (var r in n.RecipientList)
                {
                    Recipient rep;
                    if (!db.Recipients.Select(x => x.recipientID).Contains(r))
                    {
                        rep = new Recipient() { recipientID = r };
                        db.Recipients.Add(rep);
                    }
                    else
                    {
                        rep = db.Recipients.Where(x => x.recipientID == r).FirstOrDefault();
                    }
                    Node_Recipient nr = new Node_Recipient(){RecipientID=r,NodeID=n.NodeID};
                    n1.Node_Recipient.Add(nr);
                }
            }
            db.SaveChanges();
        }
   }
Run Code Online (Sandbox Code Playgroud)

MyEntities是EF模型,并在appconfig中声明:

  <connectionStrings>
    <add name="MyEntities" connectionString="xxxxx" providerName="System.Data.EntityClient" />
  </connectionStrings>
Run Code Online (Sandbox Code Playgroud)

一切都很好,编译没有问题,直到我试图保存更改.我收到了这个错误(不是很具描述性)

在此输入图像描述

谁知道发生了什么事?我的印象是,多对多关系是罪魁祸首,但无法确定导致它的原因.请帮忙!

Ger*_*old 3

问题是您正在设置Node_Recipient.recipientID值,但从您的描述来看,我很确定这些主键值是由数据库生成的。因此,不保证r保存对象时值 ( ) 会存在。

更糟糕的是 - 新的值甚至不太可能Recipients保留指定的r值,因此您可能会创建错误的关联。

这应该对你有用。请参阅下面的一些评论。

foreach (var n in MyNodes)
{
    Node n1 = new Node  { 
                          NodeID = n.NodeID,
                          categoryID = n.Category,
                          Capacity = n.Capacity
                        };
    foreach (var r in n.RecipientList)
    {
        Recipient rep = db.Recipients.Find(r);
        if (rep == null)
        {
            rep = new Recipient(); // see comment 1.
        }
        Node_Recipient nr = new Node_Recipient { 
                                                 Recipient = rep,
                                                 Node = n1
                                                 // See comment 2
                                               };
        n1.Node_Recipient.Add(nr);
    }
    db.Items.Add(n1); // see comment 3
}
Run Code Online (Sandbox Code Playgroud)
  1. 这里没有recipientId设置。

  2. 您可以在此处设置引用而不是值ID。EF 将在保存更改时“及时”分配正确的外键值。

  3. 这会将对象图中的所有对象标记为 new 下的对象NodeAdded除非它们已经为上下文所知,这对于您Recipients通过 找到的对象来说是正确的db.Recipients.Find(r)

对于多对多关联,该表Node_Recipient看起来像一个纯粹的联结表,即只有两个外键的表。EF 没有生成具有透明 m:n 关联且没有Node_Recipient实体的模型,肯定是有原因的。通常情况下它会这样做。当您生成模型时,是否Node_Recipient包含您后来删除的其他列?

如果您想要这种 m:n 关联,您可能需要尝试重新生成模型。这应该生成一个Nodes带有集合的类Recipients和一个Recipient带有Nodes集合的类。设置关联就是向 中添加新收件人的问题Node.Recipients