【问题标题】:How to avoid a sql query in a forearch如何避免foreach中的sql查询
【发布时间】:2013-09-23 13:33:30
【问题描述】:

我有 2 个表:User 和 UserFriends

用户 用户 ID,Guid

用户朋友 ActiveID、Guid - PassiveID、Guid

所以你可以在我的好友列表中,但我不需要在你的好友列表中。 对于所有用户的在线列表,首先我获取所有用户并使用 foreach 迭代他们来做我必须在这里做的事情。

List<DAL.User> onlineList = DAL.UserDAL.GetAllOnlineUser();
foreach (DAL.User onlineUser in onlineList)
{
   //do things here
    if (DAL.UserDAL.CheckForFriends(myUserID, onlineUser.UserID))
    {
           //Do things here
    }
}

服务器代码:

 public static List<User> GetAllOnlineUser()
    {
        using (RPGDataContext dc = new RPGDataContext())
        {
            return (from a in dc.Users where a.RefreshPing > DateTime.Now.AddMinutes(-30) orderby a.Username select a).ToList();
        }
    }

public static bool CheckForFriends(Guid userActive, Guid userPassive)
    {
        using (RPGDataContext dc = new RPGDataContext())
        {
            UserFriend uf = (from a in dc.UserFriends where a.UserIDActive == userActive && a.UserIDPassive == userPassive select a).SingleOrDefault();
            return (uf != null);
        }
    }

在这个 foreach 中,我必须检查朋友,如果,我在在线列表中加入一个朋友符号。 这意味着有 20 个在线用户没有我,我必须访问数据库 20 次并返回。 如何避免?

【问题讨论】:

  • 你不能获取GetAllOnlineUser()方法上加载的所有信息吗?

标签: asp.net sql


【解决方案1】:

正在使用关系数据库(例如 Oracle、MySql、MsSql 等)?

如果是这样,让数据库做它最擅长的事情:编写一个查询从数据库返回适当的结果。

更新 1

例如,MS SQL 查询可能类似于:

SELECT u.userId, u.refreshPing
FROM userFriends f
JOIN [user] u ON u.userId = f.userFriendId
WHERE DATEDIFF(MINUTE, u.refreshPing, GetDate()) < 6000
AND f.userId = 1

由于时间原因,我的查询假设:

  • 键是整数(不是 GUID)
  • 用户表 = userId (int), refreshPing (DateTime)
  • userFriends = userId (int), userFriendId (int)
  • 在我的示例中 userFriends.userFriendId 是返回用户表的外键
  • 此查询未经测试

您必须修改查询以匹配您的架构...我不知道您是如何管理朋友关系的。

更新 2 你可以:

  1. 使用实体框架编写类似的查询(我认为这是您正在使用的技术)
  2. 在数据库上创建一个视图并查询结果
  3. 创建一个存储过程并从您的代码中调用它

我倾向于选项 #1。

更新 3

下载 LINQPad www.linqpad.net/‎

【讨论】:

  • 您能添加一个示例查询吗?或者至少是让 OP 开始的东西?
  • 我同意,请提供比这个提示更多的内容:)
  • 谢谢。我真的不能将 T-SQL 转换为 Linq To SQL,你能在 Linq to sql 中形成它吗?当然,数据库中充满了 FK 和 PK 等等,ID 是 Guid。
  • 就逻辑而言,拉回“在线朋友”列表时,GUID 或整数不会产生影响。
  • 伟大的更新,Pressacco。我删除了我的反对票和赞成票。
【解决方案2】:

在输入 foreach 之前创建一个查询以返回您的所有朋友,然后只需对照该集合检查每个在线用户

【讨论】:

  • 您可以为此添加代码吗?也许在 GetAllOnlineUser-Query 中,所以我只需要 1 个查询?
【解决方案3】:

所以你想返回一个在线用户列表,并为 IsFriendOfCurrentUser 添加属性?如果您想在单个查询中执行此操作,则不能在 UI 层中使用 DAL 实体。

为您的 UI 创建单独的类,然后如果当前用户是该用户的朋友,则选择带有在线用户详细信息 + 布尔信息的匿名类。并从列表中排除当前用户,因为您可能不想向用户显示他在线。

public static List<InsertClassNameHere> GetAllOnlineUser(Guid userActive)
{
    using (RPGDataContext dc = new RPGDataContext())
    {
        var userList = from u in dc.Users
        join uf in dc.UserFriends on u.UserId equals uf.UserIDPassive into JoinedFriends 
        from uf in JoinedFriends.DefaultIfEmpty()
        where u.UserId != userActive
        select new 
        {
            UserId = u.UserId,
            IsFriend = uf != null ? true : false
        };

        var returnList = new list<InsertClassNameHere>();
        foreach(var user in userList)
        {
            returnList.Add(new InsertClassNameHere()
            {
                UserId = UserId,
                IsFriend = IsFriend 
            };
        }

        return returnList;
    }
}

【讨论】:

    【解决方案4】:

    类似

    var friends = onlineList.Where(a => a.UserIDActive == myUserID && a.UserIDPassive == userPassive);
    

    或者我没听懂这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-14
      • 2011-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多