2017-08-09 72 views
0

对于C#,实体框架和LINW,我希望有人能够在关于LINQ的代码中解释一些东西。我的程序中有一个方法从表中选择一个用户。该方法是:从包含LINQ语句/表达式的表中选择用户

public static cp_user SelectUser(string user, string passw) 
    { 
     try 
     { 
      cp_user entityUser = (from u in _db.cp_user 
            where u.username == user && u.password == passw 
            select u).FirstOrDefault(); 

      return entityUser; 
     } 
     catch (System.Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 

     return null; 
    } 

cp_user是对应于我在我的数据库中的表的类。而_db是一个保存对数据库实例的引用的字段。

在选择用户方法我明白,有类型cp_user的局部变量的创建,它是由该语句定义:

(from u in _db.cp_user 
           where u.username == user && u.password == passw 
           select u).FirstOrDefault(); 
  1. 林困惑的语句的第一部分。 “从_dp.cp_user中的u开始”。 到目前为止,我一直在使用MySQL,所以它很迷惑地看到这个“来自你”。在MySQL中,这个“u”是指一个表。但在Linq im混淆了它的功能。

  2. 尽管我大致了解了其余的声明,但方法中的用户名和密码参数必须与表中的数据相同。并且它会返回数据库对象。但是,在最后一部分“选择你”中再次感到困惑。

另一个问题我已经是在所谓的checkany另一种方法,它检查用户登录正确的是:

public static bool CheckAny(string user, string passw) 
    { 
     bool itIsAlredy = _db.cp_user.Any(u => u.username == user && u.password == passw); 
     return itIsAlredy; 
    } 

我明白,在用户名和密码CheckAny methodtakes并创建一个布尔变量它可以根据语句返回true或false。这是我不了解的部分。

  • 对于我这个语句 “(U => u.username ==用户& & u.password == PASSW);”看起来像这意味着方法参数中的用户名和密码必须存在于数据库中。但是有学校的人告诉我,这意味着用户名和密码必须正确对应;您不能拥有连接到其他用户名的密码。那么这个声明实际上说了些什么?而且我也不明白整个“u => u.username”。像这个你代表什么。它是特殊的linq语法,如果是这意味着什么?任何人都有链接解释这一点?
  • 如果我有任何错误的陈述,请纠正我,如果我有新的编程,一般只在MySQL以前使用过。如果有人能回答我提出的三个问题,我将不胜感激。

    由于在预先from u in _db.cp_user

    +0

    您需要开始使用Linq to SQL或Linq来处理一般情况。这是在这里解释太基本的东西。 – niksofteng

    +0

    @niksofteng好的非常感谢你在提出另一个问题之前,我会牢记这一点。 Regards –

    回答

    0

    的“U”你提到的仅仅是你的cp_user的集合代表一个元素的临时变量。实际上它说:

    for each u in the collection of elements in cp_user do ... 
    

    Linq有两种语法形式:query syntax and method syntax。你的陈述是两者的结合。方法语法具有更多的功能,正如您在只存在于方法语法中的函数FirstOrDefault中所见。

    如果将语句分成两个语句,您将看到包含查询语法的部分和包含方法语法的部分。

    顺便说一句,多年来,我发现适当的变量命名提高了可读性。

    (假设cp_user是DbSet)

    IQueryable<User> myUsers = from user in db.cp_user 
        where user.username == userName && user.password == password 
        select user; 
    User myUser = myUsers.FirstOrDefault(); 
    

    在的话:从cpUser集合中的所有用户,其中的用户名等于用户名和口令等于密码只需要那些用户。

    从剩余的集合中取第一个元素,如果没有第一个元素(更确切地说:返回缺省值(User),对于类为null)返回null。

    我来自C#世界到SQL世界,我发现方法的语法更具可读性。如果您将集合命名为复数,并将集合中的每个元素都命名为单数,它会有所帮助。过短的标识符减少打字时间,但增加了解的时间比你省得更多通过输入较短的名称

    User user = db.cp_users 
        .Where(user => user.userName == userName && user.password == password) 
        .FirstOrDefault(); 
    

    从cp_User用户的收集,使用用户名等于userName和密码等于密码只需要用户。从剩余的集合中取第一个元素,如果集合为空,则返回null。

    如果您想要所选用户的所有属性,则不需要执行选择。但是,如果你只想要一些属性的,你需要做一个“投影”,这是使用Select

    db.cp_users 
        .Where(user => user.userName == userName && user.password == password) 
        .Select(use0r => new 
        { 
         Id = user.Id, 
         Name = user.userName, 
        }) 
        .FirstOrDefault(); 
    
    • 对于收集cp_users所有用户完成,只需要用户使用用户名等于userName的密码等于密码。
    • 对得到的集合中的每个用户创建一个新的匿名类型的对象有两个属性:
      • ID应具有user.Id价值
      • 名称应该有user.UserName
      • 的价值
    • 从剩余的匿名类型集合中,只取第一个元素,如果集合为空,则返回null。

    任何()

    有两个版本Enumerable.Any,一种带有一个无参数。

    该一个与参数:

    bool result = _db.cp_user.Any(user => user.username == userName && user.password == password); 
    

    是等效于以下:

    bool result = _db.cp_users 
        .Where(user => user.username == userName && user.password == password) 
        .Any(); 
    

    在词:

    在cp_users所有用户,采取只有那些其中username等于userName和密码等于密码。如果集合中至少有一个元素,则返回true,如果集合为空,则返回false。

    任何比COUNT()快!= 0,因为一旦一个元素被发现的任何停止,而COUNT()具有枚举完整集合之前,相比之下,0

    你写的结果:

    看起来像这意味着方法参数中的用户名和密码必须存在于数据库中。但是有学校的人告诉我,这意味着用户名和密码必须正确对应;您不能拥有连接到其他用户名的密码。

    假设有两个用户的集合:

    ICollection<User> myUsers = new User[] 
    { 
        new User{ Name = "U1", Password = "P1"}, 
        new User{ Name = "U2", Password = "P2"}, 
    }; 
    

    这是很容易看到,有与NAME =“U1”和密码“P1”用户,但没有用户使用名称“U1”和密码“P2”。

    bool result = myUsers 
        .Where(user => user.username == "U1" && user.password == "P1") 
        .Any(); 
    

    在口头上:对于myUsers的集合中的每个用户,只需要那些用户名等于“U1”和密码等于“P1”。返回剩余的集合是否为空。

    很容易看出myUsers中的第一个元素与Where匹配,所以剩余的集合不是空的。

    结果为真;

    bool result = myUsers 
        .Where(user => user.username == "U1" && user.password == "P2") 
        .Any(); 
    

    myUsers中没有元素与Where匹配。剩下的收集是空的。结果是错误的。

    您会发现使用适当的变量名可以提高可读性。而不是“你”写“用户”,这个声明几乎是正常的语言。

    如果您打算使用linq很多,请考虑使用方法语法而不是查询语法。方法语法比查询语法具有更多的功能。方法的语法是更基本的C#。使用方法语法,你也可以添加你自己的类LINQ函数。因此,如果您将大量使用Linq,请考虑学习Method语法。

    参见:Extension methods demystified

    0
    from u in _db.cp_user 
    where u.username == user && u.password == passw 
    select u 
    

    LINQ都有它自己的语法和像任何其他事情,你将有机会学习并获得最终习惯了。不要混淆SQL和LINQ查询语法。此查询中的u是一个范围变量。您可以将u视为我们在应用where子句的SQL查询中使用的表别名。请注意,我只是为了更容易理解而这么说的。这并不意味着上面的代码在翻译成等效的SQL时实际上使用u作为别名。

    _db.cp_user.Any(U => u.username ==用户& & u.password == PASSW)

    内部Any函数的代码是λ表达式。你也需要了解它们。它们非常美丽,可以像任何东西一样减少代码。见下文

    Any是定义作为扩展方法:这里

    static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate) { 
        foreach (T element in source) { 
         if (predicate(element)) { 
          return true; 
         } 
        } 
        return false; 
    } 
    

    predicate参数是代表表示,它表示接受T类型的输入参数,并返回bool的方法的方法。所以,如果你想写不lambda表达式相同的代码,你就必须定义一个方法,像这样

    private bool CheckUser(cp_user user, string user, string passw) { 
        if (user.username == user && cp_user.password == passw) { 
         return true; 
        } 
        return false; 
    } 
    

    ,并使用此方法,因为谓词过滤掉无效用户。这是很多不必要的工作。

    我希望你现在已经确信并且有足够的动力来学习更多关于lambda的知识。