Does not return property through manual projection

Hi, I have this problem that I need to pull only data from a property marked as ExtraElements, in this case it is “AdditionalData”. When I use .Select or Builder.Projection it always returns null, when it comes to other properties it returns fine. But when I don’t do any projection and I just do ToListAsync it returns AdditionalData correctly. How can I solve this?

 var query = _repository.GetAll().Select(x => new CollectiveDataDto
           {
               Id = x.Id,
               Prop1 = xProp1,
               Prop2 = x.Prop2,
               AdditionalData = x.AdditionalData,
           });

in repo i just return collection as queryable

or

var proje = Builders<SomeEntity>.Projection.Include(x => x.AdditionalData);
var test = await _repository.GetAllWithProjections(proje);

in repo i have:
return await _collection.Find(new BsonDocument()).Project<SomeEntity>(projection).ToListAsync();

Hi, @thebaku_N_A,

Welcome to the MongoDB Community Forums. I understand that you are unable to use Select with BsonExtraElementsAttribute.

When you perform a Select operation, this maps to a $project in MQL. The MQL for your above Select will look something like this:

test.coll.Aggregate([{ "$project" : { "_id" : "$_id", "Prop1" : "$Prop1", "Prop2" : "$Prop2", "AdditionalData" : "$AdditionalData" } }])

There is no AdditionalData field and thus $AdditionalData returns null. While we probably shouldn’t render a field marked with BsonExtraElements as $FieldName, it is a moot point as there is no way to easily express “place all unknown fields in a name-value collection” in MQL. What you really want is to return all fields back to the client and let deserialization handle the unknown fields in whatever manner is configured in the BSON class mappings.

The easiest way to solve this is to leverage LINQ-to-Objects. First query back the data of interest using the MongoDB .NET/C# driver and then use LINQ-to-Objects to map the returned data into your DTO classes.

var query = _repository.GetAll().Where(predicate);
var results = query.ToList();

// map returned data to DTOs using LINQ-to-Objects
var dtoResults = results.Select(x => new CollectiveDataDto {
    Id = x.Id,
    Prop1 = x.Prop1,
    Prop2 = x.Prop2,
    AdditionalData = x.AdditionalData
});

Hopefully this helps.

Sincerely,
James