【问题标题】:Get Difference between Following Entities Linq to Entities获取以下实体之间的差异 Linq to Entity
【发布时间】:2013-06-05 14:04:57
【问题描述】:

为了清楚起见,按照建议将问题总结在一行中:

我想找出对某个字段具有不同值且相隔不到一周的所有事物(基于另一个字段)


假设我有一个Users 表和一个User 类。

每个User 都有以下字段:

  • SignUpDate 非空 DateTime 字段
  • UserType 一个 int 字段,对于这个问题,假设它是 10

我想选择所有注册时间少于 7 天且用户类型不同的用户。

我当前(悲惨的)尝试包括OrderBy(r=>r.SignUpDate).ToList,这没什么大不了的,因为每两周的用户数量并不多。 (我从重叠的几周中抓取了所有用户并比较了数据)。

但是,我发现我目前的解决方案很差。我不知道解决这个问题的正确方法是什么。

我认为这里的核心问题是我不知道如何在排序后解决 LINQ to Entities 中“选择每两个对应记录”的概念

非常感谢任何帮助,我对如何在将来不提出自己的问题的情况下解决此类问题感兴趣。

示例输入

 SignUpDate        UserType
 ------------------------------------
 2008-11-11          1
 2008-11-12          0
 2008-11-13          0
 2008-12-13          0
 2008-12-15          1

示例输出

任何有意义的方式表明有问题的对是:

 2008-11-11          1
 2008-11-12          0

(不同的日子和不同的类型)

 2008-12-13          0
 2008-12-15          1

(相差两天,不同类型)


这是我找到的related SQL solution

【问题讨论】:

  • 只是为了让您入门,这可能会有所帮助:msdn.microsoft.com/en-us/library/dd487052.aspx
  • @RussC 感谢虽然 LINQ to Entities 似乎能够做到 DateTime.Subtract ,但我的问题是“找到对某个字段具有不同价值且相隔不到一周的所有事物”。我会澄清的。

标签: c# linq entity-framework linq-to-entities


【解决方案1】:

我不完全了解您要解决的问题,因此以下只是一般性建议。听起来任何两个“在时间上相邻”并且彼此在一周内的用户注册都是规则,但这听起来有点奇怪..

当您想查询一条只能间接获得的信息(即不是简单的列值)时,请使用投影来选择解决问题所需的信息。

var query = from user in context.Users
            let previousUser = context.Users
                .Where( u => u.SignUpDate < user.SignUpDate )
                .OrderBy( u => u.SignUpDate )
                .FirstOrDefault()
            select new
            {
                User = user,
                PreviousUser = previousUser,
                IsDuplicate = previousUser != null && previousUser.UserType != user.UserType,
                SignUpDaysApart = user.SignUpDate.Subtract( previousUser.SignUpDate )
            };

一旦您拥有更易于访问的格式的数据,编写查询来解决业务问题就会变得更加容易。

var duplicates = (from d in query
                 where d.IsDuplicate && d.SignUpDaysApart.TotalDays <= 7
                 select d).ToList();

我希望以上内容足以启发您找到解决方案。

【讨论】:

  • 谢谢,这看起来像我要找的东西,有没有办法在 lambda 表达式语法中执行查询语法(let 部分)? (也许是Select 介于两者之间?)只是想知道。
  • 是的,LINQ 查询语法只是扩展方法之上的编译器糖。不知道你会使用什么方法,对不起:)
【解决方案2】:

想出了这样的东西

        private bool LessThan7DaysApart(DateTime d1, DateTime d2)
        {
            return (d1 - d2).Duration() < new TimeSpan(7, 0, 0, 0);
        }


        private void Match()
        {
            List<User> listfortype0 = users.Where(u => u.UserType == 0).ToList();
            List<User> listfortype1 = users.Where(u => u.UserType == 1).ToList();

            foreach (User u in listfortype0)
            {
                List<User> tmp = listfortype1.Where(u2 => LessThan7DaysApart(u2.SignUpDate, u2.SignUpDate)).ToList();
                if (tmp.Count > 0)
                {
                    List<User> matchedusers = new List<User> { u, tmp[0] };                    
                    listfortype1.Remove(tmp[0]);
                }
            }
        }

【讨论】:

  • 欢迎来到 StackOverflow!感谢您尝试帮助我解决我的问题。 Please see this。当您执行 ToList() 时,您将从数据库中提取 all 数据并将其转换为对象。查询这些对象将非常昂贵且不切实际。 Linq to Entities 将您的代码映射到 SQL 并在数据库上运行。这个建议的解决方案实际上比我目前使用的方法慢并且不满意。不过感谢您的努力。
  • 您不需要 .Duration() 来创建时间跨度对象,这是 DateTime 上 - 运算符的正常输出。此外,不要在您评估时创建一个 7 天的新 TimeSpan 对象(非常昂贵),只需比较已创建的 TimeSpan 的 .Days 属性。通过这两个更改,您可以使用 return (d1 - d2).Days &lt; 7;
猜你喜欢
  • 2014-06-29
  • 1970-01-01
  • 2013-07-29
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
相关资源
最近更新 更多