Details
-
Bug
-
Resolution: Works as Designed
-
Unknown
-
None
-
2.19.0
-
None
-
(copied to CRM)
Description
Summary
The LINQ3 provider does not support projection to a class taking a BsonDocument in its constructor (the V2 provider supports it).
How to Reproduce
|
Linq3Bug.csproj |
<Project Sdk="Microsoft.NET.Sdk">
|
|
|
<PropertyGroup>
|
<OutputType>Exe</OutputType>
|
<TargetFramework>net6.0</TargetFramework>
|
<Nullable>enable</Nullable>
|
</PropertyGroup>
|
|
|
<ItemGroup>
|
<PackageReference Include="EphemeralMongo6" Version="0.1.3" />
|
<PackageReference Include="MongoDB.Driver" Version="2.19.0" />
|
</ItemGroup>
|
|
|
</Project>
|
|
Program.cs |
using System;
|
using System.Linq;
|
using EphemeralMongo;
|
using MongoDB.Bson;
|
using MongoDB.Driver;
|
using MongoDB.Driver.Linq;
|
|
|
Console.Write("Running MongoDB");
|
using var runner = MongoRunner.Run();
|
Console.WriteLine($" on {runner.ConnectionString}");
|
var settings = MongoClientSettings.FromConnectionString(runner.ConnectionString);
|
if (Enum.TryParse<LinqProvider>(args.FirstOrDefault(), out var provider))
|
{
|
settings.LinqProvider = provider;
|
}
|
Console.WriteLine($"Using LinqProvider {settings.LinqProvider}");
|
|
|
var client = new MongoClient(settings);
|
var collection = client.GetDatabase("my-db").GetCollection<BsonDocument>("my-collection");
|
var document = new BsonDocument
|
{
|
["_id"] = ObjectId.GenerateNewId(),
|
["Name"] = "Me",
|
};
|
collection.InsertOne(document);
|
var me = collection.Find(new BsonDocument()).Project(d => new Person(d)).Single();
|
Console.WriteLine($"[{me.Id}] {me.Name}");
|
|
|
public class Person
|
{
|
public Person(BsonDocument document)
|
{
|
Id = document["_id"].AsObjectId;
|
Name = document["Name"].AsString;
|
}
|
|
|
public ObjectId Id { get; set; }
|
|
|
public string Name { get; set; }
|
}
|
Run with the V2 driver (dotnet run V2): ✅ works as expected
Running MongoDB on mongodb://127.0.0.1:60766
|
Using LinqProvider V2
|
[63d846b35c677f6f0e813308] Me
|
Run with the V3 driver (dotnet run V3): ❌ ExpressionNotSupportedException
Running MongoDB on mongodb://127.0.0.1:60866
|
Using LinqProvider V3
|
Unhandled exception. MongoDB.Driver.Linq.ExpressionNotSupportedException: Expression not supported: new Person(d) because constructor parameter document does not match any property.
|
at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.NewExpressionToAggregationExpressionTranslator.GetMatchingPropertyName(NewExpression expression, String constructorParameterName)
|
at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.NewExpressionToAggregationExpressionTranslator.<>c__DisplayClass0_0.<Translate>b__1(ParameterInfo p)
|
at System.Linq.Enumerable.SelectArrayIterator`2.ToArray()
|
at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.NewExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, NewExpression expression)
|
at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, Expression expression)
|
at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(TranslationContext context, LambdaExpression lambdaExpression, IBsonSerializer parameterSerializer, Boolean asRoot)
|
at MongoDB.Driver.Linq.Linq3Implementation.LinqProviderAdapterV3.TranslateExpressionToProjection[TInput,TOutput](Expression`1 expression, IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry, ExpressionTranslationOptions translationOptions)
|
at MongoDB.Driver.Linq.Linq3Implementation.LinqProviderAdapterV3.TranslateExpressionToFindProjection[TSource,TProjection](Expression`1 expression, IBsonSerializer`1 sourceSerializer, IBsonSerializerRegistry serializerRegistry)
|
at MongoDB.Driver.FindExpressionProjectionDefinition`2.Render(IBsonSerializer`1 sourceSerializer, IBsonSerializerRegistry serializerRegistry, LinqProvider linqProvider)
|
at MongoDB.Driver.MongoCollectionImpl`1.CreateFindOperation[TProjection](FilterDefinition`1 filter, FindOptions`2 options)
|
at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
|
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass46_0`1.<FindSync>b__0(IClientSessionHandle session)
|
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
|
at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
|
at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)
|
at MongoDB.Driver.IAsyncCursorSourceExtensions.Single[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
|
at MongoDB.Driver.IFindFluentExtensions.Single[TDocument,TProjection](IFindFluent`2 find, CancellationToken cancellationToken)
|
Additional Background
The Hangfire.Mongo project uses this pattern (Find + Project) a lot so it's impossible to migrate to the LINQ3 provider.