【问题标题】:Entity Framework Code First table relationships实体框架代码优先表关系
【发布时间】:2017-07-05 05:00:46
【问题描述】:

我有一个 C# 应用程序,它连接到一个 Web API,它为我的应用程序提供一些用于房地产代理列表和代理的 XML 数据。

XML 看起来是这样的:

<Snapshot>
      <Agents>
        <Agent id="838388" firstName="John" surname="Smith"/>
        <Agent id="838389" firstName="Jane" surname="Doe"/>
        <Agent id="838390" firstName="Mary" surname="Appleton"/>
        <Agent id="838391" firstName="Peter" surname="Gill"/>
      </Agents>

      <Listings>
        <Listing id="1737672" officeId="801948" agencyName="Century 21">
          <Agents>
            <AgentRef id="838388" />
            <AgentRef id="838391" />
          </Agents>
        </Listing>

        <Listing id="1737673" officeId="801949" agencyName="Remax">
          <Agents>
            <AgentRef id="838390" />
            <AgentRef id="838389" />
          </Agents>
        </Listing>
      </Listings>
    </Snapshot>

我决定使用 Entity Framework 6.2,代码优先的方法。所以我创建了这两个类:

public class Agent
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int AgentId { get; set; }
        public string FirstName { get; set; }
        public string Surname { get; set; }
        public virtual ICollection<Listing> Listings { get; set; }
    }

public class Listing
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int ListingId { get; set; }
        public int OfficeId { get; set; }
        public int AgencyName { get; set; }
        public virtual ICollection<Agent> Agents { get; set; }
    }

如您所见,代理和列表之间是多对多的关系。因此,一个代理可以有零个或多个与其关联的列表,而一个列表可以有零个或多个与其关联的代理。

所以,我的应用程序读取第一个标签中的所有代理,并将所有代理插入到代理表中。然后,稍后,当它读取所有列表时,看起来 EF 正在尝试再次创建这些代理。显然,这会导致 PRIMARY KEY 违规错误,因为它试图再次添加具有相同 ID 的第二个代理。

我正在使用 XDocument 来解析 XML。这是我阅读清单的 AgentRef 元素的地方:

XElement root =  xDoc.Root.Elements("Listings").Descendants("Listing");
if (root.Descendants("Agents").Any())
{
    List<string> agentRefs = root.Element("Agents").Elements("AgentRef")
    .Select(a => a.Attribute("id").Value).ToList();
    listing.AgentRefs = agentRefs.Select(int.Parse).ToList();
}

有什么想法可以解决这个问题吗?

【问题讨论】:

  • 请包含处理列表的相关代码。还要指定是否使用同一个 DbContext 实例来插入代理和列表。
  • 感谢伊万的回复。我只使用一个 DbContext。基本上,我的 XML 解析例程返回一个“快照”类,其中包含一组代理和一组清单。然后我遍历 Agents 和 Listings 集合,将每个项目添加到 dbContext,最后我调用 dbContext.SaveChanges();
  • 在上面的清单类中,我很想替换: public virtual ICollection Agents { get;放; }public virtual ICollection AgentRefs { get;放; } 以更好地反映 XML。但这不会创建 EF 正确完成工作和创建 Listings-Agents 桥接表所需的导航属性,对吗?
  • 我也在这里发布过——也许我解释得更好一些? social.msdn.microsoft.com/Forums/en-US/…
  • 不,实体模型没问题,只是最有可能应用更改的代码(未显示)不正确。

标签: c# .net entity-framework database-design entity-framework-6


【解决方案1】:

如果代理已经存在于数据库中,您必须 EF 通过将代理附加到上下文来告知:

using(var myContext = new MyContext)
{
   var agent = new Agent() { AgentId = 838388 };
   myContext.Agents.Attach(agent);

   var listing = new Listing() { ... };
   listing.Agents.Add(agent);

   myContext.Listings.AddObject(listing);

   myContext.SaveChanges();
}

【讨论】:

  • 谢谢杜伊。我现在明白了:) 附加“代理”类型的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后将非新实体的状态设置为“未更改”或“已修改”。
  • 我也把它贴在这里...也许我解释得更好一些? social.msdn.microsoft.com/Forums/en-US/…
猜你喜欢
  • 1970-01-01
  • 2012-10-11
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
相关资源
最近更新 更多