2

EF5 で DBContext を使用する - 日付範囲などの基準に基づいてフィルター処理と部分的な読み込みを行った後。

私はオブジェクトの完全なグラフまたはツリーを作成しようとしています-Persons->Events where the only Events that are included are within a date range. これはすべて、次のように取得する標準の変更追跡を維持しながら:

 Dim Repository As Models.personRepository = New Models.personRepository

 Private Sub LoadData()
    Dim personViewModelViewSource As System.Windows.Data.CollectionViewSource = CType(Me.FindResource("personViewModelViewSource"), System.Windows.Data.CollectionViewSource)
    Repository.endDate = EndDate.SelectedDate
    Repository.startDate = StartDate.SelectedDate
    personViewModelViewSource.Source = Repository.collectionOfpersons
 End Sub

リストボックスとデータグリッドはどちらも適切なデータソースとしてバインドされています。POCO テンプレートは、ナビゲーション プロパティ クラス Events に INotifyProperty イベントを配置するように変更されました。

私はこれと何日も戦ってきましたが、遅延読み込みまたは明示的読み込みのどちらでフィルタリングしても機能しません。大量のブログ/チャパーを読んだ後、インクルードに関するかなり非現実的な制限に気づきました。代わりに、明示的な読み込みを試みています。私はDBContextの本を使用しています。

データベースからイベント データのサブセットのみを取得できないことは、100% 取引を妨げるものです。Entity Framework がこの機能をかなり明白にしていないということは、私にも私の上司にも理解できません。

私が試みたパスのいくつかを試して説明するために、コメント付きのコードを残しました。クラス自体は、このメソッドが属するリポジトリです。この質問をさらに編集して、多くのルートがあったため、試したルートの数を明確にします。View はリポジトリ レイヤーと ViewModel を使用するため、XAML 上のコード ビハインドはかなり最小限です。

よろしくお願いします。

 Public Overridable ReadOnly Property AllFiltered(startdate As Date, enddate As Date) As ObservableCollection(Of person) Implements IpersonRepository.AllFiltered
        Get
            Dim uow = New UnitOfWork
            context = uow.Context
            Dim personQuery = context.persons.Include(Function(p) p.events).AsQueryable.Where(Function(x) x.personID = 10).FirstOrDefault


            'Dim eventQuery = From e In context.Notes
            '                 Where e.eventDateTime >= startdate And e.eventDateTime <= enddate
            '                 Select e

            'Dim personQuery As person = From r In context.persons
            '                   From e In eventQuery
            '                   Where r.personID = e.personID
            '                   Select r, e

            Dim singleperson = personQuery

            'For Each r As person In personQuery
            '    persons.Add(r)
            'Next

            '   context.Entry(eventQuery).Collection()
            ' context.Entry(personQuery).Reference(personQuery).Load()

            context.Entry(singleperson).Collection(Function(d) d.events).Query().Where(Function(x) x.eventDateTime > startdate And x.eventDateTime < enddate).Load()

            Return context.persons.Local
        End Get
    End Property

注: コードを汚染するのではなく、PostSharp を介してログ記録/例外処理を使用しています。

以下は、以前のパスで生成したエラーの一部です。

エンティティ タイプ DbQuery`1 は、現在のコンテキストのモデルの一部ではありません。

インクルード パス式は、型で定義されたナビゲーション プロパティを参照する必要があります。参照ナビゲーション プロパティにはドット パスを使用し、コレクション ナビゲーション プロパティには Select 演算子を使用します。

パラメータ名: パス

タイプ 'System.Data.Entity.Infrastructure.DbQuery 1[VB$AnonymousType_02 [Entity.Person,Entity.Notes]]' のオブジェクトをタイプ 'System.Collections.ObjectModel.ObservableCollection`1[Entity.Person]' にキャストできません。

更新:私が試したさらに別のルートでも、これを飛ばすことはできません:

Private Property _collectionOfPersons As ObservableCollection(Of Person)

Public ReadOnly Property collectionOfPersons As ObservableCollection(Of Person)
        Get
            For Each Person In context.Persons
                _collectionOfPersons.Add(ReturnSinglePerson(startDate, endDate, Person.PersonID))
            Next
            Return _collectionOfPersons.Where(Function(x) x.events.Where(Function(e)         e.eventDateTime > startDate And e.eventDateTime < endDate))
        End Get
    End Property

