1

POCO オブジェクトの単一のプロパティの値を設定しようとしていますが、POCO オブジェクトが最初に取得されたデータベース テーブル内のすべてのレコードをエンティティが取得しているように見えます。コードは次のとおりです。

public void DeleteFile(int fileid)
{
    var context = GetContext(myTrans, false);
    FILE pocofile = (from f in context.FILES.All()
                     where f.File_Id == fileId
                     select f).FirstOrDefault();

    // the following line causes a retrieve of 60,000 records
    pocofile.State_Id = Global.DeletedStateId // global constant

    // additional code that is eventually reached after about 10 minutes
}

テーブルにマップされた列を持つFILESテーブルがあります。したがって、上記の State_Id プロパティを設定しようとすると、最初のファイルが正常に設定されているように見えますが、poco クラスでヒットしているブレークポイントから判断すると、データベース内のすべてのファイルに対して取得を行っているように見えます。はじまり。State_IdSTATEFILEState_Id

FILE.cs クラスも参照用に以下に貼り付けます。基本的に、60,000 の長いループで多くのゲッターとセッターにヒットしています。任意の時点でそれらの 1 つにブレークポイントを設定し、デバッガーで File_Id をチェックすると、毎回新しい File_Id が取得されます。それらすべてをループしていることを知っています。

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;    

namespace FORTRESSPOCO
{
    public partial class FILE
    {
        #region Primitive Properties

        public virtual int File_Id
        {
            get;
            set;
        }

        public virtual string Name
        {
            get;
            set;
        }

        public virtual string Description
        {
            get;
            set;
        }

        public virtual Nullable<System.DateTime> Expiration_Date
        {
            get;
            set;
        }

        public virtual bool Is_Directory
        {
            get;
            set;
        }

        public virtual string Path
        {
            get;
            set;
        }

        public virtual int Data_Asset_Id
        {
            get { return _data_Asset_Id; }
            set
            {
                if (_data_Asset_Id != value)
                {
                    if (Data_Asset != null && Data_Asset.Data_Asset_ID != value)
                    {
                        Data_Asset = null;
                    }
                    _data_Asset_Id = value;
                }
            }
        }
        private int _data_Asset_Id;

        public virtual int State_Id
        {
            get { return _state_Id; }
            set
            {
                if (_state_Id != value)
                {
                    if (STATE != null && STATE.State_Id != value)
                    {
                        STATE = null;
                    }
                    _state_Id = value;
                }
            }
        }
        private int _state_Id;

        #endregion
        #region Navigation Properties

        public virtual Data_Asset Data_Asset
        {
            get { return _data_Asset; }
            set
            {
                if (!ReferenceEquals(_data_Asset, value))
                {
                    var previousValue = _data_Asset;
                    _data_Asset = value;
                    FixupData_Asset(previousValue);
                }
            }
        }
        private Data_Asset _data_Asset;

        public virtual ICollection<File_DateTime_Attribute> File_DateTime_Attribute
        {
            get
            {
                if (_file_DateTime_Attribute == null)
                {
                    var newCollection = new FixupCollection<File_DateTime_Attribute>();
                    newCollection.CollectionChanged += FixupFile_DateTime_Attribute;
                    _file_DateTime_Attribute = newCollection;
                }
                return _file_DateTime_Attribute;
            }
            set
            {
                if (!ReferenceEquals(_file_DateTime_Attribute, value))
                {
                    var previousValue = _file_DateTime_Attribute as FixupCollection<File_DateTime_Attribute>;
                    if (previousValue != null)
                    {
                        previousValue.CollectionChanged -= FixupFile_DateTime_Attribute;
                    }
                    _file_DateTime_Attribute = value;
                    var newValue = value as FixupCollection<File_DateTime_Attribute>;
                    if (newValue != null)
                    {
                        newValue.CollectionChanged += FixupFile_DateTime_Attribute;
                    }
                }
            }
        }
        private ICollection<File_DateTime_Attribute> _file_DateTime_Attribute;

        public virtual ICollection<File_Int_Attribute> File_Int_Attribute
        {
            get
            {
                if (_file_Int_Attribute == null)
                {
                    var newCollection = new FixupCollection<File_Int_Attribute>();
                    newCollection.CollectionChanged += FixupFile_Int_Attribute;
                    _file_Int_Attribute = newCollection;
                }
                return _file_Int_Attribute;
            }
            set
            {
                if (!ReferenceEquals(_file_Int_Attribute, value))
                {
                    var previousValue = _file_Int_Attribute as FixupCollection<File_Int_Attribute>;
                    if (previousValue != null)
                    {
                        previousValue.CollectionChanged -= FixupFile_Int_Attribute;
                    }
                    _file_Int_Attribute = value;
                    var newValue = value as FixupCollection<File_Int_Attribute>;
                    if (newValue != null)
                    {
                        newValue.CollectionChanged += FixupFile_Int_Attribute;
                    }
                }
            }
        }
        private ICollection<File_Int_Attribute> _file_Int_Attribute;

        public virtual ICollection<File_String_Attribute> File_String_Attribute
        {
            get
            {
                if (_file_String_Attribute == null)
                {
                    var newCollection = new FixupCollection<File_String_Attribute>();
                    newCollection.CollectionChanged += FixupFile_String_Attribute;
                    _file_String_Attribute = newCollection;
                }
                return _file_String_Attribute;
            }
            set
            {
                if (!ReferenceEquals(_file_String_Attribute, value))
                {
                    var previousValue = _file_String_Attribute as FixupCollection<File_String_Attribute>;
                    if (previousValue != null)
                    {
                        previousValue.CollectionChanged -= FixupFile_String_Attribute;
                    }
                    _file_String_Attribute = value;
                    var newValue = value as FixupCollection<File_String_Attribute>;
                    if (newValue != null)
                    {
                        newValue.CollectionChanged += FixupFile_String_Attribute;
                    }
                }
            }
        }
        private ICollection<File_String_Attribute> _file_String_Attribute;

