asp.net LINQ到实体和空字符串

pb3s4cty  于 2022-11-19  发布在  .NET
关注(0)|答案(4)|浏览(168)

我在一个使用EF4.0作为数据库后端的ASP.NET4.0Web应用程序上遇到了一件非常奇怪的事情。(包含类型byte[]的复位密钥、类型DateTime的期满以及指向包含string Emailstring NameUser的外键)。某些用户没有设置电子邮件地址,因此对于PasswordRequest requestrequest.Emailnull
问题就在这里。这个方法很好用:

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电子邮件的条目)。
但是,当enull时,这始终返回一个空集合:

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;

我完全被难住了。有什么主意吗?

vqlkdk9b

vqlkdk9b1#

基本上,这是SQL和C#在处理空值时的不匹配。您不需要使用两个查询,但需要:

where r.User.Name == u && (r.User.Email == e ||
                           (e == null && r.User.Email == null))

这很烦人,可能有一个帮助器函数可以使工作变得更容易,但它基本上来自SQL的空处理,其中

where X = Y

如果X和Y都为空,则 * 不 * 匹配。(而在C#中,等效表达式将为true。)
您可能也需要对u执行相同的操作,除非它在数据库中不可为空。
如果您对空字符串和空字符串的处理方式感到满意,那么至少可以 * 尝试 * 一个小技巧:

// Before the query
e = e ?? "";

// In the query
where r.User.Name == u && (r.User.Email ?? "") == e

我相信这将在email列和e上执行null合并,因此您永远不会将null与任何内容进行比较。

xxb16uws

xxb16uws2#

我 发现 有 几 篇 文章 详细 描述 了 同一 个 问题 。 不幸 的 是 , 我 还 没有 面对 这个 问题 , 但 它 是 非常 有趣 的 。
在 这里 :
LINQ syntax where string value is not null or empty 的 最 大 值
LINQ to SQL and Null strings, how do I use Contains? 格式
来自 MSDN :http://msdn.microsoft.com/en-us/library/bb882535.aspx 格式

h43kikqp

h43kikqp3#

如果你喜欢像我一样使用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;
6fe3ivhb

6fe3ivhb4#

如果要在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 Info
因此,最后一个示例是有效的,因为您需要两种方法从DB获取数据。即,一种方法是email为null,另一种方法是email == Request ['e']

相关问题