【问题标题】:LINQ to Entities and null stringsLINQ to Entities 和空字符串
【发布时间】:2011-11-11 07:26:57
【问题描述】:

我在使用 EF 4.0 作为其数据库后端的 ASP.NET 4.0 Web 应用程序上发生了一件很奇怪的事情。本质上,我有一个存储用户密码重置请求的表(包含byte[] 类型的重置密钥、DateTime 类型的到期时间以及包含User 的外键string Email 和@ 987654325@)。有些用户没有设置电子邮件地址,因此对于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;

我完全被难住了。有什么想法吗?

【问题讨论】:

  • 实际表中的 Email 字段,是否声明为 NULL 列?
  • 可以把生成的sql贴一下吗?

标签: c# asp.net sql-server entity-framework linq-to-entities


【解决方案1】:

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

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

这很烦人,可能有一个帮助函数可以让生活更轻松,但它本质上来自于 SQL 的 null 处理 where

where X = Y
如果 X 和 Y 都为空,

匹配。 (而在 C# 中,等效表达式为真。)

您可能还需要对 u 执行相同的操作,除非它在数据库中不可为空。

如果您对以相同方式处理空字符串和空字符串感到满意,您至少可以尝试一个小技巧:

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

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

我相信这将对电子邮件列和e 执行空值合并,因此您永远不会将空值与任何内容进行比较。

【讨论】:

  • 啊哈!我虽然可能会这样,但我不确定究竟是什么原因造成的。感谢您的澄清!
  • 干得好! where 条件有点松散。所以我想为e 输入所有三个可能的值是有意义的。
  • 我遇到了一个问题,我的数据库包含一个允许空值的 INT 列,因此其他一些解决方案对我不起作用(大多数解决方案都处理字符串) - 你的最后一点代码保存了我的生活!谢谢!这是我最终使用的: (w.AccountID ?? _AccountID) == _AccountID
  • 这应该被认为是 Linq to Entities(或 Linq to sql - 它也发生在那里)中的一个错误。这是在 Connect 上打开的吗?我找不到任何东西。
  • 好的,找到了,而且似乎在一些较新版本的 EF 中已修复:data.uservoice.com/forums/…
【解决方案2】:

我找到了几篇详细介绍同一问题的文章。不幸的是,到目前为止我还没有遇到过这个问题。不过这很有趣。

这里:

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

【讨论】:

  • 有用的链接。感谢发帖!
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    如果您想在 request['e'] == null 时从数据库中检索项目

    应该是的

    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

    因此,您的最后一个示例是有效的,因为您需要 2 种方法从数据库中获取数据。即如果 email 为 null 则为一个,如果 email == Request['e'] 则为一个

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-20
      相关资源
      最近更新 更多