dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.8k stars 3.2k forks source link

The given key was not present in the dictionary (System.Collections.Generic.KeyNotFoundException) #9572

Closed mheilimo closed 2 years ago

mheilimo commented 7 years ago

I my trying (EF core 2.0) to fetch users with Roles from db (my own EF core objects in db), but this fails for some (about 10%) users with this cryptic error - 'The given key was not present in the dictionary' (System.Collections.Generic.KeyNotFoundException) - can you please improve this error message - how I can debug this because there is no info what really failing?

I already checked all similar bugs report earlier and mine is not same than already resolved (I don't have any same name index in db for example). I can't send you full my commercial project to reproduce this, but I do my best to copy paste most important codes here if you will get idea what is wrong and why EF core failing to do what it should do: my call to to get users is this:

IQueryable<User> users = contextStore.GetContext().Users.Include(usr => usr.ActiveRoleRelations).
                                         ThenInclude(rolRel => rolRel.User).
                                         Include(usr => usr.ActiveRoleRelations).
                                         ThenInclude(rolRel => rolRel.SubjectUser).
                                         Include(usr => usr.ActiveRoleRelations).
                                         ThenInclude(rolRel => rolRel.SubjectOrganisationUnit).
                                         Include(usr => usr.Subscriptions).
                                         ThenInclude(subs => subs.Type).
                                         Include(usr => usr.Subscriptions).
                                         ThenInclude(subs => subs.User).
                                         ThenInclude(subUser => subUser.OrganisationUnit).
                                         Include(usr => usr.LicenseKeys).
                                         ThenInclude(licKey => licKey.Subscription).
                                         ThenInclude(subs => subs.User).
                                         ThenInclude(subUser => subUser.OrganisationUnit).
                                         Include(usr => usr.LicenseKeys).
                                         ThenInclude(licKey => licKey.Subscription).
                                         ThenInclude(subs => subs.Tags).
                                         Include(usr => usr.LicenseKeys).
                                         ThenInclude(licKey => licKey.Subscription).
                                         ThenInclude(subs => subs.Type).
                                         ThenInclude(subsType => subsType.Tags).
                                         Include(usr => usr.OrganisationUnit).
                                         Include(usr => usr.Tags).
                                         Include(usr => usr.CountryCodeNavigation).
                                         Include(usr => usr.UserTrainingPlans).
                                         Include(usr => usr.PersonalDatas).
                                         Include(usr => usr.Accounts).
                                         ThenInclude(account => account.Logins)
                                         .ThenInclude(login => login.ExternalLoginAutToken).
                                         Include(usr => usr.ExternallyManagedSubscriptions).
                                         ThenInclude(extSubLinks => extSubLinks.Subscription).
                                         ThenInclude(extSubLinksSubs => extSubLinksSubs.Type);

I actually investigated it already that it work well without these RoleRelations (ActiveRoleReleations) relations - actually it is enought to have this first 'Users.Include(usr => usr.ActiveRoleRelations)' to get it crash so I guest that problem is in RoleRelation object.

My RoleRelation object is very simple:

 public partial class RoleRelation : MyBaseObject
    {
        public RoleRelation()
        {
        }

        public Guid UserGUID { get; set; }
        public Guid? SubjectUserGUID { get; set; }
        public Guid? SubjectOrgUnitGUID { get; set; }
        public string RoleName { get; set; }
        public DateTime? Expiring { get; set; }

        public virtual Role Role { get; set; }

        public virtual OrganisationUnit SubjectOrganisationUnit { get; set; }
        public virtual User SubjectUser { get; set; }
        public virtual User User { get; set; }
}

MyBaseObject is:

 using System.ComponentModel.DataAnnotations.Schema;

    [NotMapped]
    public abstract class MyBaseObject
    {

        public Guid GUID{ get; set; }

        public DateTime Modified { get; set; }

        public DateTime Created { get; set; }           
    }    

RoleRelations object relations are defined this way:

   modelBuilder.Entity<RoleRelation>(
                entity =>
                    {
                        entity.ToTable("RoleRelation");                        
                        entity.HasIndex(e => e.RoleName).HasName("IX_RoleRelation_RoleName");
                        entity.HasIndex(e => e.SubjectOrgUnitGUID).HasName("IX_RoleRelation_SubjectOrgUnitGUID"); ;
                        entity.HasIndex(e => e.SubjectUserGUID).HasName("IX_RoleRelation_SubjectUserGUID"); ;
                        entity.HasIndex(e => e.UserGUID).HasName("IX_RoleRelation_UserGUID"); ;

                        entity.Property(e => e.Expiring).HasColumnType("datetime");
                        entity.Property(e => e.RoleName).HasColumnType("varchar(255)");
                        entity.Property(e => e.SubjectOrgUnitGUID).HasColumnName("SubjectOrgUnitGUID");
                        entity.Property(e => e.SubjectUserGUID).HasColumnName("SubjectUserGUID");
                        entity.Property(e => e.UserGUID).HasColumnName("UserGUID");

                        entity.HasOne(d => d.Role).WithMany(p => p.RoleRelations).HasForeignKey(d => d.RoleName);
                        entity.HasOne(d => d.SubjectOrganisationUnit)
                            .WithMany(p => p.SubjectRoleRelations)
                            .HasForeignKey(d => d.SubjectOrgUnitGUID);
                        entity.HasOne(d => d.SubjectUser).WithMany(p => p.SubjectRelations).HasForeignKey(d => d.SubjectUserGUID);
                        entity.HasOne(d => d.User).WithMany(p => p.ActiveRoleRelations).HasForeignKey(d => d.UserGUID); 
                    });

and all MyObject are defined liked this to get primary key and modified and created datetimes (TEntity is MyObject based class):

 modelBuilder.Entity<TEntity>()
                            .HasKey(e => e.GUID);

                modelBuilder.Entity<TEntity>()
                            .Property(e => e.GUID)
                            .ValueGeneratedNever();

                modelBuilder.Entity<TEntity>().Property(e => e.Created);

                modelBuilder.Entity<TEntity>().Property(e => e.Modified);

This is my role relationTable definition:

CREATE TABLE [dbo].[RoleRelation] (
    [GUID]               UNIQUEIDENTIFIER NOT NULL,
    [Expiring]           DATETIME         NULL,
    [Modified]           DATETIME2 (7)    NOT NULL,
    [RoleName]           VARCHAR (255)    NULL,
    [SubjectOrgUnitGUID] UNIQUEIDENTIFIER NULL,
    [SubjectUserGUID]    UNIQUEIDENTIFIER NULL,
    [UserGUID]           UNIQUEIDENTIFIER NOT NULL,
    [Created]            DATETIME2 (7)    NOT NULL
);

GO
CREATE NONCLUSTERED INDEX [IX_RoleRelation_RoleName]
    ON [dbo].[RoleRelation]([RoleName] ASC);

GO
CREATE NONCLUSTERED INDEX [IX_RoleRelation_SubjectOrgUnitGUID]
    ON [dbo].[RoleRelation]([SubjectOrgUnitGUID] ASC);

GO
CREATE NONCLUSTERED INDEX [IX_RoleRelation_SubjectUserGUID]
    ON [dbo].[RoleRelation]([SubjectUserGUID] ASC);

GO
CREATE NONCLUSTERED INDEX [IX_RoleRelation_UserGUID]
    ON [dbo].[RoleRelation]([UserGUID] ASC);

GO
CREATE NONCLUSTERED INDEX [IX_RoleRelation_Modified]
    ON [dbo].[RoleRelation]([Modified] ASC);

GO
CREATE NONCLUSTERED INDEX [IX_RoleRelation_Created]
    ON [dbo].[RoleRelation]([Created] ASC);

GO
ALTER TABLE [dbo].[RoleRelation]
    ADD CONSTRAINT [PK_RoleRelation] PRIMARY KEY CLUSTERED ([GUID] ASC);

GO
ALTER TABLE [dbo].[RoleRelation]
    ADD CONSTRAINT [FK_RoleRelation_rle_RoleName] FOREIGN KEY ([RoleName]) REFERENCES [dbo].[rle] ([Nme]);

GO
ALTER TABLE [dbo].[RoleRelation]
    ADD CONSTRAINT [FK_RoleRelation_OrganisationUnit_SubjectOrgUnitGUID] FOREIGN KEY ([SubjectOrgUnitGUID]) REFERENCES [dbo].[OrganisationUnit] ([GUID]);

GO
ALTER TABLE [dbo].[RoleRelation]
    ADD CONSTRAINT [FK_RoleRelation_usr_UserGUID] FOREIGN KEY ([UserGUID]) REFERENCES [dbo].[usr] ([GUID]) ON DELETE CASCADE;

Exception message: An error has occurred - The given key was not present in the dictionary

System.Collections.Generic.KeyNotFoundException

Stack trace: at System.Collections.Generic.Dictionary2.get_Item(TKey key) at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.System.IDisposable.Dispose() at Microsoft.EntityFrameworkCore.Query.QueryContext.Dispose() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.Dispose() at System.Linq.Enumerable.First[TSource](IEnumerable1 source) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass17_01.b__0(QueryContext qc) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression) at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable1 source) at Cloud.MainWebAPI.Services.GenericServiceGUID4.GetFirstOrDefaultByGUID(Guid guid, ContextStore1 contextStore, ORMLoadEnums ormLoadSettings) in C:\gitroot\omegawave\webapi\API\MainWebAPI\Source\Cloud.MainWebAPI\Services\GenericServiceGUID.cs:line 109 at Cloud.MainWebAPI.Services.GenericServiceGUID4.Get(Guid id, Boolean isThrowIfNotExist, ContextStore1 contextStore, ORMLoadEnums ormLoadSettings) in C:\gitroot\omegawave\webapi\API\MainWebAPI\Source\Cloud.MainWebAPI\Services\GenericServiceGUID.cs:line 139 at Cloud.MainWebAPI.Controllers.UserController.ShowDetails(Guid id) in [Mypath]\webapi\API\MainWebAPI\Source\Cloud.MainWebAPI\Controllers\UserController.cs:line 323 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ApiControllerActionInvoker.d0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.d2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()

Steps to reproduce

If you can't reproduce this issue can you even improve error message that I can find reason for error myself. It can't be that all bug report have to have full big project with it because there is no change to isolate problem from big project if error messages are in this level.

I am more than happy to give you more info if needed to resolve this bug.

Further technical details

EF Core version: 2.0 (latests) Database Provider: Microsoft.EntityFrameworkCore.SqlServer Operating system: Windows 10 IDE: Visual Studio 2017 15.3.1 Preview 1.0

smitpatel commented 7 years ago

duplicate of #8817 This bug was fixed in EF Core 2.0 RTM release. Not sure why it is still giving error.

anpete commented 7 years ago

@mheilimo Are you sure you are running against 2.0 RTM? That stack trace looks like the code as it was before the fix.

mheilimo commented 7 years ago

Actually I used call Update-Package Microsoft.EntityFrameworkCore and it looks that all was updated properly (it wasn't anymore preview what I got) - when I checked dll version it wasn't upgraded properly in one project. After removing and installing it works properly and this issue is also gone. This happen already second time that update-package don't do update properly. Did you see this issue earlier?

So you can close this - thanks for you help!