2

私は3つのテーブルを持っています:

  • USERS_TABLE(ユーザーID、名前)
  • ACTIVITY_HISTORY_TABLE(ユーザー ID、開始日、開始日、アクティビティ ID)
  • ACTIVITY_TABLE (アクティビティ ID、名前)

EFでは、これらはテーブルに対応する以下のエンティティです

  • User(UserId,Name, AssignedActivities) A​​ssignedActivities beeing ナビゲーション プロパティ
  • ActivityHistory (UserId, DateFrom,DateTo,activityId,TheActivity) ナビゲーション プロパティである TheActivity
  • 活動 (ActivityId、名前)

リクエスト時に行っているアクティビティを含むすべてのユーザーのリストを返す必要があります (ActivityHistory.Datefrom <= now および ActivityHistory.DateTo >= now)。

現在活動していないユーザーも返されます。

複数のアクティビティを持つユーザーは重複してはいけません

「User.AssignedActivities」と「ActivityHistory.TheActivity」をロードする必要があります(遅延ロードなし)。

これまでのところ、私のニーズの 1 つに失敗する 4 つのソリューションがあります。

1 - すべてのユーザーではなく、特定の時間にアクティビティがあるユーザーのみを返します

public List<User> GetAll()
{
  using (Entities _db = new Entities())
  {
    return _db.USERS_TABLE
       .Include("ActivityHistory")
       .Include("ActivityHistory.Activity")
       .Where(x => x.ActivityHistory.Any(y => y.DateFrom <= DateTime.Now && y.DateTo >= DateTime.Now))
       .ToList();    
   }
}

2 - ユーザーの正しいリストを返します (重複なしで完了) が、アクティビティは読み込まれません (返されたリストで User.AssignedActivities を操作すると System.ObjectDisposedException)

(ここで見られる解決策:条件付きインクルードを使用したEFクエリ

public List<User> GetAll()
{
  using (Entities _db = new Entities())
  {
    var query = from users in _db.USERS_TABLE
                select new
                {
                    users,
                assignments = from ActivityAssigned in users.AssignedActivities
                              .Where(y => y.DateFrom <= now && y.DateTo >= now)
                              .DefaultIfEmpty()
                              select ActivityAssigned
            };

var query2 = query
    .AsEnumerable()
    .Select(x => x.users);

return query2.ToList();
   }
}

3 - ユーザーが多くのアクティビティを持っていて、それらのアクティビティが読み込まれていない場合に重複を返します (返されたリストで User.AssignedActivities を操作すると System.ObjectDisposedException が発生します)。

(以下のSteve Rubleの解決策)

public List<User> GetAll()
{
  using (Entities _db = new Entities())
  {
    var query = 
     from u in _db.USERS_TABLE
     select new {
     User = u,
     CurrentActivities = u.ActivityHistory
                          .Where(y => 
                                 y.DateFrom <= DateTime.Now
                              && y.DateTo >= DateTime.Now)
                          .Select(ah => new 
                          {
                            ActivityHistory = ah,
                            Activity = ah.Activity
                          }
     }

return query.AsEnumerable().Select(x=> x.User).ToList();    
}
}   

4 - ActivityHistory エンティティのリポジトリを使用して、やりたいことを実行しますが、それを行うには永遠に時間がかかります。

public List<User> GetAll()
{
  using (Entities _db = new Entities())
  {
List<Users> MyUsersList = new List<Users>();

MyUsersList = _db.USERS_TABLE
    .Include("ActivityHistory")
    .Include("ActivityHistory.Activity")
    .ToList();

for (int i = 0; i < MyUsersList.Count(); i++)
{
    List<ActivityHistory > UserCurrentActivityList = new List<ActivityHistory >();

    ActivityListRepository activityListRepo = new ActivityListRepository();

    UserCurrentActivityList = activityListRepo.GetUserCurrentActivity(MyUsersList[i].UserId);

    MyUsersList[i].AssignedActivities = UserCurrentActivityList;
}

return MyUsersList; 
   }
}               

ヘルプ :) !

4

3 に答える 3

1

必要なものがすべてのユーザーのリストであり、各ユーザーの現在のアクティビティまたは nullがある場合は、これで実行できます。トリックはDefaultOrEmpty、SQL 側で LEFT OUTER JOIN に変換される にあります。

from u in _db.USERS_TABLE
from aht in u.ActivityHistory
             .Where(y => y.DateFrom <= DateTime.Now && y.DateTo >= DateTime.Now)
             .DefaultIfEmpty()
select new {
    User = u,
    CurrentActivityHistory = ah
    CurrentActivity = ah.Activity
}

編集

現在のすべての ActivityHistory レコードと、ActivityHistory ごとに熱心に読み込まれたアクティビティを含むすべてのユーザーのリストが必要な場合は、次のようにします。

var query = 
 from u in _db.USERS_TABLE
 select new {
     User = u,
     CurrentActivities = u.ActivityHistory
                          .Where(y => 
                                 y.DateFrom <= DateTime.Now
                              && y.DateTo >= DateTime.Now)
                          .Select(ah => new 
                          {
                            ActivityHistory = ah,
                            Activity = ah.Activity
                          }
 }

具体化されたエンティティに関する注意:

この変数の値を考えてみましょう:

var レコード = query.First();

ユーザーがデータベース内に最新でないレコードをさらに多く持っている場合でも、プロパティには と同じオブジェクトrecord.User.ActivityHistoryを含むコレクションが取り込まれます。つまり、 のすべてのレコードを取得する必要がある場合は、遅延読み込みに頼ってそれらを取得するのではなく、別のクエリを作成する必要があります。ActivityHistoryrecord.CurrentActivitiesActivityHistoryActivityHistoryUser

于 2013-09-28T15:16:47.493 に答える
1
_db.Database.EnableLazyLoading = false;
_db.Database.UseProxyObjects = false;
var now = DateTime.Now; //DON'T REFACTOR THIS LINE!!!
var query = from user in _db.USERS_TABLE
            from activity in user.ACTIVITY_HISTORY
            group activity by user into g
            select new {
               User = g.Key,
               CurrentActivities = g.Where(activity =>
                           activity.DateFrom <= now && activity.DateTo >= now)
            };
return query.ToList().Select(x => x.User).ToList();

編集:修正...願っています。ただし、このクエリは使用しないことをお勧めします。その非常にハック。CurrentActivities のルックアップが必要な場合は、データ構造を使用してそれを保存することを強調します。

これが機能するという事実は、EF の機能のいくつかのニュアンスによってまとめられています。それは非常に悪い習慣であり、将来的に多くの問題が発生することになります。

于 2013-09-26T14:30:41.030 に答える