JonPSmith / EfCore.TestSupport

Tools for helping in unit testing applications that use Entity Framework Core
https://www.thereformedprogrammer.net/new-features-for-unit-testing-your-entity-framework-core-5-code/
Other
353 stars 53 forks source link

Error while saving with Update method #7

Closed CrahunGit closed 6 years ago

CrahunGit commented 6 years ago

When using update to save the entity the test will fail. If you just change properties and save everuthing works fine.

The erros says: Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException : Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.

JonPSmith commented 6 years ago

Hi @CrahunGit,

Can you show me your code, and if possible the logging output (see the Wiki page for info on how to capture and output EF core logging). Then I can comment.

CrahunGit commented 6 years ago

Ok, my test code is:

        public async Task Update(Tecnician item)
        {
            if (item == null)
                return;

            Context.Update(item);
            await Context.SaveChangesAsync();
        }

Now the test tries to update any tecnician but it throws exception. The test is:

        [Fact]
        public async Task UpdateTecnician_NonExistingTecnician1_CallUpdatesTecnician1()
        {
            //Arrange
            Tecnician tecnician = new Tecnician { Id = "Tec1", CodTecNavigation = new Place { Id = "Tec1" } };
            DbContextOptions<PlaceContext> options = SqliteInMemory.CreateOptions<PlaceContext>();
            using (PlaceContext context = new PlaceContext(options))
            {
                context.CreateEmptyViaWipe();

                ITecnicianRepository repository = new TecnicianRepository(context);
                TecnicianService service = new TecnicianService(context, repository);

                //Act
                await service.UpdateTecnician(tecnician);

                //Assert
                context.Tecnician.FirstOrDefault().Should().NotBeNull();
            }
        }

Unafortunley the logger is not working on NET 4.7.1, it returns null items while using it on the loop.

JonPSmith commented 6 years ago

hi @CrahunGit,

I think I know what is happening here. I assume the Tecnician's primary key is Id. If so then you have an empty database, and when you try to update EF Core will output SQL something like this:

UPDATE 
    dbo.Tecnicians SET SomeColumn = @p0
WHERE Id= @p1

Because you database is empty it will not find an row with the primary key of "Tec1" and it will fail with the error you saw. Does that make sense?

Try adding a Tecnician with a given key and then try update with a new Tecnician with the same key. I think that will work.

CrahunGit commented 6 years ago

Yes, this what's is happening, the database is empty as this is the test case. It makes sense your assumption. And yes, if database is not empty test passes as it should be. The normal operation in prouduction is it inserts it if it doesn't exist.

JonPSmith commented 6 years ago

Good. I am closing this.