3

I try to filter on of my mongo collections like that:

    public IMongoCollection<T> GetCollection<T>()
        where T : class
    {
        return _database.GetCollection<T>(typeof(T).Name);
    }


    public IMongoQueryable<TModel> Get<TModel>() where TModel : class
    {
        return GetCollection<TModel>().AsQueryable();
    }


    public async Task<TModel> FindOneAsync<TModel>(Expression<Func<TModel, bool>> predicate) where TModel : class
    {
        var foundEntity = await Get<TModel>().FirstOrDefaultAsync(predicate);
        if (foundEntity == null)
        {
            throw new NotFoundException();
        }

        return foundEntity;
    }

And then call it finally like that:

return await Db.FindOneAsync<Node>(node => node.Type == NodeType.Start);

But it seems like there is an error with the enum converter inside the mongo driver. I got the following error:

Application startup exception: System.AggregateException: One or more errors occurred. (Convert({document}.Type, Int32) is not supported.) ---> System.InvalidOperationException: Convert({document}.Type, Int32) is not supported.

Don't know what i am doing wrong. If i first cast the queryable to a list, then everything is working fine! But then the filter-operation is running on ram.

Matt Evans
  • 7,113
  • 7
  • 32
  • 64
Flo
  • 1,179
  • 3
  • 15
  • 43

1 Answers1

0

can't seem to be able to reproduce the error. the following is working with the latest driver. what's your driver and server version?

using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace StackOverflow
{
    public class Program
    {
        public enum NodeType
        {
            Start = 1,
            End = 2
        }

        public class Node
        {
            public ObjectId Id { get; set; }
            public NodeType Type { get; set; }
        }

        private async static Task Main(string[] args)
        {
            var _database = new MongoClient("mongodb://localhost").GetDatabase("test");

            await GetCollection<Node>().InsertOneAsync(new Node { Type = NodeType.Start });

            IMongoCollection<T> GetCollection<T>() where T : class
            {
                return _database.GetCollection<T>(typeof(T).Name);
            }

            IMongoQueryable<TModel> Get<TModel>() where TModel : class
            {
                return GetCollection<TModel>().AsQueryable();
            }

            async Task<TModel> FindOneAsync<TModel>(Expression<Func<TModel, bool>> predicate) where TModel : class
            {
                var foundEntity = await Get<TModel>().FirstOrDefaultAsync(predicate);
                if (foundEntity == null)
                {
                    throw new Exception("not found");
                }
                return foundEntity;
            }

            var res = await FindOneAsync<Node>(node => node.Type == NodeType.Start);
        }
    }
}
Dĵ ΝιΓΞΗΛψΚ
  • 5,068
  • 3
  • 13
  • 26
  • Driver Version: 2.9.1 MongoDB: latest docker – Flo Sep 10 '19 at 11:13
  • does your `Node` class and `Enum` look similar to mine above? – Dĵ ΝιΓΞΗΛψΚ Sep 10 '19 at 11:17
  • Not exaclty but basicly yes – Flo Sep 10 '19 at 11:29
  • if you have some custom serializers, conventions or class maps configured it could be interfering with the enums. try to run my code in a fresh docker and see if it still produces the error for you. if it doesn't then it's definitely something in your app setup. – Dĵ ΝιΓΞΗΛψΚ Sep 10 '19 at 11:32
  • Yes i have some custom serializers (for example: options.Converters.Add(new StringEnumConverter()); ) Can u tell me what is the default behavior how mongo stores enums (as string or int?) – Flo Sep 10 '19 at 11:36
  • it's stored as int like so: `"Type": NumberInt("1")`. if you need to store them as strings, you can [try this](https://stackoverflow.com/a/18874502/4368485) – Dĵ ΝιΓΞΗΛψΚ Sep 10 '19 at 12:52