        public virtual STATE STATE
        {
            get { return _sTATE; }
            set
            {
                if (!ReferenceEquals(_sTATE, value))
                {
                    var previousValue = _sTATE;
                    _sTATE = value;
                    FixupSTATE(previousValue);
                }
            }
        }
        private STATE _sTATE;

        #endregion
        #region Association Fixup

        private void FixupData_Asset(Data_Asset previousValue)
        {
            if (previousValue != null && previousValue.FILES.Contains(this))
            {
                previousValue.FILES.Remove(this);
            }

            if (Data_Asset != null)
            {
                if (!Data_Asset.FILES.Contains(this))
                {
                    Data_Asset.FILES.Add(this);
                }
                if (Data_Asset_Id != Data_Asset.Data_Asset_ID)
                {
                    Data_Asset_Id = Data_Asset.Data_Asset_ID;
                }
            }
        }

        private void FixupSTATE(STATE previousValue)
        {
            if (previousValue != null && previousValue.FILES.Contains(this))
            {
                previousValue.FILES.Remove(this);
            }

            if (STATE != null)
            {
                if (!STATE.FILES.Contains(this))
                {
                    STATE.FILES.Add(this);
                }
                if (State_Id != STATE.State_Id)
                {
                    State_Id = STATE.State_Id;
                }
            }
        }

        private void FixupFile_DateTime_Attribute(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (File_DateTime_Attribute item in e.NewItems)
                {
                    item.FILE = this;
                }
            }

            if (e.OldItems != null)
            {
                foreach (File_DateTime_Attribute item in e.OldItems)
                {
                    if (ReferenceEquals(item.FILE, this))
                    {
                        item.FILE = null;
                    }
                }
            }
        }

        private void FixupFile_Int_Attribute(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (File_Int_Attribute item in e.NewItems)
                {
                    item.FILE = this;
                }
            }

            if (e.OldItems != null)
            {
                foreach (File_Int_Attribute item in e.OldItems)
                {
                    if (ReferenceEquals(item.FILE, this))
                    {
                        item.FILE = null;
                    }
                }
            }
        }

        private void FixupFile_String_Attribute(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (File_String_Attribute item in e.NewItems)
                {
                    item.FILE = this;
                }
            }

            if (e.OldItems != null)
            {
                foreach (File_String_Attribute item in e.OldItems)
                {
                    if (ReferenceEquals(item.FILE, this))
                    {
                        item.FILE = null;
                    }
                }
            }
        }

        #endregion
    }
}

この動作に論理的な理由はありますか? ありがとう。

4

1 に答える 1

1

はい、この動作には論理的な理由があります。しかし、それは私の意見ではあなたのせいではなく、EF 4.0POCOT4テンプレートのせいです。問題は、これらの自動生成Fixup...されたメソッドと遅延読み込みの組み合わせです。

次のことが起こります。

  • FKプロパティを設定します。

    pocofile.State_Id = Global.DeletedStateId;
    
  • State_Idセッターを呼び出します。

    if (_state_Id != value)
    {
        if (STATE != null && STATE.State_Id != value)
        {
            STATE = null;
        }
        _state_Id = value;
    }
    
  • 最初のif条件は、ロードされたエンティティがすでに持っているtrueのと同じ値を設定しない限りです(FKの変更なし)。FK2番目のif条件はtrue、遅延読み込みによってSTATE式のデータベースからが読み込まれ、関係がnull許容されない(である)STATE != nullため、データベースのが読み込まれSTATEないためです。に等しくない場合は、等しくすることはできません。DBのFK制約に違反します。だから、実行されます。言い換えると、ナビゲーションプロパティのセッターは次のように呼び出されます。nullState_IdintSTATE.State_Idvalue_state_IdvalueSTATE = nullSTATE

    if (!ReferenceEquals(_sTATE, value))
    {
        var previousValue = _sTATE;
        _sTATE = value;
        FixupSTATE(previousValue);
    }
    
  • if条件は、ではなく(以前にDBからロードされたばかりである)、であるtrueためです。したがって、次ではないパラメータで呼び出されます:_STATEnullvaluenullFixupSTATEpreviousValuenull

    if (previousValue != null && previousValue.FILES.Contains(this))
        //...
    
  • これで、遅延読み込みが有効になっている場合(デフォルトで有効になっている場合)、previousValue.FILESコレクションにアクセスすると、遅延読み込みが開始され、データベースクエリが発行さpreviousValue.FILESれ、データベースからコレクション全体が読み込まれます。この場合、60000個のエンティティが含まれているようです。

この問題の解決策は、遅延読み込みを無効にすることです。

var context = GetContext(myTrans, false);
context.ContextOptions.LazyLoadingEnabled = false;

//...

または、Fixupコードが作成されないようにT4テンプレートを変更します(正しく取得するのが難しい場合があります)。または、EF4.0用に変更されたT4テンプレートがすでに存在している可能性があります。または、EF> = 4.1にアップグレードします。これはDbContext、のPOCOテンプレートにDbContextこの追加コードがないためです。生成されたPOCOクラスは、はるかに単純です。

于 2012-12-06T20:36:28.260 に答える