Aller au contenu

« Mongodb and csharp » : différence entre les versions

De Banane Atomic
Aucun résumé des modifications
(20 versions intermédiaires par le même utilisateur non affichées)
Ligne 5 : Ligne 5 :
* [https://www.mongodb.com/developer/languages/csharp/joining-collections-mongodb-dotnet-core-aggregation-pipeline Joining Collections in MongoDB with .NET Core and an Aggregation Pipeline]
* [https://www.mongodb.com/developer/languages/csharp/joining-collections-mongodb-dotnet-core-aggregation-pipeline Joining Collections in MongoDB with .NET Core and an Aggregation Pipeline]
* [https://www.mongodb.com/developer/languages/csharp C# and MongoDB]
* [https://www.mongodb.com/developer/languages/csharp C# and MongoDB]
* [https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mongo-app?view=aspnetcore-9.0&tabs=visual-studio Create a web API with ASP.NET Core and MongoDB]


= Access to a collection =
= Access to a collection =
Ligne 10 : Ligne 11 :
var mongoClient = new MongoClient("MONGODB_CONNECTION_STRING");
var mongoClient = new MongoClient("MONGODB_CONNECTION_STRING");
var database = mongoClient.GetDatabase("DB_NAME");
var database = mongoClient.GetDatabase("DB_NAME");
var collection = database.GetCollection<Collection>("COLLECTION_NAME");
var collection = database.GetCollection<MyClass>("COLLECTION_NAME");
</kode>
</kode>


= Filter =
= Dependency injection =
<filebox fn='Program.cs'>
builder.Services
    .Configure<MongoConfiguration>(builder.Configuration.GetSection("Mongo"))
    .AddSingleton<IMongoClient>(x =>
        {
            var mongoConfiguration = x.GetRequiredService<IOptions<MongoConfiguration>>().Value;
            var settings = MongoClientSettings.FromConnectionString(mongoConfiguration.ConnectionString);
            settings.LinqProvider = LinqProvider.V3;
            return new MongoClient(settings);
        })
    .AddSingleton(x =>
    {
        var client = x.GetRequiredService<IMongoClient>();
        var configuration = x.GetRequiredService<IOptions<MongoConfiguration>>().Value;
        return client.GetDatabase(configuration.DatabaseName);
    })
    .AddSingleton(x =>
    {
        var database = x.GetRequiredService<IMongoDatabase>();
        return database.GetCollection<MyCollection>(GetConfigurationValue("MyCollectionName"));
    });
</filebox>
 
<filebox fn='MongoConfiguration.cs' collapsed>
public class MongoConfiguration
{
    public string ConnectionString { get; set; } = string.Empty;
 
    public string DatabaseName { get; set; } = string.Empty;
}
</filebox>
 
= Find =
== Filter ==
<kode lang='cs'>
<kode lang='cs'>
var builder = Builders<MyClass>.Filter;
var builder = Builders<MyClass>.Filter;
FilterDefinition<MyClass> filter = filterDefinition.Empty;
FilterDefinition<MyClass> filter = builder.Empty;


filter &= builder.Eq(x => x.Property1, "id");
filter &= builder.Exists(x => x.Property1);
filter &= builder.In(x => x.Property1, new[] { "id1", "id2" });  // filter by Property1 equals to one of the ids
filter &= builder.Eq(x => x.Property1, "value");
filter &= builder.In(x => x.Property1, new[] { "value1", "value2" });  // filter by Property1 equals to one of the values
filter &= builder.AnyIn(x => x.Tags, new[] { "value1", "value2" });    // filter by string[] Tags property which contains at least value1 or value2
filter &= builder.All(x => x.Tags, new[] { "value1", "value2" });      // filter by string[] Tags property which contains at least value1 and value2, order doesn't matter
 
var result = await collection
    .Find(filter)
    .SortByDescending(x => x.Property1)
    .Skip(100)
    .Limit(10)
    .ToListAsync();


var result = (await collection.FindAsync(filter)).ToList();
var result = (await collection.FindAsync(filter)).ToList();
</kode>
== Handle different types ==
<kode lang='cs'>
// get all the documents
var bsonDocumentCollection = database.GetCollection<BsonDocument>("MyCollection");
var filter = Builders<BsonDocument>.Filter.Empty;
var result = await bsonDocumentCollection.Find(filter).ToListAsync();
// get all the Class1 document
var class1Collection = database.GetCollection<Class1>("MyCollection");
await type1Collection.InsertOneAsync(new Class1 { Name = "Name1" });
var filter = Builders<Class1>.Filter.Eq(x => x.Type, nameof(Class1));
var filter = Builders<SimpleClass>.Filter.Exists(x => x.Name); // get all the documents which have a property Name
var result = await class1Collection.Find(filter).ToListAsync();
class Class1
{
    public ObjectId Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Type { get; set; } =  nameof(Class1);
}
</kode>
</kode>


Ligne 61 : Ligne 128 :
BsonDocument SortStage() =>
BsonDocument SortStage() =>
     new BsonDocument("$sort", new BsonDocument("timestamp", 1));
     new BsonDocument("$sort", new BsonDocument("timestamp", 1));
</kode>
= Insert / Update =
<kode lang='cs'>
// insert
await itemMongoCollection.InsertOneAsync(item);
FilterDefinition<Item> filter = Builders<Item>.Filter.Eq(nameod(Item.Id), item.Id);
// update
Item updatedItem = await itemMongoCollection.FindOneAndReplaceAsync(filter, item);
// upsert
var options = new FindOneAndReplaceOptions<Item, T> { IsUpsert = true };
await itemMongoCollection.FindOneAndReplaceAsync(filter, item, options);
// patch
UpdateDefinitionBuilder<Item> updateBuilder = Builders<Item>.Update;
UpdateDefinition<Item> updateDefinition = Builders<Item>.Update.Combine(
    updateBuilder.Set(nameof(Item.Name), "updatedName"),
    updateBuilder.Set(nameof(Item.Available), false));
UpdateResult result = await itemMongoCollection.UpdateOneAsync(filter, updateDefinition);
var success = result.ModifiedCount > 0;
</kode>
</kode>


Ligne 77 : Ligne 167 :
</kode>
</kode>
Configure the [[Asp.net_core_7#Log|Log]] so it will be displayed in Visual Studio Output Debug window.
Configure the [[Asp.net_core_7#Log|Log]] so it will be displayed in Visual Studio Output Debug window.
* [https://www.mongodb.com/docs/drivers/csharp/current/fundamentals/logging/#configure-logging Configure logging]
= Serialize a dictionary with an Enum as key =
Error: An error occurred while serializing the Values property of class ...: When using DictionaryRepresentation.Document key values must serialize as strings
<kode lang='cs'>
class MyClass
{
    public ObjectId Id { get; set; }
    public Dictionary<MyEnum, int> Values { get; set; } = [];
}
// serialize the enum as string
BsonSerializer.RegisterSerializer(new EnumSerializer<MyEnum>(BsonType.String));
</kode>
= BsonDocument =
<kode lang='cs'>
var bsonDocument = BsonDocument.Parse(jsonDocument.RootElement.GetRawText());
var bsonDocument = myObject.ToBsonDocument();
bsonDocument["fieldName"] = "value";
</kode>

Version du 2 avril 2025 à 12:21

Links

Access to a collection

var mongoClient = new MongoClient("MONGODB_CONNECTION_STRING");
var database = mongoClient.GetDatabase("DB_NAME");
var collection = database.GetCollection<MyClass>("COLLECTION_NAME");

Dependency injection

Program.cs
builder.Services
    .Configure<MongoConfiguration>(builder.Configuration.GetSection("Mongo"))
    .AddSingleton<IMongoClient>(x =>
        {
            var mongoConfiguration = x.GetRequiredService<IOptions<MongoConfiguration>>().Value;
            var settings = MongoClientSettings.FromConnectionString(mongoConfiguration.ConnectionString);
            settings.LinqProvider = LinqProvider.V3;
            return new MongoClient(settings);
        })
    .AddSingleton(x =>
    {
        var client = x.GetRequiredService<IMongoClient>();
        var configuration = x.GetRequiredService<IOptions<MongoConfiguration>>().Value;
        return client.GetDatabase(configuration.DatabaseName);
    })
    .AddSingleton(x =>
    {
        var database = x.GetRequiredService<IMongoDatabase>();
        return database.GetCollection<MyCollection>(GetConfigurationValue("MyCollectionName"));
    });
MongoConfiguration.cs
public class MongoConfiguration
{
    public string ConnectionString { get; set; } = string.Empty;

    public string DatabaseName { get; set; } = string.Empty;
}

Find

Filter

var builder = Builders<MyClass>.Filter;
FilterDefinition<MyClass> filter = builder.Empty;

filter &= builder.Exists(x => x.Property1);
filter &= builder.Eq(x => x.Property1, "value");
filter &= builder.In(x => x.Property1, new[] { "value1", "value2" });  // filter by Property1 equals to one of the values
filter &= builder.AnyIn(x => x.Tags, new[] { "value1", "value2" });    // filter by string[] Tags property which contains at least value1 or value2
filter &= builder.All(x => x.Tags, new[] { "value1", "value2" });      // filter by string[] Tags property which contains at least value1 and value2, order doesn't matter

var result = await collection
    .Find(filter)
    .SortByDescending(x => x.Property1)
    .Skip(100)
    .Limit(10)
    .ToListAsync();

var result = (await collection.FindAsync(filter)).ToList();

Handle different types

// get all the documents
var bsonDocumentCollection = database.GetCollection<BsonDocument>("MyCollection");
var filter = Builders<BsonDocument>.Filter.Empty;
var result = await bsonDocumentCollection.Find(filter).ToListAsync();

// get all the Class1 document
var class1Collection = database.GetCollection<Class1>("MyCollection");
await type1Collection.InsertOneAsync(new Class1 { Name = "Name1" });
var filter = Builders<Class1>.Filter.Eq(x => x.Type, nameof(Class1));
var filter = Builders<SimpleClass>.Filter.Exists(x => x.Name); // get all the documents which have a property Name
var result = await class1Collection.Find(filter).ToListAsync();

class Class1
{
    public ObjectId Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Type { get; set; } =  nameof(Class1);
}

Pipeline

var stages = new BsonDocument[]
{
    MatchStage(getTimeSeriesQuery),
    ProjectionStage(),
    SortStage()
};
var pipeline = PipelineDefinition<InputClass, OutputClass>.Create(stages);

var results = (await myCollection.AggregateAsync(pipeline)).List();

BsonDocument MatchStage(GetTimeSeriesQuery getTimeSeriesQuery)
{
    var match = new BsonDocument("property1", "value1");
    if (!string.IsNullOrEmpty(variable2))
    {
        match.AddRange(
            new BsonDocument("property2", variable2)
        );
    }
    return new BsonDocument("$match", match);
}

BsonDocument ProjectionStage() =>
    new BsonDocument(
        "$project",
        new BsonDocument
        {
            { "_id", 0 },
            { "property1", 1 },
            { "property2", 1 }
        }
    );

BsonDocument SortStage() =>
    new BsonDocument("$sort", new BsonDocument("timestamp", 1));

Insert / Update

// insert
await itemMongoCollection.InsertOneAsync(item);

FilterDefinition<Item> filter = Builders<Item>.Filter.Eq(nameod(Item.Id), item.Id);

// update
Item updatedItem = await itemMongoCollection.FindOneAndReplaceAsync(filter, item);

// upsert
var options = new FindOneAndReplaceOptions<Item, T> { IsUpsert = true };
await itemMongoCollection.FindOneAndReplaceAsync(filter, item, options);

// patch
UpdateDefinitionBuilder<Item> updateBuilder = Builders<Item>.Update;
UpdateDefinition<Item> updateDefinition = Builders<Item>.Update.Combine(
    updateBuilder.Set(nameof(Item.Name), "updatedName"),
    updateBuilder.Set(nameof(Item.Available), false));
UpdateResult result = await itemMongoCollection.UpdateOneAsync(filter, updateDefinition);
var success = result.ModifiedCount > 0;

Log

var mongoUrl = new MongoUrl("MONGODB_CONNECTION_STRING");
var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl);
mongoClientSettings.ClusterConfigurator = cb =>
{
    cb.Subscribe<CommandStartedEvent>(e =>
    {
        logger.LogTrace($"{e.CommandName} - {e.Command.ToJson()}");
    });
};
this.mongoClient = new MongoClient(mongoClientSettings);

Configure the Log so it will be displayed in Visual Studio Output Debug window.

Serialize a dictionary with an Enum as key

Error: An error occurred while serializing the Values property of class ...: When using DictionaryRepresentation.Document key values must serialize as strings

class MyClass
{
    public ObjectId Id { get; set; }
    public Dictionary<MyEnum, int> Values { get; set; } = [];
}

// serialize the enum as string
BsonSerializer.RegisterSerializer(new EnumSerializer<MyEnum>(BsonType.String));

BsonDocument

var bsonDocument = BsonDocument.Parse(jsonDocument.RootElement.GetRawText());
var bsonDocument = myObject.ToBsonDocument();

bsonDocument["fieldName"] = "value";