2011-04-26 103 views
10

我最近已将此代码迁移到实体框架4并且失败。显然,如果状态没有值,则返回所有匹配,如果它具有与user.StatusID == 1相匹配的值。实体框架中的简单条件LINQ查询4

return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       (!status.HasValue || user.StatusID == 1) 
       ); 

异常返回:

ArgumentException: The specified value is not an instance of type 'Edm.Int32' 
Parameter name: value 

但是,移除条件测试,它工作正常:

return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       user.StatusID == 1 
       ); 

任何想法?如何在EF 4中执行条件测试?当然,如果线条不分开?我在Linq to Sql中一次又一次地使用这些条件测试;对于EF 4中不起作用的原因真的很奇怪。一定有一些简单的错误,或许在EF 4.0中有一个推荐的替代方法。

感谢您的帮助球员,
格雷厄姆

+0

什么'Edm.Int32'?是你自己实现的'System.Int32'吗? – Stecya 2011-04-26 11:12:23

+1

@Stecya:http://msdn.microsoft.com/en-us/library/bb387164.aspx,似乎是EF的一些内部特征。 – Euphoric 2011-04-26 11:14:05

回答

5

好吧,我解决了两件事的结合。

  1. 做一个简单的空测试。
  2. 检测本地铸件status变量没有.Value方法。

两者都必须到位,否则它将继续失败,并出现错误!这将是很好的测试值属性,但我想查询必须非常简单 - 非常有趣!

return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       (status == null || user.StatusID == (int) status) 
       ); 

我将等待更好的实现,否则接受我自己的答案。但感谢大家的帮助。

+0

EF看起来越来越好...感谢您的解决方案,它今天咬我一口。 – greenoldman 2011-08-04 09:14:02

0

是什么status.HasValue?如果状态是User一个领域,你应该这样称呼它:user.status.HasValue

如此简单的做到这些:

if(status.HasValue) 
    return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       user.StatusID == 1 
       ); 

    return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password 
       ); 
+0

嗨Farzin,它是一个可以为空的int,而不是封闭方法的一个字段。编辑 – GONeale 2011-04-26 11:04:17

+0

,我知道这不是一个常用的解决方案,但适合你! ;) – 2011-04-26 11:08:37

+0

Eek,维护两个查询。不,谢谢,但无论如何感谢=) – GONeale 2011-04-26 11:10:26

0

我想你应该附上user.StatusID == 1组附加括号的,因为我认为目前EF试图应用||操作状态.HasValue和user.StatusId,然后将结果与1进行比较。

+0

唉,没有运气。虽然好想法。 – GONeale 2011-04-26 11:05:52

2

如何为!status.HasValue创建单独的变量并在查询中使用它?

我想这里的问题是,EF试图将您的状态变量作为参数传递到查询中,然后在SQL本身中执行逻辑。尝试检查生成的SQL是什么。

+0

哇,通过,声明'var test =!status.HasValue'然后测试测试。但它不好。然而,它让我尝试了我能想到的每一个投射和包围技巧,因为如果它像这样工作,它可以在线工作,它们都解决错误。哼。还有什么想法? – GONeale 2011-04-26 11:14:44

+0

我认为问题在于'status'不是int;并且它在一个构造中比较一个枚举和一个int类型时感到困惑。没有铸件可以工作,因为它是可空的:( – GONeale 2011-04-26 11:17:51

2

在where子句中执行空检查的另一种方法是分离出可选参数并只在需要时才应用它。

例如

var data = users.Where(
     user => 
      user.Username == username && 
      user.EncryptedPassword == password 
     ); 

    if (status.HasValue) 
    { 
     data = data.Where(user => user.StatusID == status.Value); 
    } 

    return data.FirstOrDefault(); 

我不认为它会提供比目前的解决方案,而不是多一点的可读性。

+0

感谢您的想法 – GONeale 2011-04-27 06:02:40

0

在第一galance它在我的脑海appeare这样的:

return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       (status == null || user.StatusID == 1) 
       ); 

,但是当我看它更多的我觉得这是错了,所以怎么样?

return users.SingleOrDefault(
    user => 
    user.Username == username && 
    user.EncryptedPassword == password && 
    status != null && 
    user.StatusID == 1) 
); 

背后它究竟是什么商业逻辑?

+0

啊,好吧,您的第二个查询将始终强制一个状态不一定是这样的,'status'可能是'null',在这种情况下,我想获取所有的条目,这就是为什么我使用'||'操作符 – GONeale 2011-04-27 06:04:15

1

好像你已经找到了解决办法...

然而,仅供参考......我有在VS以下行没有问题2010

Nullable<int> status = 0; 
    String username = "Alexandre 2"; 

    var test = _context.Contacts.SingleOrDefault(c => c.FirstName == username && (!status.HasValue || c.ContactID == 1)); 

我没有得到任何错误,联系对象我期望是返回...所以如果有的话,这让我想知道什么是你的用户类型.StatusID字段?

祝你好运

+0

这是EF4吗? – GONeale 2011-04-27 06:02:12