2017-08-09 40 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的知識。