Search code examples
asp.netsql-serverentity-frameworkasp.net-coreaspnetboilerplate

SQL Insert sent to server from entity framework does not create any record


I have a asp.net core web application with entity framework core. When I add a record to in EF and save changes, I don't see any record being created in SQL table.

So I open SQL Profiler to SQL profiler to debug and I can clearly see below insert statement in RPC:Starting and RPC:Completed event. There was no entity framework related exception thrown from my application. There was not SQL exception also. however, the record does not appear in AbpUsers table. But if I manually copy below statement and run in SSMS, the record can be created.

    exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [AbpUsers] ([AccessFailedCount], [AuthenticationSource], [ConcurrencyStamp], [CreationTime], [CreatorUserId], [DeleterUserId], [DeletionTime], [EmailAddress], [EmailConfirmationCode], [IsActive], [IsDeleted], [IsEmailConfirmed], [IsLockoutEnabled], [IsPhoneNumberConfirmed], [IsTwoFactorEnabled], [LastLoginTime], [LastModificationTime], [LastModifierUserId], [LockoutEndDateUtc], [Name], [NormalizedEmailAddress], [NormalizedUserName], [Password], [PasswordResetCode], [PhoneNumber], [SecurityStamp], [Surname], [TenantId], [UserName])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27, @p28);
SELECT [Id]
FROM [AbpUsers]
WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();

',N'@p0 int,@p1 nvarchar(64),@p2 nvarchar(4000),@p3 datetime2(7),@p4 bigint,@p5 bigint,@p6 datetime2(7),@p7 nvarchar(256),@p8 nvarchar(328),@p9 bit,@p10 bit,@p11 bit,@p12 bit,@p13 bit,@p14 bit,@p15 datetime2(7),@p16 datetime2(7),@p17 bigint,@p18 datetime2(7),@p19 nvarchar(32),@p20 nvarchar(256),@p21 nvarchar(32),@p22 nvarchar(128),@p23 nvarchar(328),@p24 nvarchar(4000),@p25 nvarchar(4000),@p26 nvarchar(32),@p27 int,@p28 nvarchar(32)',@p0=0,@p1=N'LDAP',@p2=N'215f3645-7546-4808-a1ec-141bf634f818',@p3='2017-07-06 16:54:41.5659350',@p4=NULL,@p5=NULL,@p6=NULL,@p7=N'some email address',@p8=NULL,@p9=1,@p10=0,@p11=1,@p12=1,@p13=0,@p14=0,@p15=NULL,@p16=NULL,@p17=NULL,@p18=NULL,@p19=N'first name',@p20=N'some email address',@p21=N'SESA405265',@p22=N'AQAAAAEAACcQAAAAENF58O2EZ7lsnJuBuoW4hHI9D5dKdf37Hgzcc/VH9eZ5J4x2966Qp2e464o7gfs8KQ==',@p23=NULL,@p24=NULL,@p25=N'34dc38d9-64df-2795-f645-39e029489a9d',@p26=N'last name',@p27=NULL,@p28=N'some id'

Below is the code where the record was inserted in entity framework. Full source code can be found here: https://github.com/aspnetboilerplate/module-zero/blob/dev/src/Abp.ZeroCore/Authorization/AbpLoginManager.cs

using (UnitOfWorkManager.Current.SetTenantId(tenantId))
                    {
                        var user = await UserManager.AbpStore.FindByNameOrEmailAsync(tenantId, userNameOrEmailAddress);
                        if (user == null)
                        {
                            user = await source.Object.CreateUserAsync(userNameOrEmailAddress, tenant);

                            user.TenantId = tenantId;
                            user.AuthenticationSource = source.Object.Name;
                            user.Password = _passwordHasher.HashPassword(user, Guid.NewGuid().ToString("N").Left(16)); //Setting a random password since it will not be used
                            user.NormalizedEmailAddress = user.EmailAddress;
                            user.NormalizedUserName = user.UserName;
                            if (user.Roles == null)
                            {
                                user.Roles = new List<UserRole>();
                                foreach (var defaultRole in RoleManager.Roles.Where(r => r.TenantId == tenantId && r.IsDefault).ToList())
                                {
                                    user.Roles.Add(new UserRole(tenantId, user.Id, defaultRole.Id));
                                }
                            }

                            await UserManager.AbpStore.CreateAsync(user);
                        }
                        else
                        {
                            await source.Object.UpdateUserAsync(user, tenant);

                            user.AuthenticationSource = source.Object.Name;

                            await UserManager.AbpStore.UpdateAsync(user);
                        }

                        await UnitOfWorkManager.Current.SaveChangesAsync();

                        return true;
                    }

Solution

  • Thanks to Dan Guzman's suggestions, I started to look for places where rollback could have happened in my code.

    So here is what happened. The TryLoginFromExternalAuthenticationSources method created a user with the userName (e.g. Tom). but on the next line of the code, the user was searched using 'domain\Tom' format, which results in the null result. therefore the login result was considered failed and an exception was thrown somewhere very far from this place, causing the transaction being rolledback.

                    var loggedInFromExternalSource = await TryLoginFromExternalAuthenticationSources(userNameOrEmailAddress, plainPassword, tenant);
    
                var user = await UserManager.AbpStore.FindByNameOrEmailAsync(tenantId, userNameOrEmailAddress);
                if (user == null)
                {
                    return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.InvalidUserNameOrEmailAddress, tenant);
                }