diff --git a/docs/docs/configuration/queryable-projections.mdx b/docs/docs/configuration/queryable-projections.mdx
index 55874bdd17..e41b7216de 100644
--- a/docs/docs/configuration/queryable-projections.mdx
+++ b/docs/docs/configuration/queryable-projections.mdx
@@ -56,6 +56,59 @@ such mappings have several limitations:
- Deep cloning is not applied
:::
+## Null handling
+
+By default, Mapperly emits null-safe projections: nullable source members are guarded so mapping a
+`null` value does not throw. When a projection is translated to SQL by a relational provider (such as
+Entity Framework Core), these guards become `CASE WHEN` expressions that can prevent the database from
+using indexes. Mapping a nullable source member to a non-nullable target member additionally reports
+the `RMG089` diagnostic.
+
+If your projections are only ever executed by a relational provider (where the lambda is translated to
+a query and never run in memory), you can skip this null handling with
+`QueryableProjectionNullHandling.Ignore`:
+
+
+
+
+```csharp
+// highlight-start
+[Mapper(QueryableProjectionNullHandling = QueryableProjectionNullHandling.Ignore)]
+// highlight-end
+public static partial class CarMapper
+{
+ public static partial IQueryable ProjectToDto(this IQueryable q);
+}
+```
+
+
+
+
+```csharp
+// with Ignore: source members are projected directly
+q.Select(x => new CarDto() { OwnerName = x.Owner.Name });
+
+// default (NullSafe): nullable members are guarded
+q.Select(x => new CarDto() { OwnerName = x.Owner != null ? x.Owner.Name : default });
+```
+
+
+
+
+With `Ignore`, Mapperly projects source members directly, producing cleaner SQL and skipping the
+related nullability diagnostics. The generated projection is then identical regardless of the nullable
+reference type context.
+
+:::warning
+`QueryableProjectionNullHandling.Ignore` assumes source members are non-`null`. Using it with an
+in-memory `IQueryable` (e.g. LINQ to Objects) where a source value is actually `null` throws a
+`NullReferenceException`. Only use it with providers that translate the projection to a query, such as
+Entity Framework Core.
+:::
+
+The default is `QueryableProjectionNullHandling.NullSafe`, which keeps the null-safe behavior described
+above.
+
## Property configurations
To configure property mappings add partial mapping method definitions with attributes as needed.
diff --git a/src/Riok.Mapperly.Abstractions/MapperAttribute.cs b/src/Riok.Mapperly.Abstractions/MapperAttribute.cs
index f0e1190379..87342a2596 100644
--- a/src/Riok.Mapperly.Abstractions/MapperAttribute.cs
+++ b/src/Riok.Mapperly.Abstractions/MapperAttribute.cs
@@ -142,4 +142,10 @@ public class MapperAttribute : Attribute
/// partial methods are discovered.
///
public bool AutoUserMappings { get; set; } = true;
+
+ ///
+ /// Controls how null values are handled in projection mappings.
+ /// Defaults to .
+ ///
+ public QueryableProjectionNullHandling QueryableProjectionNullHandling { get; set; } = QueryableProjectionNullHandling.NullSafe;
}
diff --git a/src/Riok.Mapperly.Abstractions/QueryableProjectionNullHandling.cs b/src/Riok.Mapperly.Abstractions/QueryableProjectionNullHandling.cs
new file mode 100644
index 0000000000..c4913cd659
--- /dev/null
+++ b/src/Riok.Mapperly.Abstractions/QueryableProjectionNullHandling.cs
@@ -0,0 +1,19 @@
+namespace Riok.Mapperly.Abstractions;
+
+///
+/// Controls how null values are handled in projection mappings.
+///
+public enum QueryableProjectionNullHandling
+{
+ ///
+ /// Emits null-safe projections based on the nullable reference type annotations (default).
+ ///
+ NullSafe = 0,
+
+ ///
+ /// Skips null handling in queryable projections, even when the source may be null.
+ /// Intended for relational providers (e.g. EF Core) where the projection is translated to SQL
+ /// and the lambda is never executed. Using this with in-memory queryables may cause a .
+ ///
+ Ignore = 1,
+}
diff --git a/src/Riok.Mapperly/Configuration/MapperConfiguration.cs b/src/Riok.Mapperly/Configuration/MapperConfiguration.cs
index 68893d366a..bc4d127ad9 100644
--- a/src/Riok.Mapperly/Configuration/MapperConfiguration.cs
+++ b/src/Riok.Mapperly/Configuration/MapperConfiguration.cs
@@ -135,4 +135,7 @@ public record MapperConfiguration
/// Can be overwritten on specific enums via mapping method configurations.
///
public EnumNamingStrategy? EnumNamingStrategy { get; init; }
+
+ ///
+ public QueryableProjectionNullHandling? QueryableProjectionNullHandling { get; init; }
}
diff --git a/src/Riok.Mapperly/Configuration/MapperConfigurationMerger.cs b/src/Riok.Mapperly/Configuration/MapperConfigurationMerger.cs
index 4d625f49f3..a509868356 100644
--- a/src/Riok.Mapperly/Configuration/MapperConfigurationMerger.cs
+++ b/src/Riok.Mapperly/Configuration/MapperConfigurationMerger.cs
@@ -27,6 +27,7 @@ public static MapperConfiguration Merge(MapperConfiguration highPriority, Mapper
PreferParameterlessConstructors = highPriority.PreferParameterlessConstructors ?? lowPriority.PreferParameterlessConstructors,
AutoUserMappings = highPriority.AutoUserMappings ?? lowPriority.AutoUserMappings,
EnumNamingStrategy = highPriority.EnumNamingStrategy ?? lowPriority.EnumNamingStrategy,
+ QueryableProjectionNullHandling = highPriority.QueryableProjectionNullHandling ?? lowPriority.QueryableProjectionNullHandling,
};
}
@@ -104,6 +105,11 @@ public static MapperAttribute MergeToAttribute(MapperConfiguration mapperConfigu
mapper.EnumNamingStrategy =
mapperConfiguration.EnumNamingStrategy ?? defaultMapperConfiguration.EnumNamingStrategy ?? mapper.EnumNamingStrategy;
+ mapper.QueryableProjectionNullHandling =
+ mapperConfiguration.QueryableProjectionNullHandling
+ ?? defaultMapperConfiguration.QueryableProjectionNullHandling
+ ?? mapper.QueryableProjectionNullHandling;
+
return mapper;
}
}
diff --git a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/MemberMappingBuilder.cs b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/MemberMappingBuilder.cs
index 1f6f950fe2..2e25e7e07b 100644
--- a/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/MemberMappingBuilder.cs
+++ b/src/Riok.Mapperly/Descriptors/MappingBodyBuilders/MemberMappingBuilder.cs
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;
+using Riok.Mapperly.Abstractions;
using Riok.Mapperly.Descriptors.MappingBodyBuilders.BuilderContext;
using Riok.Mapperly.Descriptors.Mappings;
using Riok.Mapperly.Descriptors.Mappings.MemberMappings;
@@ -90,8 +91,11 @@ public static bool TryBuild(
var memberSourceNullable = memberMappingInfo.IsSourceNullable;
var delegateSourceNullable = delegateMapping.SourceType.IsNullable();
+ var ignoreProjectionNulls = IsIgnoredProjectionNullHandling(ctx.BuilderContext);
+
if (
memberMappingInfo.Configuration?.SuppressNullMismatchDiagnostic != true
+ && !ignoreProjectionNulls
&& memberSourceNullable
&& !memberTargetAcceptsNull
&& !(delegateSourceNullable && !delegateTargetNullable)
@@ -136,6 +140,9 @@ public static bool TryBuild(
return true;
}
+ private static bool IsIgnoredProjectionNullHandling(MappingBuilderContext ctx) =>
+ ctx.IsExpression && ctx.Configuration.Mapper.QueryableProjectionNullHandling == QueryableProjectionNullHandling.Ignore;
+
private static bool ValidateLoopMapping(
IMembersBuilderContext ctx,
INewInstanceMapping delegateMapping,
@@ -173,8 +180,10 @@ private static NullMappedMemberSourceValue BuildInlineNullHandlingMapping(
ITypeSymbol targetMemberType
)
{
+ var ignoreNullHandling = IsIgnoredProjectionNullHandling(ctx.BuilderContext);
+
var nullFallback = NullFallbackValue.Default;
- if (!delegateMapping.SourceType.IsNullable() && sourcePath.IsAnyReadNullable())
+ if (!ignoreNullHandling && !delegateMapping.SourceType.IsNullable() && sourcePath.IsAnyReadNullable())
{
nullFallback = ctx.BuilderContext.GetNullFallbackValue(targetMemberType);
}
@@ -184,7 +193,8 @@ ITypeSymbol targetMemberType
sourcePath.BuildGetter(ctx.BuilderContext),
targetMemberType,
nullFallback,
- !ctx.BuilderContext.IsExpression
+ !ctx.BuilderContext.IsExpression,
+ ignoreNullHandling
);
}
diff --git a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/SourceValue/NullMappedMemberSourceValue.cs b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/SourceValue/NullMappedMemberSourceValue.cs
index da4dbe9e8e..8292c13e2d 100644
--- a/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/SourceValue/NullMappedMemberSourceValue.cs
+++ b/src/Riok.Mapperly/Descriptors/Mappings/MemberMappings/SourceValue/NullMappedMemberSourceValue.cs
@@ -17,15 +17,25 @@ public class NullMappedMemberSourceValue(
MemberPathGetter sourceGetter,
ITypeSymbol targetType,
NullFallbackValue nullFallback,
- bool useNullConditionalAccess
+ bool useNullConditionalAccess,
+ bool ignoreNullHandling = false
) : ISourceValue
{
private readonly INewInstanceMapping _delegateMapping = delegateMapping;
private readonly NullFallbackValue _nullFallback = nullFallback;
private readonly MemberPathGetter _sourceGetter = sourceGetter;
+ private readonly bool _ignoreNullHandling = ignoreNullHandling;
public ExpressionSyntax Build(TypeMappingBuildContext ctx)
{
+ // if null handling should be ignored (e.g. queryable projections with
+ // QueryableProjectionNullHandling.Ignore), emit a straight member access.
+ if (_ignoreNullHandling)
+ {
+ ctx = ctx.WithSource(_sourceGetter.BuildAccess(ctx.Source, addValuePropertyOnNullable: true));
+ return _delegateMapping.Build(ctx);
+ }
+
// if the source is not nullable, return it directly.
if (!_sourceGetter.MemberPath.IsAnyReadNullable())
{
@@ -79,8 +89,9 @@ public override bool Equals(object? obj)
var other = (NullMappedMemberSourceValue)obj;
return _delegateMapping.Equals(other._delegateMapping)
&& _nullFallback == other._nullFallback
- && _sourceGetter.Equals(other._sourceGetter);
+ && _sourceGetter.Equals(other._sourceGetter)
+ && _ignoreNullHandling == other._ignoreNullHandling;
}
- public override int GetHashCode() => HashCode.Combine(_delegateMapping, _nullFallback, _sourceGetter);
+ public override int GetHashCode() => HashCode.Combine(_delegateMapping, _nullFallback, _sourceGetter, _ignoreNullHandling);
}
diff --git a/src/Riok.Mapperly/Riok.Mapperly.targets b/src/Riok.Mapperly/Riok.Mapperly.targets
index 6a1a0f4e24..80c5719eb0 100644
--- a/src/Riok.Mapperly/Riok.Mapperly.targets
+++ b/src/Riok.Mapperly/Riok.Mapperly.targets
@@ -23,5 +23,6 @@
+
diff --git a/test/Riok.Mapperly.Abstractions.Tests/_snapshots/PublicApiTest.PublicApiHasNotChanged.verified.cs b/test/Riok.Mapperly.Abstractions.Tests/_snapshots/PublicApiTest.PublicApiHasNotChanged.verified.cs
index 2491f7d24b..529eb579a4 100644
--- a/test/Riok.Mapperly.Abstractions.Tests/_snapshots/PublicApiTest.PublicApiHasNotChanged.verified.cs
+++ b/test/Riok.Mapperly.Abstractions.Tests/_snapshots/PublicApiTest.PublicApiHasNotChanged.verified.cs
@@ -140,6 +140,7 @@ public MapperAttribute() { }
public Riok.Mapperly.Abstractions.MemberVisibility IncludedMembers { get; set; }
public bool PreferParameterlessConstructors { get; set; }
public Riok.Mapperly.Abstractions.PropertyNameMappingStrategy PropertyNameMappingStrategy { get; set; }
+ public Riok.Mapperly.Abstractions.QueryableProjectionNullHandling QueryableProjectionNullHandling { get; set; }
public Riok.Mapperly.Abstractions.RequiredMappingStrategy RequiredEnumMappingStrategy { get; set; }
public Riok.Mapperly.Abstractions.RequiredMappingStrategy RequiredMappingStrategy { get; set; }
public Riok.Mapperly.Abstractions.StackCloningStrategy StackCloningStrategy { get; set; }
@@ -277,6 +278,11 @@ public enum PropertyNameMappingStrategy
SnakeCase = 2,
UpperSnakeCase = 3,
}
+ public enum QueryableProjectionNullHandling
+ {
+ NullSafe = 0,
+ Ignore = 1,
+ }
[System.Flags]
public enum RequiredMappingStrategy
{
diff --git a/test/Riok.Mapperly.Tests/Mapping/QueryableProjectionNullHandlingTest.cs b/test/Riok.Mapperly.Tests/Mapping/QueryableProjectionNullHandlingTest.cs
new file mode 100644
index 0000000000..9993522614
--- /dev/null
+++ b/test/Riok.Mapperly.Tests/Mapping/QueryableProjectionNullHandlingTest.cs
@@ -0,0 +1,186 @@
+using Riok.Mapperly.Abstractions;
+
+namespace Riok.Mapperly.Tests.Mapping;
+
+public class QueryableProjectionNullHandlingTest
+{
+ [Fact]
+ public void IgnoreShouldSkipNullHandlingForNullableMember()
+ {
+ var source = TestSourceBuilder.Mapping(
+ "System.Linq.IQueryable",
+ "System.Linq.IQueryable",
+ TestSourceBuilderOptions.Default with
+ {
+ QueryableProjectionNullHandling = QueryableProjectionNullHandling.Ignore,
+ },
+ "class A { public C? Value { get; set; } }",
+ "class B { public D Value { get; set; } }",
+ "class C { public int Id { get; set; } }",
+ "class D { public int Id { get; set; } }"
+ );
+
+ TestHelper
+ .GenerateMapper(source, TestHelperOptions.AllowInfoDiagnostics)
+ .Should()
+ .HaveSingleMethodBody(
+ """
+ #nullable disable
+ return global::System.Linq.Queryable.Select(
+ source,
+ x => new global::B()
+ {
+ Value = new global::D()
+ {
+ Id = x.Value.Id,
+ },
+ }
+ );
+ #nullable enable
+ """
+ );
+ }
+
+ [Fact]
+ public Task IgnoreShouldNotRequireParameterlessCtorForNullableNavigation()
+ {
+ // https://github.com/riok/mapperly/issues/2350
+ var source = TestSourceBuilder.Mapping(
+ "System.Linq.IQueryable",
+ "System.Linq.IQueryable",
+ TestSourceBuilderOptions.Default with
+ {
+ QueryableProjectionNullHandling = QueryableProjectionNullHandling.Ignore,
+ },
+ "class A { public C? Nested { get; set; } }",
+ "class B { public D Nested { get; set; } }",
+ "class C { public int Id { get; set; } }",
+ "class D { public D(int id) { Id = id; } public int Id { get; } }"
+ );
+
+ return TestHelper.VerifyGenerator(source);
+ }
+
+ [Fact]
+ public void IgnoreShouldNotReportNullableSourceDiagnostic()
+ {
+ // https://github.com/riok/mapperly/issues/1293
+ var source = TestSourceBuilder.Mapping(
+ "System.Linq.IQueryable",
+ "System.Linq.IQueryable",
+ TestSourceBuilderOptions.Default with
+ {
+ QueryableProjectionNullHandling = QueryableProjectionNullHandling.Ignore,
+ },
+ "class A { public string? Name { get; set; } }",
+ "class B { public string Name { get; set; } }"
+ );
+
+ TestHelper
+ .GenerateMapper(source)
+ .Should()
+ .HaveSingleMethodBody(
+ """
+ #nullable disable
+ return global::System.Linq.Queryable.Select(
+ source,
+ x => new global::B()
+ {
+ Name = x.Name,
+ }
+ );
+ #nullable enable
+ """
+ );
+ }
+
+ [Fact]
+ public Task IgnoreDisabledNullableContextShouldMatchEnabled()
+ {
+ // https://github.com/riok/mapperly/issues/1293 — output must not depend on the nullable context
+ var source = TestSourceBuilder.Mapping(
+ "System.Linq.IQueryable",
+ "System.Linq.IQueryable",
+ TestSourceBuilderOptions.Default with
+ {
+ QueryableProjectionNullHandling = QueryableProjectionNullHandling.Ignore,
+ },
+ "class A { public string? Name { get; set; } }",
+ "class B { public string Name { get; set; } }"
+ );
+
+ return TestHelper.VerifyGenerator(source, TestHelperOptions.DisabledNullable);
+ }
+
+ [Fact]
+ public void IgnoreShouldUnwrapNullableValueTypeMember()
+ {
+ var source = TestSourceBuilder.Mapping(
+ "System.Linq.IQueryable",
+ "System.Linq.IQueryable",
+ TestSourceBuilderOptions.Default with
+ {
+ QueryableProjectionNullHandling = QueryableProjectionNullHandling.Ignore,
+ },
+ "class A { public int? IntValue { get; set; } }",
+ "class B { public int IntValue { get; set; } }"
+ );
+
+ TestHelper
+ .GenerateMapper(source)
+ .Should()
+ .HaveSingleMethodBody(
+ """
+ #nullable disable
+ return global::System.Linq.Queryable.Select(
+ source,
+ x => new global::B()
+ {
+ IntValue = x.IntValue.Value,
+ }
+ );
+ #nullable enable
+ """
+ );
+ }
+
+ [Fact]
+ public Task IgnoreShouldProjectDeeplyNestedNullablePathDirectly()
+ {
+ // relies on Mapperly's automatic flattening (Owner.Address.City => OwnerAddressCity),
+ // as MapProperty configuration is not supported directly on queryable projection mappings (RMG065).
+ var source = TestSourceBuilder.Mapping(
+ "System.Linq.IQueryable",
+ "System.Linq.IQueryable",
+ TestSourceBuilderOptions.Default with
+ {
+ QueryableProjectionNullHandling = QueryableProjectionNullHandling.Ignore,
+ },
+ "class A { public C? Owner { get; set; } }",
+ "class B { public string OwnerAddressCity { get; set; } }",
+ "class C { public Address? Address { get; set; } }",
+ "class Address { public string City { get; set; } }"
+ );
+
+ return TestHelper.VerifyGenerator(source);
+ }
+
+ [Fact]
+ public Task IgnoreShouldProjectNullableCollectionMember()
+ {
+ var source = TestSourceBuilder.Mapping(
+ "System.Linq.IQueryable",
+ "System.Linq.IQueryable",
+ TestSourceBuilderOptions.Default with
+ {
+ QueryableProjectionNullHandling = QueryableProjectionNullHandling.Ignore,
+ },
+ "class A { public System.Collections.Generic.List? Items { get; set; } }",
+ "class B { public System.Collections.Generic.List Items { get; set; } }",
+ "class C { public int Id { get; set; } }",
+ "class D { public int Id { get; set; } }"
+ );
+
+ return TestHelper.VerifyGenerator(source);
+ }
+}
diff --git a/test/Riok.Mapperly.Tests/TestSourceBuilder.cs b/test/Riok.Mapperly.Tests/TestSourceBuilder.cs
index 5861f4b988..b95b60311a 100644
--- a/test/Riok.Mapperly.Tests/TestSourceBuilder.cs
+++ b/test/Riok.Mapperly.Tests/TestSourceBuilder.cs
@@ -107,6 +107,7 @@ private static string BuildAttribute(TestSourceBuilderOptions options)
Attribute(options.IncludedConstructors),
Attribute(options.PreferParameterlessConstructors),
Attribute(options.AutoUserMappings),
+ Attribute(options.QueryableProjectionNullHandling),
}.WhereNotNull();
return $"[Mapper({string.Join(", ", attrs)})]";
diff --git a/test/Riok.Mapperly.Tests/TestSourceBuilderOptions.cs b/test/Riok.Mapperly.Tests/TestSourceBuilderOptions.cs
index 6e166ff415..bbe1a10bb8 100644
--- a/test/Riok.Mapperly.Tests/TestSourceBuilderOptions.cs
+++ b/test/Riok.Mapperly.Tests/TestSourceBuilderOptions.cs
@@ -24,7 +24,8 @@ public record TestSourceBuilderOptions(
MemberVisibility? IncludedConstructors = null,
bool Static = false,
bool PreferParameterlessConstructors = true,
- bool AutoUserMappings = true
+ bool AutoUserMappings = true,
+ QueryableProjectionNullHandling? QueryableProjectionNullHandling = null
)
{
public const string DefaultMapperClassName = "Mapper";
diff --git a/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreDisabledNullableContextShouldMatchEnabled#Mapper.g.verified.cs b/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreDisabledNullableContextShouldMatchEnabled#Mapper.g.verified.cs
new file mode 100644
index 0000000000..ea06718d01
--- /dev/null
+++ b/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreDisabledNullableContextShouldMatchEnabled#Mapper.g.verified.cs
@@ -0,0 +1,22 @@
+//HintName: Mapper.g.cs
+//
+#nullable enable
+public partial class Mapper
+{
+ [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
+ [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(source))]
+ private partial global::System.Linq.IQueryable? Map(global::System.Linq.IQueryable? source)
+ {
+ if (source == null)
+ return default;
+#nullable disable
+ return global::System.Linq.Queryable.Select(
+ source,
+ x => new global::B()
+ {
+ Name = x.Name,
+ }
+ );
+#nullable enable
+ }
+}
\ No newline at end of file
diff --git a/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldNotRequireParameterlessCtorForNullableNavigation#Mapper.g.verified.cs b/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldNotRequireParameterlessCtorForNullableNavigation#Mapper.g.verified.cs
new file mode 100644
index 0000000000..031eca90ca
--- /dev/null
+++ b/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldNotRequireParameterlessCtorForNullableNavigation#Mapper.g.verified.cs
@@ -0,0 +1,19 @@
+//HintName: Mapper.g.cs
+//
+#nullable enable
+public partial class Mapper
+{
+ [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
+ private partial global::System.Linq.IQueryable Map(global::System.Linq.IQueryable source)
+ {
+#nullable disable
+ return global::System.Linq.Queryable.Select(
+ source,
+ x => new global::B()
+ {
+ Nested = new global::D(x.Nested.Id),
+ }
+ );
+#nullable enable
+ }
+}
\ No newline at end of file
diff --git a/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldProjectDeeplyNestedNullablePathDirectly#Mapper.g.verified.cs b/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldProjectDeeplyNestedNullablePathDirectly#Mapper.g.verified.cs
new file mode 100644
index 0000000000..8dbfb7844a
--- /dev/null
+++ b/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldProjectDeeplyNestedNullablePathDirectly#Mapper.g.verified.cs
@@ -0,0 +1,19 @@
+//HintName: Mapper.g.cs
+//
+#nullable enable
+public partial class Mapper
+{
+ [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
+ private partial global::System.Linq.IQueryable Map(global::System.Linq.IQueryable source)
+ {
+#nullable disable
+ return global::System.Linq.Queryable.Select(
+ source,
+ x => new global::B()
+ {
+ OwnerAddressCity = x.Owner.Address.City,
+ }
+ );
+#nullable enable
+ }
+}
\ No newline at end of file
diff --git a/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldProjectNullableCollectionMember#Mapper.g.verified.cs b/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldProjectNullableCollectionMember#Mapper.g.verified.cs
new file mode 100644
index 0000000000..72a1afd930
--- /dev/null
+++ b/test/Riok.Mapperly.Tests/_snapshots/QueryableProjectionNullHandlingTest.IgnoreShouldProjectNullableCollectionMember#Mapper.g.verified.cs
@@ -0,0 +1,27 @@
+//HintName: Mapper.g.cs
+//
+#nullable enable
+public partial class Mapper
+{
+ [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "0.0.1.0")]
+ private partial global::System.Linq.IQueryable Map(global::System.Linq.IQueryable source)
+ {
+#nullable disable
+ return global::System.Linq.Queryable.Select(
+ source,
+ x => new global::B()
+ {
+ Items = global::System.Linq.Enumerable.ToList(
+ global::System.Linq.Enumerable.Select(
+ x.Items,
+ x1 => new global::D()
+ {
+ Id = x1.Id,
+ }
+ )
+ ),
+ }
+ );
+#nullable enable
+ }
+}
\ No newline at end of file