using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.IdGenerators; using MongoDB.Driver; using Xunit; namespace MongoDB_Projection_Issue; public class Program { // Configuration values private const string connectionString = "{Insert Connection String}"; private const string dbName = "Test"; private const string collectionName = "Test"; public static async Task Main() { // Connect to database. var url = new MongoUrl(connectionString); var client = new MongoClient(url); // Test projection on documents with ObjectId. (Fails; all values are empty ObjectIds) await TestObjectId(client); // Test projection on documents with string ID. (Fails; all values are null) await TestStringId(client); } private static async Task TestObjectId(MongoClient client) { var collection = client.GetDatabase(dbName).GetCollection(collectionName); // Create test documents. var docs = Enumerable.Range(1, 5).Select(_ => new TestModelWithObjectId()); // Delete any existing documents await collection.DeleteManyAsync(x => true); // Insert documents in collection. await collection.InsertManyAsync(docs); // Projection to get IDs of documents in collection. var projection = collection.Find(_ => true) .Project(x => x.Id); var ids = await projection.ToListAsync(); var results = await collection.Find(x => true).ToListAsync(); // Write projection to the console for validation. Console.WriteLine(projection.ToString()); // Assert that all results are not null. Assert.All(results, x => Assert.NotEqual(ObjectId.Empty, x.Id)); Assert.All(ids, x => Assert.NotEqual(ObjectId.Empty, x)); } private static async Task TestStringId(MongoClient client) { var collection = client.GetDatabase(dbName).GetCollection(collectionName); // Create test documents. var docs = Enumerable.Range(1, 5).Select(_ => new TestModelWithStringId()); // Delete any existing documents await collection.DeleteManyAsync(x => true); // Insert documents in collection. await collection.InsertManyAsync(docs); // Projection to get IDs of documents in collection. var projection = collection.Find(_ => true) .Project(x => x.Id); var ids = await projection.ToListAsync(); var results = await collection.Find(x => true).ToListAsync(); // Write projection to the console for validation. Console.WriteLine(projection.ToString()); // Assert that all results are not null. Assert.All(results, x => Assert.NotNull(x.Id)); Assert.All(ids, x => Assert.NotNull(x?.ToString())); } } /// /// Document model that uses a string for the document ID. /// public class TestModelWithStringId { /// /// Document ID. /// [BsonId(IdGenerator = typeof(StringObjectIdGenerator))] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } /// /// Document type; here only for differentiation in results. /// [BsonElement] public string Type => nameof(TestModelWithStringId); } /// /// Document model that uses an Object ID for the document ID. /// public class TestModelWithObjectId { /// /// Document ID. /// [BsonId] public ObjectId Id { get; set; } /// /// Document type; here only for differentiation in results. /// [BsonElement] public string Type => nameof(TestModelWithObjectId); }