我试图在asp.net框架中使用带有c#的LINQ访问SQL服务器。我正在网页上写一个简单的登录表单。以下是我的c#代码,用于检查它是否在数据库中。
public int getUserId(string un, string pw)
{
IEnumerable<int> query;
using (var context = new IngredientsLinqDataContext())
{
query = from c in context.USERs
where c.Username == un && c.Password == pw
select c.UserID;
}
if(query.Count() >= 1)
{
return query.Min();//a very serious kludge. Need to fix this
}
else { return -1; }
}
}
检查查询计数是否大于或等于1时,抛出了对象处置异常。我曾经想过,因为查询是在花括号之外声明的,所以这不应该是范围问题。此外,什么是修复kludge的好方法?它应该只返回一个int,而不是一个int列表。我怎么能这样对待它?谢谢!
更改
query = from c in context.USERs
where c.Username == un && c.Password == pw
select c.UserID;
至
query = (from c in context.USERs
where c.Username == un && c.Password == pw
select c.UserID).ToList();
LINQ使用延迟执行,因此您不会立即计算查询,但仅在query.Count()
进行评估。那一刻的context
已经被处理掉了。这就是你收到错误的原因。
context
被处置,因为你试图使用块从context
中检索数据库中的数据;
using (var context = new IngredientsLinqDataContext())
{
query = from c in context.USERs
where c.Username == un && c.Password == pw
select c.UserID;
if (query.Count() >= 1)
{
return query.Min();//a very serious kludge. Need to fix this
}
else { return -1; }
}
您必须知道Linq查询可以是qqxxswpoi或AsEnumerable
。
如果你的查询是AsQueryable
,它包含访问查询中元素所需的所有信息:你可以要求序列中的第一个元素(如果有的话),一旦你有了一个元素,你可以要求下一个元素(如果有的话)。如果您的查询在您的流程中使用其他功能,则它具有访问这些其他功能的所有信息。简而言之:AsEnumerable
在本地内存中处理。
如果你的查询是AsEnumerable
它持有AsQueryable
和Expression
。 Provider
知道指定哪个过程来处理Provider
。它知道此进程使用的语言。 Expression
的任务是将Provider
转换为目标处理器的语言并将其发送到此处理器。
对于Entity Framework,这通常是SQL或MySQL等数据库,但它也可以是电子表格或CSV文件。关于Expression
的好处是,您不需要知道它用于与其他进程通信的语言。您可以使用相同的IDbSet类与完全不同的进程进行通信。
因此,DbContext
不会保存信息以枚举查询中的元素。它只知道如何将其转换为指定进程的语言以及要求执行此查询的人员。
在您要求元素之前,不会进行翻译和执行。这意味着您必须保持查询使用的提供对象,直到您不再需要此提供对象的任何更多结果。
每当您要求一个不使用延迟执行的函数时,就会执行查询(如每个linq函数的备注部分所述)。这些是ToList(),FirstOrDefault(),Single(),Count()等函数。
像IQueryable
,Where
,Select
和其他使用延迟执行的函数只会改变GroupBy
。
结论 在Dispose()之前,请确保已从提供程序中获取所需的所有数据
可能这将解决您的问题。
Expression
在此构造中使用public int getUserId(string un, string pw)
{
int query;
using (var context = new IngredientsLinqDataContext())
{
--change here
query = (from c in context.USERs
where c.Username == un && c.Password == pw
select c.UserID).FirstOrDefault();
}
if(query != 0) --change here
{
return query;//a very serious kludge. Need to fix this
}
else { return -1; }
}
指示query
在对数据库执行实际查询之前等待访问对象。在这种情况下,LINQ
可以在query
块之外访问,这就是你收到错误的原因。
试试这个:
using