1

私はEntityFramework4.0を試していますが、これがケース最も単純化されたバージョンです-

私は次の2つの関連するテーブルを持っています-

住所
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();
        }
    }

Programming EntityFrameworkのJulieLermanは、次のように述べています。...Because the entities are joined, you can add either entity, and it will bring along the rest of the graph...しかし、私が持っているのは、「EntityKeyプロパティは、プロパティの現在の値がnullの場合にのみ設定できる」というInvalidOperationExceptionです。
使用する場合-

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

しかし今回は、「一時的なEntityKey値を持つオブジェクトをオブジェクトコンテキストにアタッチできません」というInvalidOperationExceptionが発生します。それで、私がここで間違っているのは何ですか?前もって感謝します。

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.AddressDbContextにアタッチすることにより、Entity Frameworkは、アドレスがデータベースに既に存在し、に割り当てるときに既存のオブジェクトとの関連付けを作成していることを認識しますthis.Client.Address

IMO、EntityFrameworkのセマンティクスをより適切に文書化する必要があります。このように、誤解を招くような例外やあいまいな例外がスローされる場合が多くあります。たとえば、オブジェクトをアタッチする場合、オブジェクトは再帰的にアタッチされることに注意することが重要です。新しいデータコンテキストでアタッチthis.Clientする場合は、再帰的にアタッチthis.Client.Addressし、他のエンティティthis.Clientが参照する可能性があります。このため、明示的にアタッチするthis.Clientと、this.Addressアタッチ時にアドレスが暗黙的にアタッチされていたため、例外が発生しますthis.Client

于 2012-08-31T18:29:34.543 に答える