-
Type: Bug
-
Resolution: Works as Designed
-
Priority: Unknown
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
Summary
Especially notable during projection, if you check whether a field exists or not by doing a null-check, or by using string.IsNullOrEmpty or similar, it will return as not null when the field, or a parent of that field does not exist.
This is a breaking change in version 2.22.0 of the driver, coming from 2.18.0.
How to Reproduce
Add this to a collection:
{ "_id": { "$oid": "000000000000000000000001" }, "Name": "Example Name", "SecretValue": "Some Secret Value" }
With the following classes:
public class MainClass { [BsonId] public ObjectId Id { get; set; } public string Name { get; set; } public string SecretValue { get; set; } public OptionalClass OptionalData { get; set; } } public class OptionalClass { public string PublicData { get; set; } public string PrivateData { get; set; } } public class ProjectedMainClassWithoutSecretData { [BsonId] public ObjectId Id { get; set; } public string Name { get; set; } public ProjectedOptionalClassWithoutSecretData OptionalData { get; set } public bool HasOptionalPrivateData { get; set; } } public class ProjectedOptionalClassWithoutSecretData { public string PublicData { get; set; } }
Then do a find like so:
async Task<ProjectedMainClassWithoutSecretData> GetPublicData(IMongoCollection<MainClass> collection, ObjectId itemId) { var filter = Builders<MainClass>.Filter.Eq(x => x.Id, itemId); var projection = Builders<MainClass>.Projection.Expression(main => new ProjectedMainClassWithoutSecretData() { Id = main.Id, Name = main.Name, OptionalData = main.OptionalData != null ? new ProjectedOptionalClassWithoutSecretData() { PublicData = main.OptionalData.PublicData } : null, HasOptionalPrivateData = !string.IsNullOrEmpty(main.OptionalData.PrivateData) }); var result = await collection.Find(filter).Project(projection).FirstOrDefaultAsync(); return result; }
You will find that the result will have OptionalData set, and HasOptionalPrivateData set to true, where null and false were expected.
Additional Background
From what I can tell, there is no easy work-around to check for unset fields, and when dealing with larger classes, manual projection is not maintainable.
Please provide any additional background information that may be helpful in diagnosing the bug.
- is related to
-
CSHARP-4858 Provide a way to test if a field exists or is missing in a LINQ query
- Closed