Reputation: 3004
I'm using vb.net entities to access data in a sql server 2014 database.
I have a function which receives an "owner" object and if the owner has multiple current entries in the table, it's supposed to update the older entries to have a status of previous.
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
Here's a small dataset:
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
When I step through the code, there is only one entry in the prevOwner sequence.
When I run the sql profiler to view the linq query, the update statement is missing any as_of_date condition. Here's the query from the profiler:
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
Is my sql malformed, or am I missing something?
Upvotes: 2
Views: 49
Reputation: 109255
You seem to be expecting too much from Entity Framework. When EF updates database records it's always one record at a time. It doesn't do batch updates.
Here's what happens in your code (which I slightly modified):
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
As you see, at the time EF is ready for updating the database it doesn't have any knowledge as to how the modified entries were collected. The updates could be done much smarter, i.e. in statements that update batches of Owner
s that satisfy the condition p.As_Of_Date < owner.As_Of_Date
, but collecting data and updating them are totally independent operations in EF.
That's why you only see UPDATE statements in which one record is identified by its primary key. You may see many of them.
There are third-party libraries that enable batch (or bulk) updates, inserts, and deletes.
Upvotes: 2