如何使用linq to实体检查最近10个条目中的值

时间:2012-05-22 00:38:11

标签: linq entity-framework

我有一个方法,我需要使用EF检索数据库中的最后十个条目,并检查值和当前术语之间是否匹配。这是我到目前为止所拥有的

public static int ValidatePassword(string username, string password, int securityUserId)
        {
                int validResult = 0;
                /*Need to pass to client a value based upon success or failure of validation
                 * 0 - success
                 * 1 - password has already been used in the last 10 entries
                 * 2 - password does not meet CJIS requirements
                 */
                IEnumerable<string> oldpassword = null;
                // Create a Regular Expression to determine whether or not special characters are present.
                Regex regularExpression = new Regex("[^a-z0-9]");

                //if id exists pull last ten passwords
                if (securityUserId > 0)
                {
                    long id = Convert.ToInt64(securityUserId);

                    using (var context = new SecurityEntities(string.Empty))
                    {
                        try
                        {
                            oldpassword = (from p in context.SecurityAudits
                                           where p.SecurityUserId == id &&
                                           p.OldPassword == password
                                           orderby p.ActionDate descending
                                           select p.OldPassword.Take(10).ToString()).ToList();
                        }
                        catch (Exception ex)
                        {
                            string err = string.Format("ValidateCJISPassword() was unable to return an object msg:{0}", ex.Message);
                            throw new Exception(err, ex.InnerException);
                        }
                        finally
                        {
                            context.Dispose();
                        }
                    }
                }

                else if (oldpassword == null)
                {
                    //no matching record found now check other requirements
                    if ((password.Length >= DEFAULT_CJIS_PASSWORD_MIN_LENGTH) && regularExpression.IsMatch(password) && (password != username))
                    {
                        //success
                        validResult = 0;
                    }
                    else
                    {
                        //password does not meet standard CJIS requirements
                        validResult = 2;
                    }
                }
                else
                {
                    //matching record was found
                    validResult = 1;
                }
                return validResult;
            }
}

我当前挂起的地方是查询在ToString()方法上抛出异常

LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.

我还在学习EF以及linq是如何工作的,所以我不确定这里最好的方法是什么。我应该尝试将结果设置为IEnumerable以外的其他内容,如数组或List,还是应该考虑另一种方法?

提前致谢,

干杯,

2 个答案:

答案 0 :(得分:1)

更改此

oldpassword = (from p in context.SecurityAudits
                   where p.SecurityUserId == id &&
                   p.OldPassword == password
                   orderby p.ActionDate descending
                   select p.OldPassword.Take(10).ToString()).ToList();

到此

oldpassword = (from p in context.SecurityAudits
               where p.SecurityUserId == id &&
               p.OldPassword == password
               orderby p.ActionDate descending
               select p.OldPassword).Take(10).ToList();

问题是你的Take(10)子句不是整个结果的一部分,而是在实际的linq语句中..它在它的外面取得整个结果集的前10个..然后你做ToList()将整个事物变成数组

下一个问题是您刚刚创建了一个数组并将其分配给oldpassword

我在这里看不到任何与数组有关的东西......

您需要执行以下操作:

  1. 声明你的字符串数组
  2. 将数组分配给linq查询的返回
  3. 评估&gt;的回报率0结果
  4. if&gt; 0然后密码已在最后10个
  5. 中使用
  6. if = 0然后新密码应该没问题,对吗?

答案 1 :(得分:0)

现在我已经了解了查询中我需要的内容,我还能够更新linq语句,如下所示:

    var lastTenPassword = (from p in context.SecurityAudits.Take(10)
                                     orderby p.ActionDate descending
                                     where p.SecurityUserId == id
                                     select p.OldPassword).ToList();

   string oldpassword = lastTenPassword.Where(a => a == password).FirstOrDefault();

测试更进一步,但现在通过在查询中移动.Take()方法,我明确地抓住前十名,因为我的第一次尝试将检索所有记录,然后抓住前十名。

为了进行测试,你还可以看到我在哪里发布了初始where(),首先按id获取所有记录,然后通过在该集合中查找匹配的密码对该集合执行过滤。

再次感谢您的帮助