EF4.0 - 将相关对象插入数据库

时间:2012-08-31 16:06:35

标签: wpf entity-framework entity-framework-4 entity-relationship

我正在尝试Entity Framework 4.0,这里是 案例的最简化版本 -

我有以下两个相关表格 -

地址
标识
城市

客户端
标识
AddressId
姓名

我已经在ComboBox中加载了地址。我想要的只是在TextBox中输入客户端名称,从ComboBox中选择一个地址作为客户端的地址并点击保存按钮。我希望我的客户端保存在Client表中。这是我试过的 -

    /*loads Addresses to the ComboBox*/
    private void LoadData()
    {
        using (CAEntities ctx = ModelAccess.GetContext())
            this.AddressList = ctx.Addresses.ToList();
    }

    /*(tries) to insert the Client to the database*/
    private void Save()
    {
        /*here this.Client is the Client object that is instantiated & initialized   
          by previous code and this.Address is the SelectedItem of the ComboBox*/
        this.Client.Address = this.Address;
        using (CAEntities ctx = ModelAccess.GetContext())
        {
            ctx.Clients.AddObject(this.Client);
            ctx.SaveChanges();
        }
    }

朱莉勒曼在Programming Entity Framework表示,...Because the entities are joined, you can add either entity, and it will bring along the rest of the graph...但是我有是一个InvalidOperationException,说“当该属性的当前值是空的的EntityKey属性只能设置。” <无线电通信/> 如果我使用 -

this.Client.AddressId = this.Address.Id;  

而不是 -

this.Client.Address = this.Address;  

客户端完美地插入数据库。但我认为我也应该能够直接将实体联系起来,对吧? 我假设问题与我正在创建的单独上下文有关。所以我尝试了这个 -

    private void Save()
    {
        this.Client.Address = this.Address;
        using (CAEntities ctx = ModelAccess.GetContext())
        {
            ctx.Addresses.Attach(this.Address);
            ctx.SaveChanges();
        }
    }  

但是这次我得到一个InvalidOperationException,它说“具有临时EntityKey值的对象不能附加到对象上下文”。那么我在这里做错了什么呢?提前谢谢。

1 个答案:

答案 0 :(得分:2)

这应解决问题:

    using (CAEntities ctx = ModelAccess.GetContext())
    {
        ctx.Addresses.Attach(this.Address);
        this.Client.Address = this.Address;
        ctx.Clients.AddObject(this.Client);
        ctx.SaveChanges();
    }

为什么这样做?

DbContext会跟踪它被拉下或已明确附加到它的对象。在您的情况下,您将this.Client.Address设置为DbContext不知道的对象。在某些情况下,这将导致实体框架插入一个新的客户端行一个新的地址行,但在您的情况下,由于某些语义细节,我不知道,它提出了一个模糊的异常。

通过将this.Address附加到DbContext,实体框架了解地址已存在于数据库中,并且您在将其分配给this.Client.Address时正在创建与现有对象的关联。

IMO,实体框架的语义需要更好地记录。有很多这样的案例会引发误导或模糊的异常。例如,在附加对象时,请务必记住它们是递归附加的。如果您要在新数据上下文中附加this.Client,它也会以递归方式附加this.Client.Address,并且任何其他实体this.Client都可以引用。出于这个原因,如果您要明确附加this.Client然后this.Address,那么您会收到一个例外,因为当您附加this.Client时,地址已被隐式附加。