C# 中 MongoDB 的直通投影定义

Pass-through projection definition for MongoDB in C#

我有一个函数,用于通过 Mongo 数据库中的 ID 检索对象,它看起来像这样:

public async Task<IEnumerable<TItem>> GetItemsAsync(uint limit, 
    Expression<Func<TItem, bool>> filter = null,
    SortDefinition<TItem> sort = null, 
    ProjectionDefinition<TItem> projection = default, 
    CancellationToken token = default) {

    // First, create the options describing which objects will be returned
    var findOptions = new FindOptions<TItem> {
        Limit = (int)limit,
        Sort = sort,
        Projection = projection
    };

    // Next, connect to the specific collection in the database
    IMongoCollection<TItem> collection = GetCollection();

    // Now, attempt to find all the items associated with the filter and find options
    IAsyncCursor<TItem> cursor = await collection.FindAsync(filter ?? FilterDefinition<TItem>.Empty, 
        findOptions, token).ConfigureAwait(false);

     // Finally, retrieve all the items and return them
     return await cursor.ToListAsync(token).ConfigureAwait(false);
}

我遇到的问题是,在我想要 return 文档中的所有字段因此不提供投影的情况下,这会中断。在这种情况下,我得到以下异常:

System.ArgumentNullException: Value cannot be null. (Parameter 'projection')
   at MongoDB.Driver.Core.Misc.Ensure.IsNotNull[T](T value, String paramName)
   at MongoDB.Driver.KnownResultTypeProjectionDefinitionAdapter`2..ctor(ProjectionDefinition`1 projection, IBsonSerializer`1 projectionSerializer)
   at MongoDB.Driver.ProjectionDefinition`2.op_Implicit(ProjectionDefinition`1 projection)

我的问题是:是否有传递投影定义或以编程方式将从 MongoDB 文档检索到的所有字段映射到我的 return 对象的方法?

感谢@Llama 的建议,我得以解决此问题。我将代码重构为如下所示:

public async Task<IEnumerable<TItem>> GetItemsAsync(uint limit, 
    FilterDefinition<TItem> filter = null,
    SortDefinition<TItem> sort = null,
    ProjectionDefinition<TItem, TItem> projection = null,
    CancellationToken token = default) {
    return await CreateFindOperation(limit, filter, sort, projection)
        .ToListAsync(token).ConfigureAwait(false);
}

// Helper function that creates a find-operation from some common elements
private IFindFluent<TItem, TItem> CreateFindOperation(uint? limit,
    FilterDefinition<TItem> filter = null,
    SortDefinition<TItem> sort = null,
    ProjectionDefinition<TItem, TItem> projection = null) {

    // First, connect to the specific collection in the database
    IMongoCollection<TItem> collection = GetCollection();

    // Next, create an operation to find the items that are associated with the filter
    IFindFluent<TItem, TItem> operation = collection.Find(filter ?? FilterDefinition<TItem>.Empty);

    // Now, if the projection operation has been provided then apply it to the
    // search and then update the search
    if (projection != null) {
        operation = operation.Project(projection);
    }

    // If the sort operation has been provided then modify the search with the sort operation
    if (sort != null) {
        operation = operation.Sort(sort);
    }

    // Finally, if the limit has been included in the request then modify the operation to only
    // return the first N items associated with the limit; otherwise, return the operation as-is
    return limit.HasValue ? operation.Limit((int)limit) : operation;
}

辅助函数还允许我将代码重用于其他检索式函数。