Public Overridable ReadOnly Property SinglePerson(startdate As Date, enddate As Date) As ObservableCollection(Of Person) Implements IPersonRepository.AllFiltered
        Get

            Dim PersonQuery = context.Persons.Include(Function(p) p.events).AsQueryable.Where(Function(x) x.PersonID = 10).Select(Function(x) x).FirstOrDefault

            Dim Person = PersonQuery

            context.Entry(Person).Collection(Function(d) d.events).Query().Where(Function(x) x.eventDateTime > startdate And x.eventDateTime < enddate).Load()

            Return context.Persons.Local
        End Get
End Property

Public Function ReturnSinglePerson(startdate As Date, enddate As Date, id As Integer)

        Dim PersonQuery = context.Persons.Include(Function(p) p.events).AsQueryable.Where(Function(x) x.PersonID = id).Select(Function(x) x).FirstOrDefault
        Dim Person = PersonQuery
        Return Person

End Function

別のショット: Public Overridable ReadOnly Property FilteredPersons(startdate As Date, enddate As Date) As ObservableCollection(Of Person) Implements IPersonRepository.AllFiltered Get context.Persons.Load() Dim DateCriteria = Function(e) e.events.Where(Function( d) d.eventDateTime > startdate および d.eventDateTime < enddate)

            Dim Res = New ObservableCollection(Of Person)
            For Each Person In context.Persons.Local.Select(Function(x) x).Where(DateCriteria)
                Res.Add(Person)
            Next

            Return Res
        End Get
    End Property

与えます:

タイプ 'ObservableCollection(Of DailyNotes)' のパブリック メンバー 'Where' が見つかりません。

リストボックスに重複した名前がたくさん表示されるだけですが、ナビゲーションは実行され、日付基準は機能します。

   <ExceptionAspect>
    Public Overridable ReadOnly Property FilteredPersons(startdate As Date, enddate As Date) As ObservableCollection(Of Person) Implements IPersonRepository.AllFiltered
        Get
            context.Persons.Load()


            Dim test = From r In context.Persons
                    From e In context.Notes
                    Where e.eventDateTime > startdate And e.eventDateTime < enddate
                    Join rr In context.Persons On e.PersonID Equals rr.PersonID
                    Select r, e


            Dim Res = New ObservableCollection(Of Person)
            For Each Person In test
                Res.Add(Person.r)
            Next

            Return Res
        End Get
    End Property

これを試さないでください:)。子プロパティのみを選択するだけです。

    Public ReadOnly Property collectionOfResidents As ObservableCollection(Of resident)
        Get
            For Each resident In context.residents
                _collectionOfResidents.Add(ReturnSingleResident(startDate, endDate, resident.residentID))
            Next
            Return _collectionOfResidents.Select(Function(x) x.events.Where(Function(e) e.eventDateTime > startDate And e.eventDateTime < endDate))
        End Get
    End Property

この質問に私の他の試みを追加することで、他の両方の答えが促され、他の人が最初にこれに取り組むときに入ることができるサークルを見るのに役立つことを願っています!

4

2 に答える 2

1

節を使用してSelect、より細かい制御を行うことができますInclude

このようなもの:

context
  .Persons
  .Where( ... some predicate on Person ... )
  .Select( o => new
    {
      Person = o,
      Events = o.Events.Where( ... some predicate on Event ... )
    }
  )
;

これにより、両方の述語がデータベース サーバーで実行される SQL に変換されます。

于 2012-12-17T14:51:41.193 に答える
0

今夜、匿名型の多くのいじりと誤解の後、私は成功したと思います。ニコラスの答えはVBで行う必要があり、しばらく時間がかかりました-私は以前に匿名型を使用したことがありません。

これは、私のリポジトリ レイヤーで正常に動作するように見えるものです。

               <ExceptionAspect>
    Public Overridable ReadOnly Property FilteredPersons(startdate As Date, enddate As Date) As ObservableCollection(Of Person) Implements IPersonRepository.AllFiltered
        Get
            context.Persons.Load()

            Dim test = context.Persons.Where(Function(r) r.PersonActive).Select(Function(o) New With { _
                 .Person = o, _
                 .events = o.events.Where(Function(e) e.eventDateTime > startdate) _
            })


            Dim PersonList= New ObservableCollection(Of Person)

            For Each t In test
               PersonList.Add(t.person)
            Next

            Return PersonList
        End Get
    End Property

wpf ビューでの重要な更新/保存はそのままです。Nicholas の助けに本当に感謝しています (そして忍耐...re:cartesion 製品)。ありがとうございます。これが他の誰かに役立つことを願っています!

于 2012-12-17T23:58:47.920 に答える