I am getting a deadlock error with below stored procedure - UpdateTestEvents.
Below is the xml deadlock report:
<deadlock>
 <victim-list>
  <victimProcess id="process1128b529468" />
 </victim-list>
 <process-list>
  <process id="process1128b529468" taskpriority="0" logused="0" waitresource="KEY: 7:72057594042777600 (fec90e3a2350)" waittime="2364" ownerId="158290173" transactionname="user_transaction" lasttranstarted="2017-12-17T01:20:45.553" XDES="0x1064ff98408" lockMode="U" schedulerid="9" kpid="6664" status="suspended" spid="57" sbid="2" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-12-17T01:20:45.547" lastbatchcompleted="2017-12-17T01:20:45.543" lastattention="1900-01-01T00:00:00.543" clientapp="EntityFramework" hostname="STAAP8895" hostpid="3616" loginname="XLAPSDBScoring" isolationlevel="read committed (2)" xactid="158290173" currentdb="7" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame procname="analytics.dbo.UpdateTestEvents" line="25" stmtstart="1836" stmtend="2132" sqlhandle="0x030007005e4b4b2a97304c0155a5000001000000000000000000000000000000000000000000000000000000">
UPDATE dbo.History
SET Ignore = 0
WHERE Number = @Number
    AND dbo.StringsMatch(@candidate, ACType, DEFAULT) =    </frame>
   </executionStack>
   <inputbuf>
Proc [Database Id = 7 Object Id = 709577566]   </inputbuf>
  </process>
  <process id="process1127e522ca8" taskpriority="0" logused="301092" waitresource="KEY: 7:72057594043039744 (c41e1b4226b6)" waittime="2364" ownerId="158290165" transactionname="user_transaction" lasttranstarted="2017-12-17T01:20:45.447" XDES="0xf8dc5ff8a8" lockMode="U" schedulerid="2" kpid="4888" status="suspended" spid="60" sbid="2" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-12-17T01:20:45.440" lastbatchcompleted="2017-12-17T01:20:45.437" lastattention="1900-01-01T00:00:00.437" clientapp="EntityFramework" hostname="STAAP1493" hostpid="3304" loginname="XLAPSDBScoring" isolationlevel="read committed (2)" xactid="158290165" currentdb="7" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame procname="analytics.dbo.UpdateTestEvents" line="32" stmtstart="2370" stmtend="3926" sqlhandle="0x030007005e4b4b2a97304c0155a5000001000000000000000000000000000000000000000000000000000000">
