title: SignalR-Hub with Entity Framework returns wrong entity
body: <p>We have a problem with SignalR, which we currently cannot fully understand:</p>
  <h3> System </h3>
  <ul>
  <li>Framework: .NET Core 2.2</li>
  <li>Entity Framework: 2.2.6.0</li>
  </ul>
  <h3> Description of the problem </h3>
  We use SignalR to communicate with multiple clients. Via the connection the clients log on to the server with a unique key. We use the Entity Framework to access the database and select the client for the given key. Now it has happened for the second time that the wrong client entry was selected for the key during the access and therefore a wrong login with the wrong client has made. This happened when 
  about 8 clients have logged on via the hub at the same time.
  <br><br>
  We assume that there are problems with the DbContext because it is not Threadsafe and for some reason the same Context is accessed for multiple requests(maybe this can be solved by updating to Core 3.1). However, we would like to understand how this can happen or why it failes. How does it happen that accessing the DbContext via FirstOrDefaultAsync() returns the wrong client? The Hub and the DbContext should be instantiated per request?
  <br><br>
  <h3> Example </h3>
  The database currently contains several client entries:
  <pre><code>+------------+---------+
  |  ClientId  |   Key   |
  +------------+---------+
  | 1          | ABC     |
  | 2          | DEF     |
  | 3          | GHI     |
  | ...        | ...     |
  +------------+---------+
  </code></pre>
  <p>Now several clients log in with their key at the same time. In one of the cases the wrong client was returned:</p>
  <ul>
  <li>Key ABC returns Client 1</li>
  <li>Key DEF returns Client 2</li>
  <li><strong>Key GHI returns Client 1</strong></li>
  </ul>
  <h3> Structure </h3>
  Our server provides a SignalR-Hub, which is configured in the Startup:
  <pre><code>app.UseSignalR(routes =&gt;
  {
      routes.MapHub&lt;MyServerHub&gt;(&quot;/myhub&quot;);
  });
  </code></pre>
  <p>According to the documentation and source code, the hub should be registered as transient (<a href="https://docs.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-2.2" rel="nofollow noreferrer">Use hubs in SignalR for ASP.NET Core</a>).</p>
  <p>We also use a service in the hub, which is injected by DI.</p>
  <pre><code>public MyServerHub(IMyDatabaseService myDatabaseService)
  {
      _myDatabaseService = myDatabaseService;
  }
  </code></pre>
  <p>This service uses the DbContext:</p>
  <pre><code>private MyContext _myContext { get; }
  
  public MyDatabaseService(MyContext myContext)
  {
      _myContext= myContext;
  }
  </code></pre>
  <p>In the Startup the service and the DbContext is defined as Scoped:</p>
  <pre><code>services.AddScoped&lt;IMyDatabaseService, MyDatabaseService&gt;();
  
  services.AddDbContext&lt;MyContext&gt;(options =&gt; options.UseSqlServer(Configuration.GetConnectionString(&quot;DefaultConnection&quot;)));
  </code></pre>
  <p>In this method of hub we get the wrong client for a key:</p>
  <pre><code>    public async Task Connect(string key)
      {
          if (!string.IsNullOrWhiteSpace(key))
          {
              var client = await _myDatabaseService.GetByKey(key);
              if(client == null)
              {
                  await LogInformation(key, null, ConnectionEvent.ConnectWithInvalidKey);
                  await Clients.Caller.ReceiveInvalidKey();
                  return;
              }
              await Clients.Caller.ReceiveValidClientKey(client.Id);
              // This created following logs: 
              // &quot;ABC&quot; with id &quot;1&quot; at 09:25:47
              // &quot;GHI&quot; with id &quot;3&quot; at 09:34:03
              // &quot;GHI&quot; with id &quot;1&quot; at 10:06:02
              // &quot;ABC&quot; with id &quot;1&quot; at 10:06:03
              await LogInformation(key, client.Id, ConnectionEvent.ConnectedSuccessfully);
          }       
          else
              await Clients.Caller.ReceiveInvalidKey();
      }
  </code></pre>
  <p>Access to the DbContext in MyDatabaseService:</p>
  <pre><code>public async Task&lt;Client&gt; GetByKey(string key)
  {
      ClientRecord client = await _myContext.Clients.FirstOrDefaultAsync(p =&gt; p.Key == key);
  
      if (client == null)
          return null;
  
      return new Client
      {
          Id = client.Id,
          Key = client.Key
      };
  }
  </code></pre>
  <p><strong>EDIT: Logging Informations</strong>
  <br/>
  We log every call on the server hub. At 10:06:01 all connected SignalR clients (~18) were disconnected by with unkown reason (OnDisconnectedAsync was executed for each client). From 10:06:02 to 10:06:03 the clients automatically reconnected via our client application.</p>
  <pre><code>+------------+---------+-----------------------+---------------------+----------+
  |  ClientId  |   Key   |     ConnectionId      |       Event         |   Date   |
  +------------+---------+-----------------------+---------------------+----------+
  |     -      |    -    |jF2OqBVgBb1PLOiVRn8SPQ | SignalR-Connected   |  9:25:47 |
  |     1      |   ABC   |jF2OqBVgBb1PLOiVRn8SPQ |    Connected        |  9:25:47 |
  |    ...     |   ...   |...                    |      ...            |  ...     |
  |     -      |    -    |5fg1CwmZxFjGXF42zb-7BQ | SignalR-Connected   |  9:34:02 |
  |     3      |   GHI   |5fg1CwmZxFjGXF42zb-7BQ |    Connected        |  9:34:03 |
  |    ...     |   ...   |...                    |      ...            |  ...     |
  |     1      |    -    |jF2OqBVgBb1PLOiVRn8SPQ | SignalR-Disconnected| 10:06:01 |
  |     3      |    -    |5fg1CwmZxFjGXF42zb-7BQ | SignalR-Disconnected| 10:06:01 |
  |    ...     |   ...   |...                    |      ...            |  ...     |
  |     -      |    -    |2lZfpu08UerqbjwNkKLC3Q | SignalR-Connected   | 10:06:02 |
  |     -      |    -    |fg0oXdDAoKW3D4Ps6WOhhg | SignalR-Connected   | 10:06:02 |
  |     1      |   GHI   |fg0oXdDAoKW3D4Ps6WOhhg |    Connected        | 10:06:02 |
  |     1      |   ABC   |2lZfpu08UerqbjwNkKLC3Q |    Connected        | 10:06:03 |
  +------------+---------+-----------------------+---------------------+----------+
  </code></pre>