Linq更新了额外的行

时间:2017-10-11 20:35:57

标签: sql-server vb.net linq

我使用vb.net实体访问sql server 2014数据库中的数据。

我有一个接收"所有者的功能"对象,如果所有者在表中有多个当前条目,则它应该更新旧条目以具有先前的状态。

Private Shared Sub CreatePreviousOwners(currentOwners As List(Of Owner), prop As compProp)
Dim names = prop.GetVendorsNames()
Using context = New GovernContext()
            Dim sameOwners = From v In currentOwners
                             Where names.Any(Function(o) o.Na_Id = v.Na_Id)
                             Select v
           If sameOwners.Count > 0 Then
                For Each owner In sameOwners
                    'Find all entries prior to the newest
                    Dim prevOwner = From p In context.Owner
                                    Where p.Status = "O" _
                                    And owner.Na_Id = p.Na_Id _
                                    And p.P_Id = prop.p_id _
                                    And p.As_Of_Date < owner.As_Of_Date 
                                    Select p
                    'Update all found entries to previous
                    For Each own As Owner In prevOwner
                        own.Status = "P"
                    Next
                Next
                context.SaveChanges()
            End If
        End Using
    End Sub

这是一个小数据集:

p_id    na_id   AS_OF_DATE              status
596     589494  2008-09-10 00:00:00.000 O
596     589494  2017-08-02 00:00:00.000 O
596     1453364 2017-08-02 00:00:00.000 P

当我单步执行代码时,prevOwner序列中只有一个条目。

当我运行sql探查器来查看linq查询时,update语句缺少任何as_of_date条件。 这是来自探查者的查询:

exec sp_executesql N'UPDATE [dbo].[Owner]
SET [Status] = @0
WHERE (([P_Id] = @1) AND ([Na_Id] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 int',@0=N'P',@1=596,@2=589494

我的sql是否格式错误,或者我遗失了什么?

1 个答案:

答案 0 :(得分:2)

您似乎对实体框架抱有太多期待。当EF更新数据库记录时,它总是一次一条记录。它不进行批量更新。

以下是您的代码中发生的情况(我稍作修改):

Private Shared Sub CreatePreviousOwners(currentOwners As List(Of Owner), prop As compProp)
    Dim names = prop.GetVendorsNames()
    Using context = New GovernContext()

        'Runs a SQL SELECT query and creates a list of owners
        Dim sameOwners = (From v In currentOwners
                         Where names.Any(Function(o) o.Na_Id = v.Na_Id)
                         Select v).ToList()

        For Each owner In sameOwners
            'Find all entries prior to the newest

            'Runs another SQL SELECT query
            Dim prevOwner = From p In context.Owner
                            Where p.Status = "O" _
                            And owner.Na_Id = p.Na_Id _
                            And p.P_Id = prop.p_id _
                            And p.As_Of_Date < owner.As_Of_Date 
                            Select p
            'Update all found entries to previous

            'Executes the SELECT query and loops through the results
            For Each own As Owner In prevOwner

                'Adds a modified entry to EF's change tracker
                own.Status = "P"

            Next
        Next

        'Runs update statements for each modified entry in the change tracker
        context.SaveChanges()

    End Using
End Sub

如您所见,在EF准备更新数据库时,它不知道如何收集修改后的条目。更新可以更加智能,即在更新满足条件Owner的批量p.As_Of_Date < owner.As_Of_Date的语句中,但收集数据和更新它们是EF中完全独立的操作。

这就是为什么你只看到UPDATE语句,其中一个记录由其主键标识。你可能会看到很多

有第三方库可以批量(或批量)更新,插入和删除。