1

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

我有以下两个相关的表 -

地址
ID
城市

客户
ID
地址 ID
名称

我已经在 ComboBox 中加载了地址。我想要的只是在文本框中输入客户端名称,从组合框中选择一个地址作为客户端的地址,然后点击保存按钮。我希望将我的客户保存在客户表中。这是我尝试过的 -

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

编程实体框架中的 Julie Lerman说,...Because the entities are joined, you can add either entity, and it will bring along the rest of the graph...但是我所拥有的是一个 InvalidOperationException,它说“EntityKey 属性只能在属性的当前值为 null 时设置。”
如果我使用 -

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 值的对象附加到对象上下文。” 那么我在这里做错了什么?提前致谢。

4

1 回答 1

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.AddressDbContext 不知道的对象。在某些情况下,这将导致实体框架同时插入一个新的客户行一个新的地址行,但在您的情况下,由于一些我不知道的语义细节,它引发了一个模糊的异常。

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

IMO,需要更好地记录实体框架的语义。有很多这样的情况会引发误导性或晦涩的异常。例如,在附加对象时,请务必记住它们是递归附加的。如果您要在新的数据上下文中附加this.Client,它也会递归附加this.Client.Address,并且任何其他实体都this.Client可能引用。出于这个原因,如果你要显式附加this.Client,那么this.Address你会得到一个异常,因为在你附加时地址已经被隐式附加this.Client

于 2012-08-31T18:29:34.543 回答