EF代码首先,使用代理在集合中创建新对象

时间:2011-08-20 03:42:26

标签: entity-framework-4.1 ef-code-first

如何仅使用导航属性集创建+ persist + has-a-proxy到代码优先poco的新实例?在下面的代码中,我将展示如何使用成员函数创建随后创建POCO的POCO。您没有DbContext,但是如果您创建一个对象并使用DbSet.Add持久化,则返回的对象不是代理,因此您不能再使用其DbSet.Add添加不同的子对象

在此代码中,如果您调用MailingList.AddIncomingMessage(“我的消息”),则会在“OOPS”注释中获得异常,因为创建的msg不是代理,因此其Message.doodads属性为null。

class Doodad {
  public int ID { get; set; }
  public string doodad { get; set; };
}

class Message {
  public int ID { get; set; }
  public virtual MailingList mailingList { get; set; } 
  public virtual ICollection<Doodad> doodads { get; set; }
  public string text { get; set; }

  public void GetDoodadCreateIfNeeded(string doodad) {
    try {
      // won't be found since we just created this Message
      return this.doodads.First(d => d.doodad == doodad);
    } catch (Exception e) {
      Doodad newDoodad = new Doodad() { doodad=doodad };

      // OOPS! this.doodads == null, because its not a proxy object
      this.doodads.Add(newDoodad);
      return newDoodad;
    }
  }
}

class MailingList {
  public int ID { get; set; }
  public virtual ICollection<Message> messages { get; set; }

  public void AddIncomingMessage(string message) {
    var msg = new Message() { text=message };

    // we have no Context, because we're in a POCO's member function
    this.messages.Add(msg);

    var doodad = msg.GetDoodadCreateIfNeeded("bongo drums");
  }
}
编辑:抱歉,伙计们,我忘了将属性访问者和ID放入这个简化的案例中,但我在实际代码中使用它们。

2 个答案:

答案 0 :(得分:2)

它与代理无关。它与任何其他代码相同 - 如果您想使用对象/集合,您必须首先初始化它!你的第一个命令:

return this.doodads.First(d => d.doodad == doodad);

不会抛出异常,因为它没有找到doodad,而是因为doodads为空。

你需要做什么?您需要在首次使用它们之前初始化集合。你可以这样做:

  • 直接在他们的定义中
  • 在实体的构造函数中
  • 在首次需要属性getter(延迟初始化)时 - 这需要将字段更改为btw属性。在.NET中编写类的正确方法
  • 在自定义方法中,您可以检查它们是否为null并初始化它们

答案 1 :(得分:1)

导航属性的补充,您需要具有属于外键ID的属性。

因此,您的MailingList需要具有此属性:

  [Key] // this attribute is important
  public int Id { get; set; }

并且您必须更改Message classe以具有以下属性:

public virtual int mailingListId { get; set; 
public virtual MailingList mailingList { get; set; }

{ get; set; }属性很重要,因此它是属性,而不仅仅是公共属性。