我是C#,Entity Framework和LINW的新手,希望有人可以在代码中解释有关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是一个包含对数据库实例的引用的字段。
在select user方法中,我理解有一个cp_user类型的局部变量的创建,它由语句定义:
(from u in _db.cp_user
where u.username == user && u.password == passw
select u).FirstOrDefault();
我对声明的第一部分感到困惑。 “来自你在_dp.cp_user”。 到目前为止,我一直在使用MySQL,所以很难看到这个“来自你”。在MySQL中,这个“你”指的是一个表。但是在Linq我很困惑它的作用。
我完全理解语句的其余部分,方法中的用户名和密码参数必须等于表中的数据。并且它将返回数据库对象。但是再次混淆了你,在最后一部分说“选择你”。
我的另一个问题是另一个名为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方法用于输入用户名和密码,并创建一个布尔变量,可以根据语句返回true或false。这是我不理解的部分。
我很抱歉,如果我做了任何错误的陈述,请纠正我,如果我刚接触编程,一般只用过MySQL。如果有人能回答我的3个问题,我将不胜感激。
提前致谢
答案 0 :(得分:0)
u
中的from u in _db.cp_user
是对列表中与条件匹配的每个项目的引用(即u.username == user && u.password == passw
)。
select u
返回匹配项。
只有当数据库中的用户名和密码都与提供的参数匹配时,该语句才会返回true。
这是开始学习LINQ的好地方:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/getting-started-with-linq
答案 1 :(得分:0)
你提到的“你”只是一个临时变量,表示你的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集合中的所有用户,只接受UserName等于userName且密码等于密码的用户。
从剩下的集合中取第一个元素,如果没有第一个元素,则返回null(更确切地说:返回默认值(User),对于类为null)。
我从C#world进入SQL世界,我发现方法语法更具可读性。如果将集合命名为复数并将集合中的每个元素命名为单数,则会有所帮助。标识符太短会减少打字时间,但通过输入较短的名称来增加理解时间远远超过保存时间
User user = db.cp_users
.Where(user => user.userName == userName && user.password == password)
.FirstOrDefault();
从cp_User中的用户集合中,仅使用userName等于userName且密码等于passWord的用户。从剩余的集合中获取第一个元素,如果集合为空,则返回null。
如果您想要所选用户的所有属性,则无需执行选择。但是,如果您只想要一些属性,则需要使用Select
进行“投影”
db.cp_users
.Where(user => user.userName == userName && user.password == password)
.Select(use0r => new
{
Id = user.Id,
Name = user.userName,
})
.FirstOrDefault();
<强>任何()强>
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和password等于password的用户。如果集合中至少有一个元素,则返回true;如果集合为空,则返回false。
Any比Count()更快!= 0,因为Any会在找到一个元素后立即停止,而Count()必须枚举完整集合才能将结果与0进行比较。
您写道:
看起来这意味着方法参数中的用户名和密码必须存在于数据库中。但有人在学校告诉我,这意味着用户名和密码必须正确对应;您不能拥有与其他用户名相关联的密码。
假设您有一个包含两个用户的集合:
ICollection<User> myUsers = new User[]
{
new User{ Name = "U1", Password = "P1"},
new User{ Name = "U2", Password = "P2"},
};
很容易看到有一个名称为“U1”且密码为“P1”的用户,但没有名称为“U1”且密码为“P2”的用户。
bool result = myUsers
.Where(user => user.username == "U1" && user.password == "P1")
.Any();
单词:对于myUsers集合中的每个用户,只需使用userName等于“U1”且密码等于“P1”的用户。返回剩余的集合是否为空。
很容易看出myUsers中的第一个元素与Where匹配,因此其余的集合不为空。
结果是真的;
bool result = myUsers
.Where(user => user.username == "U1" && user.password == "P2")
.Any();
myUsers中没有元素匹配Where。其余的集合是空的。结果是错误的。
您会发现使用正确的变量名可以提高可读性。而不是“你”写“用户”,语句几乎是正常的语言。
如果您要使用linq,请考虑使用方法语法而不是查询语法。方法语法比查询语法具有更多功能。方法语法是更基本的C#。使用方法语法,您还可以添加自己的LINQ类函数。因此,如果您将使用Linq,请考虑学习Method语法。
答案 2 :(得分: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 =&gt; u.username == user&amp;&amp; u.password == passw)
Any
函数内的代码是lambda表达式。你也需要了解它们。它们很漂亮,可以像任何东西一样减少代码。见下文
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;
}
并使用此方法作为谓词来过滤掉无效用户。这是很多不必要的工作。
我希望你现在已经说服并有足够的动力来学习更多关于lambdas的知识。