Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf EF4.0-将相关对象插入数据库_Wpf_Entity Framework_Entity Framework 4_Entity Relationship - Fatal编程技术网

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

Wpf EF4.0-将相关对象插入数据库,wpf,entity-framework,entity-framework-4,entity-relationship,Wpf,Entity Framework,Entity Framework 4,Entity Relationship,我正在尝试实体框架4.0,这里是该案例的最简化版本- 我有以下两个相关表格- 地址 Id 城市 客户端 Id 地址ID 名字 我已将地址加载到组合框中。我只想在文本框中输入客户机名称,从组合框中选择一个地址作为客户机地址,然后点击保存按钮。我希望我的客户机保存在客户机表中。这是我试过的- /*loads Addresses to the ComboBox*/ private void LoadData() { using (CAEntities ctx =

我正在尝试实体框架4.0,这里是该案例的最简化版本-

我有以下两个相关表格-

地址
Id
城市

客户端
Id
地址ID
名字

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

    /*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在中说,
…因为
实体被连接,您可以添加任何一个实体,它将带来图形的其余部分…
但我遇到的是一个InvalidOperationException,它说“只有当属性的当前值为null时,才能设置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值的对象不能附加到对象上下文。”那么我在这里做错了什么呢?提前感谢。

这应该可以解决问题:

    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不知道的对象。在某些情况下,这将导致entity framework同时插入一个新的客户端行和一个新的地址行,但在您的情况下,由于一些我不了解的语义细节,它抛出了一个模糊的异常

通过将
this.Address
附加到DbContext,entity framework可以理解该地址已经存在于数据库中,并且在将其分配给
this.Client.Address
时,您正在创建与现有对象的关联


在我看来,实体框架的语义需要更好地文档化。在很多类似的情况下,会抛出一个误导性的或模糊的异常。例如,在附加对象时,重要的是要记住它们是递归附加的。如果要在新的数据上下文中附加
this.Client
,它也会递归地附加
this.Client.Address
,任何其他实体
this.Client
都可能引用。因此,如果要显式附加
this.Client
然后再附加
this.Address
,则会出现异常,因为在附加
this.Client

时,该地址已隐式附加,因为您使用this.Client.Address获取的是组合框中的值,而不是Address对象。它正试图在数据库中创建一个新的地址对象,在创建之前,您无法将其分配给客户端。这就是为什么this.Client.AddressId可以工作的原因。您必须用var address=GetById之类的东西来实例化地址(this.Client.AddressId,然后设置Client.Address=Address。@布赖恩:我知道你的建议是有效的,但我不明白我从组合框中获取的是一个值,而不是一个地址对象。我设置了一个地址对象列表作为它的数据源,并且我将当前的
SelectedItem
作为这个.Address,然后我获取Id&Cit。)y属性。因为它是数据源。组合框保存的是键值对而不是对象。因此,通过将该键值对作为地址对象分配回客户端,您告诉db上下文在db中创建一个新地址,但它必须存在才能保存到客户端。这就是临时实体密钥消息的位置ng from@Brian:我真的没有理解你。我从xaml中设置组合框的
SelectedItem
属性绑定到我的ViewModel中的那个地址。所以每当
SelectedItem
更改时,我不应该得到地址对象吗?
SelectedItem
,正如这里提到的,返回一个
System.object
,你可以强制转换它对于您的自定义对象,我是对的吗?在某种程度上,您是对的,但请记住组合框是什么,它将返回什么,以及您使用它的介质(查看页面)。它只是要从组合框中传回一个键值对。这就是您必须使用的。非常感谢brian,它确实解决了问题:D但您能否详细说明一下,在附加地址之前,我设置
this.Client.Address=this.Address;
时到底出了什么问题。我知道
ObjectServices
会跟踪只有
EntityObject
s是它知道的。在我的例子中,只有Address对象。而且由于客户端对象是在代码中创建的,所以上下文不知道它。但是当我分配
this.Client.Address=this.Address;
时,我不是在创建一个完整的对象图,将实体彼此关联起来吗?然后当我附加了地址对象,上下文是否也应该知道客户端对象,因为它现在与地址对象相关?所以我仍然没有得到
…临时EntityKey值…
异常。无论如何,再次感谢你。我完全同意你的
更好的文档
观点。我看到很多人使用EF但是他们中很少有人知道幕后发生了什么。如果您想查看DbContext如何“查看”实体,请将该实体传递给
dataContext.Entry()
方法并检查其EntityState。如果它是分离的,则DbContext不知道它,即使它最初是由以前的DbContext下拉的。必须通过附加对象告诉DbContext,“嘿,这个对象已经存在于数据库中。”这样在保存更改时,DbContext