Possible bug when mapping a subarray using FindAsync (C# driver)

I believe I’ve found a bug related to projection, specifically when you map an array that is a deep descendant of the document root.

Suppose this is my model:


public class DummyContainer

{

    public DummyContainer(IList<Dummy> dummies)

    {

        Dummies = dummies;

        this.Id = ObjectId.GenerateNewId().ToString();

    }

    public string Id { get; private set; }

    public IList<Dummy> Dummies { get; private set; }

}

public class Dummy

{

    public Dummy(string name)

    {

        this.Name = name;

        this.Id = ObjectId.GenerateNewId().ToString();

    }

    public string Id { get; private set; }

    public string Name { get; private set; }

}

An example that works

Let’s say I insert one document of type DummyContainer into an empty collection:


collection.InsertOneAsync(new DummyContainer(new[]

{

    new Dummy("SomeValue1"),

    new Dummy("SomeValue2"),

}));

And then I load all documents from that collection, projected into this type:


    class DummyContainerWithDummyNames

    {

        public string ContainerId { get; set; }

        public IEnumerable<string> DummyNames { get; set; }

    }

Here we go:


    var dummyNamesByUsingFindAsync = await (await collection.FindAsync(Builders<DummyContainer>.Filter.Empty, new FindOptions<DummyContainer, DummyContainerWithDummyNames> { 

        Projection = Builders<DummyContainer>.Projection.Expression(x => new DummyContainerWithDummyNames

        {

            ContainerId = x.Id,

            DummyNames = x.Dummies.Select(d => d.Name)

        })

    })).ToListAsync();

    var dummyNamesUsingQuery = await collection.AsQueryable()

        .Select(x => new DummyContainerWithDummyNames

        {

            ContainerId = x.Id,

            DummyNames = x.Dummies.Select(d => d.Name)

        })

        .ToListAsync();

Result:

Both dummyNamesByUsingFindAsync and dummyNamesUsingQuery contain one document, and in both cases the property DummyNames is populated with ["SomeValue1", "SomeValue2"].

Example that reproduces the bug

Ok, in order to reproduce the bug, we’re gonna wrap the DummyContainer in a DummyContainerWrapper and let this be our root entity:


public class DummyContainerWrapper

{

    public DummyContainerWrapper(DummyContainer container)

    {

        Container = container;

        this.Id = ObjectId.GenerateNewId().ToString();

    }

    public string Id { get; private set; }

    public DummyContainer Container { get; private set; }

}

We’re gonna insert such a document to a new collection:


await collection.InsertOneAsync(new DummyContainerWrapper(new DummyContainer(new[]

{

    new Dummy("SomeValue1"),

    new Dummy("SomeValue2"),

})));

And just like before, we’re gonna query the collection for all documents and project them into the same type we used above:


var dummyNamesByUsingFindAsync = await (await collection.FindAsync(Builders<DummyContainerWrapper>.Filter.Empty, new FindOptions<DummyContainerWrapper, DummyContainerWithDummyNames> { 

    Projection = Builders<DummyContainerWrapper>.Projection.Expression(x => new DummyContainerWithDummyNames

    {

        ContainerId = x.Id,

        DummyNames = x.Container.Dummies.Select(d => d.Name)

    })

})).ToListAsync();

var dummyNamesUsingQuery = await collection.AsQueryable()

    .Select(x => new DummyContainerWithDummyNames

    {

        ContainerId = x.Id,

        DummyNames = x.Container.Dummies.Select(d => d.Name)

    })

    .ToListAsync();

And this is where we see the bug:

dummyNamesUsingQuery has one element, who’s DummyNames property is an IEnumerable<string> (the concrete type is List<string>) populated with ["SomeValue1", "SomeValue2"].

dummyNamesByUsingFindAsync on the other hand also has one element, but it´s DummyNames property is of type System.Linq.Enumerable.SelectListIterator<MyTestProgram.Dummy, string>, and the values are both null.

I thought I’d post it here first, to check if this is already a known issue, before I open a Jira ticket.

Since there’s not replies to this post, I’ll just go ahead and open a ticket in Jira

1 Like

Hi @John_Knoop,

Thanks for opening a ticket CSHARP-3227 for this.
Running the snippet code that you provided with MongoDB .NET/C# v2.11.2 , I could also replicate the issue that you’re seeing.

Regards,
Wan

1 Like