Details
-
Bug
-
Status: Backlog
-
Major - P3
-
Resolution: Unresolved
-
2.11.0
-
None
-
I've verified this behaviour both on Windows as well as in a Linux container
-
(copied to CRM)
Description
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; } |
}
|
First, 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"].
An example that shows 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.
Attachments
Issue Links
- mentioned in
-
Page Loading...