entity-framework - entity framework tutorials




Entity Frameworkのコードファーストプロキシコレクションがnullで、なぜそれを設定できないのですか? (2)

古い質問...

ポコクラス:

public partial class MyPOCO
{
    public MyPOCO()
    {
        this.MyPocoSub = new HashSet<MyPocoSub>();
    }

    //VIRTUAL
    public virtual ICollection<MyPocoSub> MyPocoSub { get; set; }
}

プロキシコード:

    public override ICollection<MyPocoSubSet> MyPocoSubSets
    {
        get
        {
            ICollection<MyPocoSubSet> myPocoSubSets = base.MyPocoSubSets;
            if (!this.ef_proxy_interceptorForMyPocoSubSets(this, myPocoSubSets))
            {
                return base.MyPocoSubSets;
            }
            return myPocoSubSets;
        }
        set
        {
            if (value != this.RelationshipManager.GetRelatedEnd("WindowsFormsApplication.Models.MyPocoSubSet_MyPOCO", "MyPocoSubSet_MyPOCO_Source"))
            {
                // EXCEPTION 
                throw new InvalidOperationException("The property 'MyPocoSubSets' on type 'MyPOCO_A78FCE6C6A890855C68B368B750864E3136B589F9023C7B1D90BF7C83FD291AC' cannot be set because the collection is already set to an EntityCollection.");
            }
            base.MyPocoSubSets = value;
        }
    }

ExtityFramework5のプロキシクラスで例外が発生しているのがわかります。これは、動作がまだ存在することを意味します。

私はDBContextを使用しており、プロパティがすべて仮想である2つのクラスを持っています。 私はコンテキストを照会するときに私がプロキシオブジェクトを取得していることをデバッガで見ることができます。 ただし、コレクションプロパティを追加しようとすると、コレクションプロパティはnullです。 プロキシがコレクションの初期化を確実にすると思った。

私のPocoオブジェクトはデータコンテキストの外で使用できるので、コンストラクタでnullであるコレクションのチェックを追加し、必要に応じて作成しました。

public class DanceStyle
{
    public DanceStyle()
    {
        if (DanceEvents == null)
        {
            DanceEvents = new Collection<DanceEvent>();
        }
    }
    ...
    public virtual ICollection<DanceEvent> DanceEvents { get; set; }
}

それはデータコンテキストの外で動作しますが、クエリを使用してオブジェクトを取得した場合、テストはtrueですが、設定しようとすると次の例外が発生します。 'DanceStyle_B6089AE40D178593955F1328A70EAA3D8F0F01DDE9F9FBD615F60A34F9178B94'のプロパティ 'DanceEvents'コレクションは既にEntityCollectionに設定されています。

私はそれがnullであると私はそれに追加することはできませんが、私はコレクションにそれを設定することができますプロキシが既に設定されていることを確認することができます。 したがって、私はそれを使用することはできません。 よくわかりません。

ここにDanceEventクラスがあります:

public class DanceEvent
{
    public DanceEvent()
    {
        if (DanceStyles == null)
        {
            DanceStyles = new Collection<DanceStyle>();
        }
    }
    ...
    public virtual ICollection<DanceStyle> DanceStyles { get; set; }
}

上記のコードから他のvalue-typeプロパティを省略しました。 私は、コンテキストクラスのそれらのクラスのための他のマッピングを持っていません。


独自の質問に対する回答で正しく観察されているように、コレクションプロパティから「仮想」キーワードを削除すると、Entity Frameworkが変更追跡プロキシを作成しないようにすることで問題を回避できます。 しかし、これは多くの人にとっては解決策ではありません。チェンジ・トラッキング・プロキシは非常に便利で、コード内の適切な場所で変更を検出するのを忘れると問題を防ぐのに役立ちます。

より良いアプローチは、POCOクラスを変更して、コンストラクタではなくgetアクセサでコレクションプロパティをインスタンス化することです。 変更追跡プロキシ作成を許可するように変更されたPOCOクラスは次のとおりです。

public class DanceEvent
{
    private ICollection<DanceStyle> _danceStyles;
    public virtual ICollection<DanceStyle> DanceStyles
    {
        get { return _danceStyles ?? (_danceStyles = new Collection<DanceStyle>()); }
        protected set { _danceStyles = value; }
    }
}

上記のコードでは、コレクションプロパティは自動ではなく、バッキングフィールドを持っています。 setterを保護したままにすると、(プロキシ以外の)コードがこれらのプロパティを後で変更することを防ぐことができます。 コンストラクタはもはや必要なくなり、削除されたことに気づくでしょう。





proxies