Why select holds exclusive lock on table? I'm currently struggling with a deadlock (graph) in our application.

Both processes execute the same query:

exec sp_executesql N'SELECT [GroupBy1].[A1] AS [C1]
                     FROM (SELECT COUNT(1) AS [A1]
                           FROM   [dbo].[Batch] AS [Extent1]
                           WHERE ([Extent1].[BatchGroupId] = @p__linq__0) 
                           AND   ([Extent1].[Status] &lt;&gt; @p__linq__1)
                          )  AS [GroupBy1]',
                   N'@p__linq__0 int, @p__linq__1 int', @p__linq__0=6, @p__linq__1=8515


Here is the index definition:

CREATE NONCLUSTERED INDEX IX_Batch_BatchGroupId_Status
ON dbo.Batch
(
    BatchGroupId asc,
    Status asc
)
There are data modification statements within the same transaction.

indexname = "IX_Batch_BatchGroupId_Status"
id = "lock2aa71e32d80"
mode = "X"
associatedObjectId = "72057594166968320"

Exclusive locks associated with those data modifications will be held until the transaction is complete.

See the Deadlock Troubleshooting posts by Bart Duncan.