LINQ到实体和空字符串
本文关键字:字符串 实体 LINQ | 更新日期: 2023-09-27 18:14:03
在ASP上发生了一件很奇怪的事情。NET 4.0 web应用程序,使用EF 4.0作为其数据库后端。基本上,我有一个存储用户密码重置请求的表(包含类型为byte[]
的重置键、类型为DateTime
的到期键和包含string Email
和string Name
的User
的外键)。有些用户没有电子邮件地址集,所以对于PasswordRequest request
, request.Email
是null
。
问题在这里。
string u = Request["u"];
string e = Request["e"];
var requests = from r in context.PasswordRequests
where r.User.Name == u && r.User.Email == null && r.Expiry >= DateTime.Now
select r;
我得到预期的结果数(非零,因为有包含null
电子邮件的条目)。
但是当e
是null
时,这总是返回一个空集合:
string u = Request["u"];
string e = Request["e"];
var requests = from r in context.PasswordRequests
where r.User.Name == u && r.User.Email == e && r.Expiry >= DateTime.Now
select r;
我唯一能正常工作的(这在逻辑上没有任何意义)是:
string u = Request["u"];
string e = Request["e"];
IQueryable<PasswordRequest> requests;
if (e == null)
requests = from r in context.PasswordRequests
where r.User.Name == u && r.User.Email == null && r.Expiry >= DateTime.Now
select r;
else
requests = from r in context.PasswordRequests
where r.User.Name == u && r.User.Email == e && r.Expiry >= DateTime.Now
select r;
我完全被难住了。什么好主意吗?
基本上这是SQL和c#在处理null时的不匹配。您不需要使用两个查询,但您需要:
where r.User.Name == u && (r.User.Email == e ||
(e == null && r.User.Email == null))
这很烦人,可能会有一个辅助函数来简化工作,但它基本上来自SQL的null处理,其中
where X = Y
如果X和Y都为空,将不匹配。(而在c#中,等效表达式将为true。)
您可能也需要为u
做同样的事情,除非它在数据库中是非空的。
一个小技巧,你至少可以尝试如果你喜欢null和空字符串以同样的方式处理:
// Before the query
e = e ?? "";
// In the query
where r.User.Name == u && (r.User.Email ?? "") == e
我相信这将在email列和e
上执行null合并,因此您永远不会将null与任何内容进行比较。
我找到了几篇详细介绍相同问题的文章。不幸的是,到目前为止我还没有遇到过这个问题。但它很有趣。
:
LINQ语法,字符串值不是null或空
LINQ SQL和空字符串,我如何使用包含?
from MSDN: http://msdn.microsoft.com/en-us/library/bb882535.aspx
如果您像我一样喜欢使用method (lambda)语法,您可以这样做:
var result = new TableName();
using(var db = new EFObjectContext)
{
var query = db.TableName;
query = value1 == null
? query.Where(tbl => tbl.entry1 == null)
: query.Where(tbl => tbl.entry1 == value1);
query = value2 == null
? query.Where(tbl => tbl.entry2 == null)
: query.Where(tbl => tbl.entry2 == value2);
result = query
.Select(tbl => tbl)
.FirstOrDefault();
// Inspect the value of the trace variable below to see the sql generated by EF
var trace = ((ObjectQuery<REF_EQUIPMENT>) query).ToTraceString();
}
return result;
如果您想在request['e'] == null时从DB检索项
应该是
var requests = from r in context.PasswordRequests
where r.User.Name == u && r.User.Email is null && r.Expiry >= DateTime.Now
select r;
注意== null和is的null是不同的。见--> MSDN信息
因此,你的最后一个例子是有效的,因为你需要2种方式从数据库获取数据。也就是说,如果email为null,如果email == Request['e']