在linq查询where子句中的vb.net iif条件

时间:2011-08-25 16:33:24

标签: vb.net linq sharepoint-2010

以下查询出了什么问题,我收到此错误: Nullable对象必须具有值。

  Dim subscriptionUsers = From inv In dataContext.Invoices.ToList Join u In dataContext.Users _
                                    On inv.Subscription Equals u.Subscription _
                                    Where inv.Id.Value = invoiceID _
                                    And Not u.Fund.Title.Contains("AGM") _
                                    And DirectCast(IIf(Not u.EndDate.HasValue, IIf(u.StartDate.Value <= inv.EndDate.Value, True, False), _
                                                    IIf((u.StartDate.Value >= inv.StartDate.Value And u.StartDate.Value <= inv.EndDate.Value) Or _
                                                (u.EndDate.Value >= inv.StartDate.Value And u.EndDate.Value <= inv.EndDate.Value) Or _
                                                (u.StartDate.Value < inv.StartDate.Value And u.EndDate.Value > inv.EndDate.Value), True, False)), Boolean) _
                                Group By Key = u.Fund.Title Into Group _
                                Select Fund = Key, UsersCount = Group.Count, Users = Group.ToList, _
                                SubFunds = (From a In dataContext.Allocations Where a.Fund.Title = Key Select a.Department.Title Distinct)

如果我在条件中删除了u.EndDate.Value,那么它可以正常工作。

这是堆栈跟踪:

at System.Nullable 1.get_Value() at SDBReports.InvoiceAllocationReportUserControl._Lambda$__4(VB$AnonymousType_0 2 $ VB $ It)    at System.Linq.Enumerable.WhereEnumerableIterator 1.MoveNext() at System.Linq.Lookup 2.Create [TSource](IEnumerable 1 source, Func 2 keySelector,Func 2 elementSelector, IEqualityComparer 1 comparer)    在System.Linq.GroupedEnumerable 4.GetEnumerator() at System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext()    在System.Linq.SystemCore_EnumerableDebugView`1.get_Items()

P.S。我使用SPMetal在SharePoint列表上生成实体类。

更清晰:

不要与u.EndDate.Value和inv.EndDate.Value混淆

这是u.EndDate.Hasvalue的真实部分:

 IIf((u.StartDate.Value >= inv.StartDate.Value And u.StartDate.Value <= inv.EndDate.Value) Or _
                                                (u.EndDate.Value >= inv.StartDate.Value And u.EndDate.Value <= inv.EndDate.Value) Or _
                                                (u.StartDate.Value < inv.StartDate.Value And u.EndDate.Value > inv.EndDate.Value), True, False)

这是假部分

IIf(u.StartDate.Value <= inv.EndDate.Value, True, False)

3 个答案:

答案 0 :(得分:5)

  • 使用If代替IIf。这是短路的(就像C#的条件运算符一样)并且会起作用,因为如果 HasValueTrue,条件 评估。不推荐使用IIf。永远不要使用它。

  • 此外,像If(condition, True, False)这样的表达式是荒谬的。只用condition替换它。

  • 最后,您需要再次使用AndAlso代替And - 短路才能发生。事实上,总是在条件中使用AndAlsoOrElse。在进行位操作时,请仅使用AndOr

  • DirectCast也是不必要的。

这给我们留下了一个简化的表达方式:

If(Not u.EndDate.HasValue, u.StartDate.Value <= inv.EndDate.Value), _
    (u.StartDate.Value >= inv.StartDate.Value AndAlso u.StartDate.Value <= inv.EndDate.Value) OrElse _
    (u.EndDate.Value >= inv.StartDate.Value AndAlso u.EndDate.Value <= inv.EndDate.Value) OrElse _
    (u.StartDate.Value < inv.StartDate.Value AndAlso u.EndDate.Value > inv.EndDate.Value))

但这个表达仍然太复杂了。您应该将其拆分,但首先使用查询中的Let将nullables中的值分配给某个临时变量。

答案 1 :(得分:1)

IIF评估两种结果,即使它只返回一种结果。因此,如果一个结果会导致异常(比如在没有的情况下访问可空的.Value),即使在IIF开头检查.HasValue,也会出现错误

答案 2 :(得分:0)

仅扩展IIF评估两部分。

尝试这样的代码:

IIF (True, msgbox("True"), msgbox("false"))

您将看到两个消息框。一个说“真”,一个说“假”。即使很清楚,你应该只触发True部分。