使用Aggregate()查询的Group和Project的MongoDb C#驱动程序给出异常

时间:2019-11-26 08:41:05

标签: c# mongodb linq aggregation-framework

我正在研究使用MongoDb作为数据库并使用.Net Core 3.0作为框架的应用程序。为了从数据库中获取数据,我创建了一个DbContext类,并使用了Aggregation()的{​​{1}}功能。我无法通过适当的预测。以下是MongoDb

的代码
DbContext.cs

要调用函数 using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace Test.DbContext { /// <summary> /// Standard CRUD Operations with MongoDb /// </summary> public class MongoDbContext { #region Properties private readonly IMongoClient _mongoDbClient = null; private readonly IMongoDatabase _mongoDb = null; #endregion #region Constructor public MongoDbContext(IOptions<MongoSetting> mongoConfigs) { _mongoDbClient = new MongoClient(mongoConfigs.Value.ConnectionString); _mongoDb = _mongoDbClient.GetDatabase(mongoConfigs.Value.DatabaseName); } #endregion #region Grouping public IList<TProjection> GroupBy<TDocument, TGroupKey, TProjection> (FilterDefinition<TDocument> filter, Expression<Func<TDocument, TGroupKey>> selector, Expression<Func<IGrouping<TGroupKey, TDocument>, TProjection>> projection){ return _mongoDb.GetCollection<TDocument>("collectionName").Aggregate().Match(filter).Group(selector, projection).ToList(); } #endregion } } ,我必须传递过滤器,选择器和投影,但无法构建适当的表达式。以下是数据模型和调用函数:

GroupBy()

我在客户存储库中将dbContext称为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.Extensions.Options;
using MongoDB.Driver;

namespace Test 
{
    [BsonIgnoreExtraElements]
    public class Employee   
    {
        [BsonId]
        [BsonElement("_id")]
        [BsonRepresentation(BsonType.ObjectId)]
        public ObjectId Id { get; set; }

        [BsonElement("type")]
        [JsonProperty("type")]
        public string Type { get; set; }

        [BsonElement("id")]
        public string CustomerId { get; set; }

        [BsonElement("name")]
        public string CustomerName { get; set; }
    }
}

例外:

  

“序列化器的值类型为<> f__AnonymousType0`1 [[System.String,   System.Private.CoreLib,版本= 4.0.0.0,文化=中性,   PublicKeyToken = 7cec85d7bea7798e]],但与成员类型不匹配   System.Object。 (参数“序列化器”)”

1 个答案:

答案 0 :(得分:1)

我认为您要执行的操作不可行。作为一种替代方案,我可以建议从dbContext中公开.Aggregate()并从存储库中进行查询,如下所示。

员工类别

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace Test
{
    [BsonIgnoreExtraElements]
    public class Employee
    {
        [BsonId]
        [BsonElement("_id")]
        [BsonRepresentation(BsonType.ObjectId)]
        public ObjectId Id { get; set; }

        [BsonElement("type")]
        public string Type { get; set; }

        [BsonElement("id")]
        [BsonRepresentation(BsonType.String)] // to avoid manual conversion
        public int CustomerId { get; set; }

        [BsonElement("name")]
        public string CustomerName { get; set; }
    }
}

数据库上下文

using MongoDB.Driver;
using System.Linq;

namespace Test.DbContext
{
    public class MongoDbContext
    {
        private readonly IMongoClient _mongoDbClient = null;

        private readonly IMongoDatabase _mongoDb = null;

        public MongoDbContext()
        {
            _mongoDbClient = new MongoClient("mongodb://localhost");
            _mongoDb = _mongoDbClient.GetDatabase("test");
        }

        public IAggregateFluent<TDocument> Aggregate<TDocument>() =>
            _mongoDb.GetCollection<TDocument>(nameof(TDocument)).Aggregate();

    }
}

存储库

using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;
using Test.DbContext;

namespace Test.Repositories
{
    public class CustomerRepository
    {
        private static readonly MongoDbContext _dbContext = new MongoDbContext();

        public List<dynamic> GetSpecificData()
        {
            var result = _dbContext.Aggregate<Employee>()
                             .Match(e => e.CustomerId == 11)
                             .Group(e => e.Type, g => new { Key = g.Key, Count = g.Count(), Average = g.Average(e => e.CustomerId) })
                             .ToList();

            return result.Cast<dynamic>().ToList();
        }
    }
}

我还建议您不要将匿名类型转换为动态类型。因此,创建并使用另一个类(用于分组结果)保留类型安全。

我还建议您看看我写的library,这消除了编写自己的dbContext的需要。

然后查看this入门模板项目以查看其使用情况。