mongo-extensions icon indicating copy to clipboard operation
mongo-extensions copied to clipboard

NullRefException when trying to serialize/deserialize a null navigational property of a migrated entity

Open BoutemineOualid opened this issue 1 year ago • 0 comments

Describe the bug When trying to execute a lookup query to load navigational properties of a migrated entity, the query fails with a null ref exception.

This happens at this line: https://github.com/SwissLife-OSS/mongo-extensions/blob/d74927556d305cc5322a7a641237a90c306cabda/src/Migration/MigrationSerializer.cs#L25

To Reproduce Steps to reproduce the behavior:

  1. Create an entity E1 with a Migration
  2. Create another entity E2 that references E1 using a property E2.NavigationalProperty of type E1 and tag it with [BsonIgnoreIfNull]
  3. Create an instance of E2 and set E2.NavigationalProperty to null
  4. Persist it.
  5. Load the collection using an aggregate lookup/unwind

public class E1 : IEquatable<E1>, IVersioned
{
	[BsonId]
	public ObjectId Id { get; set; }

        ....

	public int Version { get; set; }
}


public class E2 : IEquatable<E2>, IVersioned
{
	[BsonId]
	public ObjectId Id { get; set; }
 
        [BsonElement("e1id")]
        public ObjectId E1Id { get; set; }

        [BsonIgnoreIfNull]
        public E1? NavigationalProperty { get; set; }

	public int Version { get; set; }

 .....
}

public class E1Migration : IMigration
{
    public int Version => 1;
    
    public void Up(BsonDocument document)
    {
        document["newField"] = new BsonArray();
    }

    public void Down(BsonDocument document)
    {
        document.Remove("newField");
    }
}

_e2collection
            .Aggregate()
            .Lookup("E1Collection", nameof(E2.E1Id), "_id", nameof(E2.NavigationalProperty))
            .Unwind(nameof(E2.NavigationalProperty))
            .As<E2>()
           .Match(_ => true)
           .ToListAsync(ct)
  1. Notice a null ref exception is triggered when trying to materialize the result.

Expected behavior Null values should not be serialized/deserialized if they are marked as [BsonIgnoreIfNull]. Bellow is the stack trace.

Stack Trace

System.NullReferenceException: Object reference not set to an instance of an object.
   at MongoDB.Extensions.Migration.MigrationSerializer`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, T value)
   at MongoDB.Bson.Serialization.Serializers.SerializerBase`1.MongoDB.Bson.Serialization.IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, Object value)
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.ToBsonValue(IBsonSerializer serializer, Object value)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.TranslateComparison(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.TranslateComparison(BinaryExpression binaryExpression)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.Translate(Expression node)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.TranslateAndAlso(BinaryExpression node)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.Translate(Expression node)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.TranslateAndAlso(BinaryExpression node)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.Translate(Expression node)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry)
   at MongoDB.Driver.Linq.Linq2Implementation.Translators.PredicateTranslator.Translate[TDocument](Expression`1 predicate, IBsonSerializer`1 parameterSerializer, IBsonSerializerRegistry serializerRegistry)
   at MongoDB.Driver.Linq.Linq2Implementation.LinqProviderAdapterV2.TranslateExpressionToFilter[TDocument](Expression`1 expression, IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry)
   at MongoDB.Driver.ExpressionFilterDefinition`1.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry, LinqProvider linqProvider)
   at MongoDB.Driver.PipelineStageDefinitionBuilder.<>c__DisplayClass34_0`1.<Match>b__0(IBsonSerializer`1 s, IBsonSerializerRegistry sr, LinqProvider linqProvider)
   at MongoDB.Driver.DelegatedPipelineStageDefinition`2.Render(IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry, LinqProvider linqProvider)
   at MongoDB.Driver.AppendedStagePipelineDefinition`3.Render(IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry, LinqProvider linqProvider)
   at MongoDB.Driver.MongoCollectionImpl`1.AggregateAsync[TResult](IClientSessionHandle session, PipelineDefinition`2 pipeline, AggregateOptions options, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)
   at MongoDB.Driver.IAsyncCursorSourceExtensions.ToListAsync[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)

Desktop (please complete the following information):

  • OS: MacOS/Linux/Windows
  • Version : 3.0.0

Additional context Add any other context about the problem here.

BoutemineOualid avatar Mar 28 '23 02:03 BoutemineOualid