WITH ValidOriginsAndDestinations AS
(
      SELECT Origin FROM dbo.History
     WHERE Ignore = 0
        AND Number = @Number
     UNION ALL
         SELECT Destination FROM dbo.History
     WHERE Ignore = 0
        AND Number = @Number
)
UPDATE fh
SET Ignore = 0
FROM dbo.History AS fh
WHERE Number = @Number
    AND Ignore = 1
    AND 
    (       
        Origin IN (SELECT * FROM ValidOriginsAndDestinations)
        OR Destination IN (SELECT * FROM ValidOriginsAndDestinations)    </frame>
   </executionStack>
   <inputbuf>
Proc [Database Id = 7 Object Id = 709577566]   </inputbuf>
  </process>
 </process-list>
 <resource-list>
  <keylock hobtid="72057594042777600" dbid="7" objectname="analytics.dbo.History" indexname="PK_History" id="lockf50c41ac80" mode="X" associatedObjectId="72057594042777600">
   <owner-list>
    <owner id="process1127e522ca8" mode="X" />
   </owner-list>
   <waiter-list>
    <waiter id="process1128b529468" mode="U" requestType="wait" />
   </waiter-list>
  </keylock>
  <keylock hobtid="72057594043039744" dbid="7" objectname="xl_analytics_aviation.dbo.History" indexname="IX_History_Number" id="lock1128b5be680" mode="U" associatedObjectId="72057594043039744">
   <owner-list>
    <owner id="process1128b529468" mode="U" />
   </owner-list>
   <waiter-list>
    <waiter id="process1127e522ca8" mode="U" requestType="wait" />
   </waiter-list>
  </keylock>
 </resource-list>
</deadlock>
And the stored procedure looks like below:
CREATE PROCEDURE [dbo].[UpdateTestEvents]
    @Number varchar(50)
AS
DECLARE @tolerance decimal(10,10) = 0.15
DECLARE @totalEvents decimal(10,0) = (SELECT COUNT(*) FROM dbo.History fh WHERE fh.Number = @Number)
IF(@totalEvents = 0) RETURN
DECLARE @candidate VARCHAR(50) = 
    (SELECT TOP 1 ACType
    FROM dbo.History AS fh
    WHERE fh.Number = @Number
    GROUP BY ACType
    HAVING (COUNT(*) / @totalEvents) > @tolerance
    ORDER BY MAX(ActualDepartureTime) DESC)
SELECT @candidate
UPDATE dbo.History
SET Ignore = 0
WHERE Number = @Number
    AND dbo.StringsMatch(@candidate, ACType, DEFAULT) = 1;
WITH ValidOriginsAndDestinations AS
(
    SELECT Origin FROM dbo.History
     WHERE Ignore = 0
        AND Number = @Number
     UNION ALL
     SELECT Destination FROM dbo.History
     WHERE Ignore = 0
        AND Number = @Number
)
UPDATE fh
SET Ignore = 0
FROM dbo.History AS fh
WHERE Number = @Number
    AND Ignore = 1
    AND 
    (
        Origin IN (SELECT * FROM ValidOriginsAndDestinations)
        OR Destination IN (SELECT * FROM ValidOriginsAndDestinations)
    );
WITH Comfirmeddt AS
(
    SELECT a.lat, a.long FROM dbo.places AS a
    JOIN dbo.History AS fh
    ON     a.tidentifier = fh.Origin
        OR a.tidentifier = fh.Destination    
    WHERE fh.Number = @Number
    GROUP BY a.tidentifier, a.lat, a.long
)
UPDATE fh
SET Ignore = 0
FROM dbo.History AS fh
JOIN dbo.places AS a
ON a.tidentifier = fh.Origin
    OR a.tidentifier = fh.Destination
WHERE fh.Ignore = 1
AND fh.Number = @Number
AND EXISTS
(
    SELECT * FROM Comfirmeddt AS confirmed   
    WHERE
    (
        a.lat  < confirmed.lat  + 0.5 AND a.lat  > confirmed.lat  - 0.5 AND
        a.long < confirmed.long + 0.5 AND a.long > confirmed.long - 0.5
    )
)
GO
I am getting the below error: An error occurred while executing the command. See the inner exception for details. Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction
The index definition for [PK_History] is as below:
ALTER TABLE [dbo].[History] ADD  CONSTRAINT [PK_History] PRIMARY KEY CLUSTERED 
(
    [HashCode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
The Primary Key is HashCode Can someone suggest what I can do on this query to avoid such deadlocks in future.
Please find the table structure below:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[History](
    [HashCode] [varchar](50) NOT NULL,
    [FaID] [varchar](50) NOT NULL,
    [Number] [varchar](255) NOT NULL,
    [ActualArrivalTime] [datetime] NULL,
    [ActualDepartureTime] [datetime] NULL,
    [ACType] [varchar](10) NULL,
    [Destination] [varchar](40) NULL,
    [DestinationCity] [varchar](100) NULL,  
    [Origin] [varchar](40) NULL,
    [Ignore] [bit] NOT NULL DEFAULT ((1)),
    [FlNumber] [varchar](255) NULL,
    [DateAdded] [datetime] NOT NULL DEFAULT (getdate()),
 CONSTRAINT [History] PRIMARY KEY CLUSTERED 
(
    [HashCode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
ALTER TABLE [dbo].[History]  WITH CHECK ADD  CONSTRAINT [FK_Number] FOREIGN KEY([Number])
REFERENCES [dbo].[Number] ([Number])
GO
ALTER TABLE [dbo].[History] CHECK CONSTRAINT [FK_Number]
GO
The call to the stored procedure happends from .NET code and is achieved by entity framework. Below is the skeleton of the call to this stored procedure from application
using (var db = new NumberDbContext())
            {
foreach (var tn in Numbers)
            {
 db.UpdateTestEvents(tailNumber);
}
}
Please find the execution plan of the query below: https://www.brentozar.com/pastetheplan/?id=B1dGzUMQf
Also definition if IX_History_Number index:
CREATE NONCLUSTERED INDEX [IX_History_Number] ON [dbo].[History]
(
    [Number] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
 
     
     
    