JasperFx / marten

.NET Transactional Document DB and Event Store on PostgreSQL
https://martendb.io
MIT License
2.84k stars 450 forks source link

mt_delete set to null instead of false #2972

Closed israelolcha closed 8 months ago

israelolcha commented 8 months ago

I have a class called Facility that I push using MartenStore.BulkInsertAsync method.

The scheme is defined using soft delete as follow:

services.AddMarten(options =>
{
            options.Connection(connectionString);
            options.Logger(new ConsoleMartenLogger());

            options.UseDefaultSerialization(
                serializerType: SerializerType.SystemTextJson,
                enumStorage: EnumStorage.AsString,
                casing: Casing.CamelCase
            );

            options.DatabaseSchemaName = "my_db";
            options.Schema.For<Facility>().SoftDeleted().Identity(x => x.Key).GinIndexJsonData().UniqueIndex(x => x.Code);
}

When I try to query facilities using LINQ I get 0 results: var facilities1 = session.Query<Facility>().Where(x => x.Code == "REV").ToList();

When doing the same using SQL I get 1 result (Correct) var facilities11 = await session.QueryAsync<Facility>("where d.data->> 'code' = ?", "REV");

From checking the generate SQL from LINQ i can see there is a check for column mt_delete = false but the inserted rows have this column set to null and therefor no facilities are found

using a session with store(IEnumerable models) is setting the mt_Deleted to false as it should

jeremydmiller commented 8 months ago

Still going to need some more information from you because this "works on my box". All of these tests pass on the master branch:

using System.Linq;
using System.Threading.Tasks;
using Marten;
using Marten.Testing.Documents;
using Marten.Testing.Harness;
using Shouldly;
using Xunit;

namespace DocumentDbTests.Bugs;

public class Bug_2972_soft_deletes_plus_bulk_inserts : BugIntegrationContext
{
    [Fact]
    public async Task store_plus_soft_deletes()
    {
        StoreOptions(opts => opts.Schema.For<Target>().SoftDeleted());

        var targets = Target.GenerateRandomData(100).ToArray();

        theSession.Store(targets);
        var goodTargets = Target.GenerateRandomData(3).ToArray();
        theSession.Store(goodTargets);
        await theSession.SaveChangesAsync();
        foreach (var target in goodTargets)
        {
            theSession.Delete(target);
        }

        await theSession.SaveChangesAsync();

        var all = await theSession.Query<Target>().ToListAsync();

        all.Count.ShouldBe(100);
    }

    [Fact]
    public async Task bulk_insert_plus_soft_deletes()
    {
        StoreOptions(opts => opts.Schema.For<Target>().SoftDeleted());

        await theStore.BulkInsertAsync(Target.GenerateRandomData(100).ToArray());

        var goodTargets = Target.GenerateRandomData(3).ToArray();
        theSession.Store(goodTargets);
        await theSession.SaveChangesAsync();
        foreach (var target in goodTargets)
        {
            theSession.Delete(target);
        }

        await theSession.SaveChangesAsync();

        var all = await theSession.Query<Target>().ToListAsync();

        all.Count.ShouldBe(100);
    }

    [Fact]
    public void bulk_insert_plus_soft_deletes_sync()
    {
        StoreOptions(opts => opts.Schema.For<Target>().SoftDeleted());

        theStore.BulkInsert(Target.GenerateRandomData(100).ToArray());

        var goodTargets = Target.GenerateRandomData(3).ToArray();
        theSession.Store(goodTargets);
        theSession.SaveChanges();
        foreach (var target in goodTargets)
        {
            theSession.Delete(target);
        }

        theSession.SaveChanges();

        var all = theSession.Query<Target>().ToList();

        all.Count.ShouldBe(100);
    }
}
jeremydmiller commented 8 months ago

We can't reproduce the error, I'm closing this (for now).

nicholascm commented 1 month ago

@jeremydmiller - somewhat related here we noticed that if for some reason, documents do get into a state where mt_deleted is set to null, they neither show up with IsDeleted() / MaybeDeleted or in normal queries - they're sort of invisible to Marten. We had this occur recently.