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

时间:2013-12-17 19:38:00

标签: 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;
        }
    }

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

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)

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

enter image description here

我有一种尝试保存节点及其收件人的方法

   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();
        }
   }

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

  <connectionStrings>
    <add name="MyEntities" connectionString="xxxxx" providerName="System.Data.EntityClient" />
  </connectionStrings>

在我尝试保存更改之前,一切都很好并且编译没有问题。我收到了这个错误(不是很具描述性)

enter image description here

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

2 个答案:

答案 0 :(得分: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
}
  1. 此处未设置recipientId

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

  3. 这会将新Node下的对象图中的所有对象标记为Added,除非他们已经了解了上下文,这对于您找到的Recipients是正确的db.Recipients.Find(r)

  4. 对于多对多关联,表Node_Recipient看起来像纯粹的联结表,即只有两个外键的表。必须有一个原因,为什么EF没有生成具有透明m:n关联的模型,没有Node_Recipient实体。通常它会这样做。生成模型时,Node_Recipient是否包含您稍后删除的其他列?

    如果您想要此m:n关联,您可能需要尝试重新生成模型。这应该会生成Nodes类,其中Recipients集合和Recipient集合Nodes。然后,设置关联就是将新收件人添加到Node.Recipients

答案 1 :(得分:0)

只是查看你的代码,没有异常细节,我想知道在将n1添加到数据库之前是否需要对Node n1 = new Node() { NodeID = n.NodeID, categoryID = n.Category, Capacity = n.Capacity }; foreach (var r in n.RecipientList) { if (db.Recipients.Where(x => x.recipientID == r).FirstOrDefault() == null) { Recipient rep = new Recipient() { recipientID = r }; db.Recipients.Add(rep); } Node_Recipient nr = new Node_Recipient(){RecipientID=r,NodeID=n.NodeID}; n1.Node_Recipient.Add(nr); } db.Items.Add(n1); // add here, after modifications to n1 进行修改:

{{1}}