2

我有 3 张桌子:

  • USERS_TABLE(用户名,名称)
  • ACTIVITY_HISTORY_TABLE(userid, datefrom,dateto,activityId)
  • ACTIVITY_TABLE(活动 ID,名称)

在 EF 中,这些是对应于表格的以下实体

  • User(UserId,Name, AssignedActivities) 导航属性中的AssignedActivities
  • ActivityHistory (UserId, DateFrom,DateTo,activityId,TheActivity) TheActivity 作为导航属性
  • 活动(活动 ID、名称)

我需要返回一个包含所有用户的列表,包括他们在请求时正在进行的活动(ActivityHistory.Datefrom <= now 和 ActivityHistory.DateTo >= now)。

没有当前活动的用户也将被退回。

具有多个活动的用户不得重复

我需要加载“User.AssignedActivities”和“ActivityHistory.TheActivity”(没有延迟加载)。

到目前为止,我有 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 Query With Conditional Include

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)

(史蒂夫卢布的解决方案如下)

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

If what you want is a list of all users, with the current activity or null for each user, this should do it. The trick is in the DefaultOrEmpty, which gets translated into a LEFT OUTER JOIN on the SQL side.

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
}

EDIT

If what you want is a list of all users, with all the current ActivityHistory records, and with the activity eagerly loaded for each ActivityHistory, you can do this:

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
                          }
 }

Note concerning the materialized entities:

Consider the value of this variable:

var record = query.First();

The property record.User.ActivityHistory will be populated with a collection containing the same ActivityHistory objects as record.CurrentActivities, even if the user has many more non-current ActivityHistory records in the database. In other words, if you need to get all the ActivityHistory records for a User, you will need to make another query, rather than relying on lazy-loading to pull them in.

于 2013-09-28T15:16:47.493 回答
1

最后,在这个主题上花费了太多时间后,我终于找到了我的解决方案(我相信这在某种程度上接近关系修复概念,但我可能在这里说一个荒谬)。

public List<User> GetAll()
{
   using (Entities _db = new Entities())
   {
      _db.Configuration.LazyLoadingEnabled = false;

      var now = DateTime.Now;

      var currentActivities = _db.ActivityHistory 
                                .Where(x => x.DateFrom <= now && x.DateTo >= now)
                                .Include("TheActivity")
                                .ToList();

      var Controlers = _db.User.ToList();

      return Controlers;
   }
}

实际上答案一直在这里

发出两个单独的查询:一个用于电影,一个用于评论,然后让关系修复完成其余的工作。

任何评论赞赏想法。谢谢。

于 2013-10-10T12:07:15.877 回答
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();

编辑:固定......我希望。但是,我建议不要使用此查询。它非常hacky。我强调,如果您确实想查找 CurrentActivities,我会使用数据结构来存储它。

EF 工作方式的一些细微差别将这项工作结合在一起。这是非常糟糕的做法,你最终会遇到很多问题。

于 2013-09-26T14:30:41.030 回答