dj-nitehawk / MongoDB.Entities

A data access library for MongoDB with an elegant api, LINQ support and built-in entity relationship management
https://mongodb-entities.com
MIT License
547 stars 70 forks source link

support soft delete #204

Closed li-zheng-hao closed 1 year ago

li-zheng-hao commented 1 year ago

just like this implementation in efcore : https://blog.jetbrains.com/dotnet/2023/06/14/how-to-implement-a-soft-delete-strategy-with-entity-framework-core/

sample code:

interface ISoftDelete
{
    bool IsDeleted { get; set; }
}

class DBModel : Entity,ISoftDelete
{
    public bool IsDeleted { get; set; }
}
dj-nitehawk commented 1 year ago

already doable. see here: https://mongodb-entities.com/wiki/DB-Instances-Global-Filters.html

li-zheng-hao commented 1 year ago

global filter not work as expected, when delete a document, it should update IsDeleted to true rather than do nothing

sample code :

public class TestModel:Entity,ISoftDelete
{
    public string Name { get; set; }

    public bool IsDeleted { get; set; }
}

interface ISoftDelete
{
    bool IsDeleted { get; set; }
}

public class MyDBContext : DBContext
{
    public MyDBContext()
    {
        SetGlobalFilterForInterface<ISoftDelete>("{ IsDeleted : false }");
    }
}

unit test:

[Fact]
public async Task Test1()
{
    await DB.InitAsync("testdb",
        MongoClientSettings.FromConnectionString(
            "mongodb://root:******@172.10.2.200:30000"));

    var context = new MyDBContext();

    var model = new TestModel();

    await context.InsertAsync(model);

    await context.DeleteAsync<TestModel>(model.ID);

    var result = await context.Find<TestModel>().MatchID(model.ID).ExecuteFirstAsync();

    // failure here, result should be null
    Assert.Null(result);
}

@dj-nitehawk

li-zheng-hao commented 1 year ago

test case 2:

[Fact]
public async Task Test2()
{
    await DB.InitAsync("testdb",
        MongoClientSettings.FromConnectionString(
            "mongodb://root:***@172.10.2.200:30000"));

    var context = new MyDBContext();

    var model = new TestModel()
    {
        Name = "already deleted",
    };

    await context.InsertAsync(model);

    await context.DeleteAsync<TestModel>(it=>it.Name==model.Name);

    var result = await context.Find<TestModel>().Match(it=>it.Name==model.Name).ExecuteFirstAsync();

    // failure here, result should be null
    Assert.Null(result);
}

result:

Assert.Null() Failure
Expected: (null)
Actual:   TestModel { ID = "6492beae6462445f38de3142", IsDeleted = False, Name = "already deleted" }