如何在Linq to SQL中优雅地处理null外键?

时间:2008-10-26 22:07:23

标签: vb.net linq-to-sql

在我的数据库中,特许权与公司有多对一的关系(每个特许权都有一个FirmID)。 SqlMetal捕获了这种关系并生成了适当的类,因此每个Concession都有一个Firm元素。我绑定了一个查询(简化为此处),该查询返回特许权列表以及相应公司的信息:

From c as Concession in Db.Concessions _
Select _
   c.ConcessionID, _
   c.Title, _
   c.Firm.Title

问题在于,在某些情况下,特许权没有被分配给公司(c.FirmID为空),所以c.Firm什么都没有,我得到Object not set to an instance等。

我可以通过以下方式进行连接来解决这个问题:

From c As Concession In Db.Concessions _
Join f As Firm In Db.Firms On f.FirmID Equals c.FirmID _
Select _
    c.ConcessionID, _
    c.Title, _
    Firm_Title = f.Title 

当FirmID为null(Firm_Title只是一个空字符串)时,这不会引发错误,但它不优雅:它不是面向对象的,并且它没有利用Linq to SQL所具有的所有关系智能已被捕获。

有没有更优雅的方式来处理这种情况?

5 个答案:

答案 0 :(得分:3)

你在哪里得到错误?

我刚刚完成了类似的LINQ查询(在VB.Net中),并且工作正常(将Title设置为null)

您稍后将不得不处理标题为null,但这不是LINQ问题。 甚至可以在C#中轻松处理。

from c in Db.Concessions
select 
{   
     c.ConcessionID, 
     c.Title, 
     Title = c.Firm.Title ?? ""
}

Vb.net中的等价物是使用Iif(),但我无法使用它。

答案 1 :(得分:2)

你的第二个例子是进行内部联接。它不会返回具有null FirmID的特许权。在这种情况下,您想要进行外连接:

http://msdn.microsoft.com/en-us/vbasic/bb737929.aspx#grpjoinleftout

答案 2 :(得分:1)

@James Curran:我在任何时候实际执行查询时都会收到错误 - 例如如果我将网格数据绑定到它,或者我将.ToList应用于它。

VB.NET有一个新的真正的三元语法(仍然比C#更冗长)。这实际上有效:

From c As Concession In db.Concessions _
Select _
    c.ConcessionID, _
    c.Title, _
    Firm_Title = If(c.Firm IsNot Nothing, c.Firm.Title, String.Empty) _

我对这种方法并不满意 - 对于我可能在外表中使用的每个字段都要做到这一点很痛苦。我很想知道为什么你的查询正在运行而我的查询没有 - 你的DataContext是由SqlMetal生成的吗?是从数据库中推断出的关系吗?

答案 3 :(得分:0)

他正在工作,因为他选择的是空字符串而不是空关系。

答案 4 :(得分:0)

在对象构造函数中处理它

Public Property office() As String
            Get
                Return _office
            End Get
            Set(ByVal value As String)
                If value IsNot Nothing Then
                    _office = value
                Else
                    _office = String.Empty
                End If
            End Set
        End Property