From 47cfb0e1c16d4a9a147eae395781aab63f1e2d23 Mon Sep 17 00:00:00 2001 From: Shield1739 <18101480+Shield1739@users.noreply.github.com> Date: Tue, 21 Apr 2026 07:48:29 -0500 Subject: [PATCH 1/4] Allows ValueTypes to be used as Duplicated --- .../Linq/Members/DuplicatedArrayField.cs | 2 +- src/Marten/Linq/Members/DuplicatedField.cs | 45 +- src/Marten/Schema/DocumentMapping.cs | 47 +- ...DuplicateValueTypeDocProvider1638096971.cs | 854 ++++++++++++++++++ src/ValueTypeTests/ValueTypeTests.csproj | 1 + .../duplicated_value_type_field_operations.cs | 74 ++ 6 files changed, 1003 insertions(+), 20 deletions(-) create mode 100644 src/ValueTypeTests/Internal/Generated/DocumentStorage/DuplicateValueTypeDocProvider1638096971.cs create mode 100644 src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs diff --git a/src/Marten/Linq/Members/DuplicatedArrayField.cs b/src/Marten/Linq/Members/DuplicatedArrayField.cs index ce1f73e925..5faceda1ad 100644 --- a/src/Marten/Linq/Members/DuplicatedArrayField.cs +++ b/src/Marten/Linq/Members/DuplicatedArrayField.cs @@ -20,7 +20,7 @@ namespace Marten.Linq.Members; internal class DuplicatedArrayField: DuplicatedField, ICollectionMember, IQueryableMemberCollection { - public DuplicatedArrayField(EnumStorage enumStorage, QueryableMember innerMember, bool useTimestampWithoutTimeZoneForDateTime = true, bool notNull = false) : base(enumStorage, innerMember, useTimestampWithoutTimeZoneForDateTime, notNull) + public DuplicatedArrayField(EnumStorage enumStorage, QueryableMember innerMember, bool useTimestampWithoutTimeZoneForDateTime = true, bool notNull = false) : base(enumStorage, innerMember, null, useTimestampWithoutTimeZoneForDateTime, notNull) { if (innerMember is not ValueCollectionMember) throw new ArgumentOutOfRangeException(nameof(innerMember), diff --git a/src/Marten/Linq/Members/DuplicatedField.cs b/src/Marten/Linq/Members/DuplicatedField.cs index d3c945138d..0d77727366 100644 --- a/src/Marten/Linq/Members/DuplicatedField.cs +++ b/src/Marten/Linq/Members/DuplicatedField.cs @@ -27,7 +27,7 @@ public class DuplicatedField: IQueryableMember, IComparableMember, IHasChildrenM private readonly bool useTimestampWithoutTimeZoneForDateTime; private string _columnName; - public DuplicatedField(EnumStorage enumStorage, QueryableMember innerMember, + public DuplicatedField(EnumStorage enumStorage, QueryableMember innerMember, ValueTypeInfo? valueTypeInfo, bool useTimestampWithoutTimeZoneForDateTime = true, bool notNull = false) { InnerMember = innerMember; @@ -35,6 +35,8 @@ public DuplicatedField(EnumStorage enumStorage, QueryableMember innerMember, Members = InnerMember.Ancestors.OfType().Append(InnerMember).Select(x => x.Member).ToArray(); + ValueTypeInfo = valueTypeInfo; + NotNull = notNull; ColumnName = MemberName.ToTableAlias(); this.useTimestampWithoutTimeZoneForDateTime = useTimestampWithoutTimeZoneForDateTime; @@ -128,15 +130,33 @@ public void PlaceValueInDictionaryForContainment(Dictionary dict /// public NpgsqlDbType DbType { get; set; } + public ValueTypeInfo? ValueTypeInfo { get; } - internal UpsertArgument UpsertArgument => new() + internal UpsertArgument UpsertArgument { - Arg = "arg_" + ColumnName.ToLower(), - Column = ColumnName.ToLower(), - PostgresType = PgType, - Members = Members, - DbType = DbType - }; + get + { + UpsertArgument upsertArgument = new() + { + Arg = "arg_" + ColumnName.ToLower() + , Column = ColumnName.ToLower() + , PostgresType = PgType + , Members = Members + , DbType = DbType + }; + + if (!IsInnerMemberValueType()) return upsertArgument; + + if (InnerMember.Member.GetRawMemberType()!.IsNullable()) + { + upsertArgument.ParameterValue = $"{InnerMember.Member.Name}.Value.{ValueTypeInfo!.ValueProperty.Name}"; + } + + upsertArgument.ParameterValue = $"{InnerMember.Member.Name}.{ValueTypeInfo!.ValueProperty.Name}"; + + return upsertArgument; + } + } public string ColumnName { @@ -169,6 +189,11 @@ string IQueryableMember.SelectorForDuplication(string pgType) public ISqlFragment CreateComparison(string op, ConstantExpression constant) { + if (IsInnerMemberValueType()) + { + return InnerMember.CreateComparison(op, constant); + } + if (constant.Value == null) { return op switch @@ -205,7 +230,7 @@ public static DuplicatedField For(StoreOptions options, Expression(options).QueryMembers.MemberFor(expression); - return new DuplicatedField(options.EnumStorage, (QueryableMember)inner, useTimestampWithoutTimeZoneForDateTime); + return new DuplicatedField(options.EnumStorage, (QueryableMember)inner, null, useTimestampWithoutTimeZoneForDateTime); } // I say you don't need a ForeignKey @@ -252,4 +277,6 @@ public void ReplaceMember(MemberInfo member, IQueryableMember queryableMember) { // Nothing } + + private bool IsInnerMemberValueType() => ValueTypeInfo is not null; } diff --git a/src/Marten/Schema/DocumentMapping.cs b/src/Marten/Schema/DocumentMapping.cs index 9a13240c86..a3443c3b4d 100644 --- a/src/Marten/Schema/DocumentMapping.cs +++ b/src/Marten/Schema/DocumentMapping.cs @@ -19,6 +19,7 @@ using Marten.Schema.Indexing.Unique; using Marten.Storage; using Marten.Storage.Metadata; +using Marten.Util; using NpgsqlTypes; using Weasel.Core; using Weasel.Postgresql; @@ -741,20 +742,33 @@ public DuplicatedField DuplicateField(string memberName, string? pgType = null, var enumStorage = StoreOptions.Advanced.DuplicatedFieldEnumStorage; var dateTimeStorage = StoreOptions.Advanced.DuplicatedFieldUseTimestampWithoutTimeZoneForDateTime; - var duplicate = member is ValueCollectionMember collectionMember - ? new DuplicatedArrayField(enumStorage, collectionMember, dateTimeStorage, notNull) - : new DuplicatedField(enumStorage, (QueryableMember)member, dateTimeStorage, notNull); + + DuplicatedField duplicatedField; + + if (member is ValueCollectionMember collectionMember) + { + duplicatedField = new DuplicatedArrayField(enumStorage, collectionMember, dateTimeStorage, notNull); + } + else if (member.IsGenericInterfaceImplementation(typeof(IValueTypeMember<,>))) + { + var valueTypeInfo = StoreOptions.ValueTypes.FirstOrDefault(x => x.OuterType == member.MemberType)!; + duplicatedField = new DuplicatedValueTypeField(enumStorage, member, valueTypeInfo, notNull); + } + else + { + duplicatedField = new DuplicatedField(enumStorage, member, null, dateTimeStorage, notNull); + } if (pgType.IsNotEmpty()) { - duplicate.PgType = pgType; + duplicatedField.PgType = pgType; } - QueryMembers.ReplaceMember(member.Member, duplicate); + QueryMembers.ReplaceMember(member.Member, duplicatedField); - _duplicates.Add(duplicate); + _duplicates.Add(duplicatedField); - return duplicate; + return duplicatedField; } public DuplicatedField DuplicateField(MemberInfo[] members, string? pgType = null, string? columnName = null, @@ -786,9 +800,22 @@ public DuplicatedField DuplicateField(MemberInfo[] members, string? pgType = nul var enumStorage = StoreOptions.Advanced.DuplicatedFieldEnumStorage; var dateTimeStorage = StoreOptions.Advanced.DuplicatedFieldUseTimestampWithoutTimeZoneForDateTime; - var duplicatedField = member is ValueCollectionMember collectionMember - ? new DuplicatedArrayField(enumStorage, collectionMember, dateTimeStorage, notNull) - : new DuplicatedField(enumStorage, (QueryableMember)member, dateTimeStorage, notNull); + + DuplicatedField duplicatedField; + + if (member is ValueCollectionMember collectionMember) + { + duplicatedField = new DuplicatedArrayField(enumStorage, collectionMember, dateTimeStorage, notNull); + } + else if (member.IsGenericInterfaceImplementation(typeof(IValueTypeMember<,>))) + { + var valueTypeInfo = StoreOptions.ValueTypes.FirstOrDefault(x => x.OuterType == member.MemberType)!; + duplicatedField = new DuplicatedValueTypeField(enumStorage, (QueryableMember)member, valueTypeInfo, notNull); + } + else + { + duplicatedField = new DuplicatedField(enumStorage, (QueryableMember)member, null, dateTimeStorage, notNull); + } parent.ReplaceMember(members.Last(), duplicatedField); diff --git a/src/ValueTypeTests/Internal/Generated/DocumentStorage/DuplicateValueTypeDocProvider1638096971.cs b/src/ValueTypeTests/Internal/Generated/DocumentStorage/DuplicateValueTypeDocProvider1638096971.cs new file mode 100644 index 0000000000..6610296fd2 --- /dev/null +++ b/src/ValueTypeTests/Internal/Generated/DocumentStorage/DuplicateValueTypeDocProvider1638096971.cs @@ -0,0 +1,854 @@ +// +#pragma warning disable +using Marten.Internal; +using Marten.Internal.Storage; +using Marten.Schema; +using Marten.Schema.Arguments; +using Npgsql; +using System; +using System.Collections.Generic; +using ValueTypeTests.VogenIds; +using Weasel.Core; +using Weasel.Postgresql; + +namespace Marten.Generated.DocumentStorage +{ + // START: UpsertDuplicateValueTypeDocOperation1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class UpsertDuplicateValueTypeDocOperation1638096971 : Marten.Internal.Operations.StorageOperation + { + private readonly ValueTypeTests.VogenIds.DuplicateValueTypeDoc _document; + private readonly System.Guid _id; + private readonly System.Collections.Generic.Dictionary _versions; + private readonly Marten.Schema.DocumentMapping _mapping; + + public UpsertDuplicateValueTypeDocOperation1638096971(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, System.Guid id, System.Collections.Generic.Dictionary versions, Marten.Schema.DocumentMapping mapping) : base(document, id, versions, mapping) + { + _document = document; + _id = id; + _versions = versions; + _mapping = mapping; + } + + + + public override void Postprocess(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions) + { + storeVersion(); + } + + + public override System.Threading.Tasks.Task PostprocessAsync(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions, System.Threading.CancellationToken token) + { + storeVersion(); + // Nothing + return System.Threading.Tasks.Task.CompletedTask; + } + + + public override Marten.Internal.Operations.OperationRole Role() + { + return Marten.Internal.Operations.OperationRole.Upsert; + } + + + public override NpgsqlTypes.NpgsqlDbType DbType() + { + return NpgsqlTypes.NpgsqlDbType.Uuid; + } + + + public override void ConfigureParameters(Weasel.Postgresql.IGroupedParameterBuilder parameterBuilder, Weasel.Postgresql.ICommandBuilder builder, ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session) + { + builder.Append("select duplicated_value_type_field.mt_upsert_duplicatevaluetypedoc("); + var parameter0 = parameterBuilder.AppendParameter((document is ValueTypeTests.VogenIds.DuplicateValueTypeDoc ? ((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).DuplicateValueType.Value : default(System.Guid))); + var parameter1 = parameterBuilder.AppendParameter(session.Serializer.ToJson(_document)); + parameter1.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Jsonb; + // .Net Class Type + var parameter2 = parameterBuilder.AppendParameter(_document.GetType().FullName); + parameter2.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar; + var parameter3 = parameterBuilder.AppendParameter((document is ValueTypeTests.VogenIds.DuplicateValueTypeDoc ? ((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).Id : default(System.Guid))); + setVersionParameter(parameterBuilder); + builder.Append(')'); + } + + } + + // END: UpsertDuplicateValueTypeDocOperation1638096971 + + + // START: InsertDuplicateValueTypeDocOperation1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class InsertDuplicateValueTypeDocOperation1638096971 : Marten.Internal.Operations.StorageOperation + { + private readonly ValueTypeTests.VogenIds.DuplicateValueTypeDoc _document; + private readonly System.Guid _id; + private readonly System.Collections.Generic.Dictionary _versions; + private readonly Marten.Schema.DocumentMapping _mapping; + + public InsertDuplicateValueTypeDocOperation1638096971(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, System.Guid id, System.Collections.Generic.Dictionary versions, Marten.Schema.DocumentMapping mapping) : base(document, id, versions, mapping) + { + _document = document; + _id = id; + _versions = versions; + _mapping = mapping; + } + + + + public override void Postprocess(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions) + { + storeVersion(); + } + + + public override System.Threading.Tasks.Task PostprocessAsync(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions, System.Threading.CancellationToken token) + { + storeVersion(); + // Nothing + return System.Threading.Tasks.Task.CompletedTask; + } + + + public override Marten.Internal.Operations.OperationRole Role() + { + return Marten.Internal.Operations.OperationRole.Insert; + } + + + public override NpgsqlTypes.NpgsqlDbType DbType() + { + return NpgsqlTypes.NpgsqlDbType.Uuid; + } + + + public override void ConfigureParameters(Weasel.Postgresql.IGroupedParameterBuilder parameterBuilder, Weasel.Postgresql.ICommandBuilder builder, ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session) + { + builder.Append("select duplicated_value_type_field.mt_insert_duplicatevaluetypedoc("); + var parameter0 = parameterBuilder.AppendParameter((document is ValueTypeTests.VogenIds.DuplicateValueTypeDoc ? ((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).DuplicateValueType.Value : default(System.Guid))); + var parameter1 = parameterBuilder.AppendParameter(session.Serializer.ToJson(_document)); + parameter1.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Jsonb; + // .Net Class Type + var parameter2 = parameterBuilder.AppendParameter(_document.GetType().FullName); + parameter2.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar; + var parameter3 = parameterBuilder.AppendParameter((document is ValueTypeTests.VogenIds.DuplicateValueTypeDoc ? ((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).Id : default(System.Guid))); + setVersionParameter(parameterBuilder); + builder.Append(')'); + } + + } + + // END: InsertDuplicateValueTypeDocOperation1638096971 + + + // START: UpdateDuplicateValueTypeDocOperation1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class UpdateDuplicateValueTypeDocOperation1638096971 : Marten.Internal.Operations.StorageOperation + { + private readonly ValueTypeTests.VogenIds.DuplicateValueTypeDoc _document; + private readonly System.Guid _id; + private readonly System.Collections.Generic.Dictionary _versions; + private readonly Marten.Schema.DocumentMapping _mapping; + + public UpdateDuplicateValueTypeDocOperation1638096971(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, System.Guid id, System.Collections.Generic.Dictionary versions, Marten.Schema.DocumentMapping mapping) : base(document, id, versions, mapping) + { + _document = document; + _id = id; + _versions = versions; + _mapping = mapping; + } + + + + public override void Postprocess(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions) + { + storeVersion(); + postprocessUpdate(reader, exceptions); + } + + + public override async System.Threading.Tasks.Task PostprocessAsync(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions, System.Threading.CancellationToken token) + { + storeVersion(); + await postprocessUpdateAsync(reader, exceptions, token); + } + + + public override Marten.Internal.Operations.OperationRole Role() + { + return Marten.Internal.Operations.OperationRole.Update; + } + + + public override NpgsqlTypes.NpgsqlDbType DbType() + { + return NpgsqlTypes.NpgsqlDbType.Uuid; + } + + + public override void ConfigureParameters(Weasel.Postgresql.IGroupedParameterBuilder parameterBuilder, Weasel.Postgresql.ICommandBuilder builder, ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session) + { + builder.Append("select duplicated_value_type_field.mt_update_duplicatevaluetypedoc("); + var parameter0 = parameterBuilder.AppendParameter((document is ValueTypeTests.VogenIds.DuplicateValueTypeDoc ? ((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).DuplicateValueType.Value : default(System.Guid))); + var parameter1 = parameterBuilder.AppendParameter(session.Serializer.ToJson(_document)); + parameter1.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Jsonb; + // .Net Class Type + var parameter2 = parameterBuilder.AppendParameter(_document.GetType().FullName); + parameter2.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar; + var parameter3 = parameterBuilder.AppendParameter((document is ValueTypeTests.VogenIds.DuplicateValueTypeDoc ? ((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).Id : default(System.Guid))); + setVersionParameter(parameterBuilder); + builder.Append(')'); + } + + } + + // END: UpdateDuplicateValueTypeDocOperation1638096971 + + + // START: QueryOnlyDuplicateValueTypeDocSelector1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class QueryOnlyDuplicateValueTypeDocSelector1638096971 : Marten.Internal.CodeGeneration.DocumentSelectorWithOnlySerializer, Marten.Linq.Selectors.ISelector + { + private readonly Marten.Internal.IMartenSession _session; + private readonly Marten.Schema.DocumentMapping _mapping; + + public QueryOnlyDuplicateValueTypeDocSelector1638096971(Marten.Internal.IMartenSession session, Marten.Schema.DocumentMapping mapping) : base(session, mapping) + { + _session = session; + _mapping = mapping; + } + + + + public ValueTypeTests.VogenIds.DuplicateValueTypeDoc Resolve(System.Data.Common.DbDataReader reader) + { + + ValueTypeTests.VogenIds.DuplicateValueTypeDoc document; + document = _serializer.FromJson(reader, 0); + return document; + } + + + public async System.Threading.Tasks.Task ResolveAsync(System.Data.Common.DbDataReader reader, System.Threading.CancellationToken token) + { + + ValueTypeTests.VogenIds.DuplicateValueTypeDoc document; + document = await _serializer.FromJsonAsync(reader, 0, token).ConfigureAwait(false); + return document; + } + + } + + // END: QueryOnlyDuplicateValueTypeDocSelector1638096971 + + + // START: LightweightDuplicateValueTypeDocSelector1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LightweightDuplicateValueTypeDocSelector1638096971 : Marten.Internal.CodeGeneration.DocumentSelectorWithVersions, Marten.Linq.Selectors.ISelector + { + private readonly Marten.Internal.IMartenSession _session; + private readonly Marten.Schema.DocumentMapping _mapping; + + public LightweightDuplicateValueTypeDocSelector1638096971(Marten.Internal.IMartenSession session, Marten.Schema.DocumentMapping mapping) : base(session, mapping) + { + _session = session; + _mapping = mapping; + } + + + + public ValueTypeTests.VogenIds.DuplicateValueTypeDoc Resolve(System.Data.Common.DbDataReader reader) + { + var id = reader.GetFieldValue(0); + + ValueTypeTests.VogenIds.DuplicateValueTypeDoc document; + document = _serializer.FromJson(reader, 1); + _session.MarkAsDocumentLoaded(id, document); + return document; + } + + + public async System.Threading.Tasks.Task ResolveAsync(System.Data.Common.DbDataReader reader, System.Threading.CancellationToken token) + { + var id = await reader.GetFieldValueAsync(0, token); + + ValueTypeTests.VogenIds.DuplicateValueTypeDoc document; + document = await _serializer.FromJsonAsync(reader, 1, token).ConfigureAwait(false); + _session.MarkAsDocumentLoaded(id, document); + return document; + } + + } + + // END: LightweightDuplicateValueTypeDocSelector1638096971 + + + // START: IdentityMapDuplicateValueTypeDocSelector1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class IdentityMapDuplicateValueTypeDocSelector1638096971 : Marten.Internal.CodeGeneration.DocumentSelectorWithIdentityMap, Marten.Linq.Selectors.ISelector + { + private readonly Marten.Internal.IMartenSession _session; + private readonly Marten.Schema.DocumentMapping _mapping; + + public IdentityMapDuplicateValueTypeDocSelector1638096971(Marten.Internal.IMartenSession session, Marten.Schema.DocumentMapping mapping) : base(session, mapping) + { + _session = session; + _mapping = mapping; + } + + + + public ValueTypeTests.VogenIds.DuplicateValueTypeDoc Resolve(System.Data.Common.DbDataReader reader) + { + var id = reader.GetFieldValue(0); + if (_identityMap.TryGetValue(id, out var existing)) return existing; + + ValueTypeTests.VogenIds.DuplicateValueTypeDoc document; + document = _serializer.FromJson(reader, 1); + _session.MarkAsDocumentLoaded(id, document); + _identityMap[id] = document; + return document; + } + + + public async System.Threading.Tasks.Task ResolveAsync(System.Data.Common.DbDataReader reader, System.Threading.CancellationToken token) + { + var id = await reader.GetFieldValueAsync(0, token); + if (_identityMap.TryGetValue(id, out var existing)) return existing; + + ValueTypeTests.VogenIds.DuplicateValueTypeDoc document; + document = await _serializer.FromJsonAsync(reader, 1, token).ConfigureAwait(false); + _session.MarkAsDocumentLoaded(id, document); + _identityMap[id] = document; + return document; + } + + } + + // END: IdentityMapDuplicateValueTypeDocSelector1638096971 + + + // START: DirtyTrackingDuplicateValueTypeDocSelector1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DirtyTrackingDuplicateValueTypeDocSelector1638096971 : Marten.Internal.CodeGeneration.DocumentSelectorWithDirtyChecking, Marten.Linq.Selectors.ISelector + { + private readonly Marten.Internal.IMartenSession _session; + private readonly Marten.Schema.DocumentMapping _mapping; + + public DirtyTrackingDuplicateValueTypeDocSelector1638096971(Marten.Internal.IMartenSession session, Marten.Schema.DocumentMapping mapping) : base(session, mapping) + { + _session = session; + _mapping = mapping; + } + + + + public ValueTypeTests.VogenIds.DuplicateValueTypeDoc Resolve(System.Data.Common.DbDataReader reader) + { + var id = reader.GetFieldValue(0); + if (_identityMap.TryGetValue(id, out var existing)) return existing; + + ValueTypeTests.VogenIds.DuplicateValueTypeDoc document; + document = _serializer.FromJson(reader, 1); + _session.MarkAsDocumentLoaded(id, document); + _identityMap[id] = document; + StoreTracker(_session, document); + return document; + } + + + public async System.Threading.Tasks.Task ResolveAsync(System.Data.Common.DbDataReader reader, System.Threading.CancellationToken token) + { + var id = await reader.GetFieldValueAsync(0, token); + if (_identityMap.TryGetValue(id, out var existing)) return existing; + + ValueTypeTests.VogenIds.DuplicateValueTypeDoc document; + document = await _serializer.FromJsonAsync(reader, 1, token).ConfigureAwait(false); + _session.MarkAsDocumentLoaded(id, document); + _identityMap[id] = document; + StoreTracker(_session, document); + return document; + } + + } + + // END: DirtyTrackingDuplicateValueTypeDocSelector1638096971 + + + // START: QueryOnlyDuplicateValueTypeDocDocumentStorage1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class QueryOnlyDuplicateValueTypeDocDocumentStorage1638096971 : Marten.Internal.Storage.QueryOnlyDocumentStorage + { + private readonly Marten.Schema.DocumentMapping _document; + + public QueryOnlyDuplicateValueTypeDocDocumentStorage1638096971(Marten.Schema.DocumentMapping document) : base(document) + { + _document = document; + } + + + + public override System.Guid AssignIdentity(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, string tenantId, Marten.Storage.IMartenDatabase database) + { + if (document.Id == Guid.Empty) _setter(document, JasperFx.Core.CombGuidIdGeneration.NewGuid()); + return document.Id; + } + + + public override Marten.Internal.Operations.IStorageOperation Update(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpdateDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Insert(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.InsertDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Upsert(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpsertDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Overwrite(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + throw new System.NotSupportedException(); + } + + + public override System.Guid Identity(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document) + { + return document.Id; + } + + + public override Marten.Linq.Selectors.ISelector BuildSelector(Marten.Internal.IMartenSession session) + { + return new Marten.Generated.DocumentStorage.QueryOnlyDuplicateValueTypeDocSelector1638096971(session, _document); + } + + + public override object RawIdentityValue(System.Guid id) + { + return id; + } + + + public override Npgsql.NpgsqlParameter BuildManyIdParameter(System.Guid[] ids) + { + return base.BuildManyIdParameter(ids); + } + + } + + // END: QueryOnlyDuplicateValueTypeDocDocumentStorage1638096971 + + + // START: LightweightDuplicateValueTypeDocDocumentStorage1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LightweightDuplicateValueTypeDocDocumentStorage1638096971 : Marten.Internal.Storage.LightweightDocumentStorage + { + private readonly Marten.Schema.DocumentMapping _document; + + public LightweightDuplicateValueTypeDocDocumentStorage1638096971(Marten.Schema.DocumentMapping document) : base(document) + { + _document = document; + } + + + + public override System.Guid AssignIdentity(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, string tenantId, Marten.Storage.IMartenDatabase database) + { + if (document.Id == Guid.Empty) _setter(document, JasperFx.Core.CombGuidIdGeneration.NewGuid()); + return document.Id; + } + + + public override Marten.Internal.Operations.IStorageOperation Update(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpdateDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Insert(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.InsertDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Upsert(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpsertDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Overwrite(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + throw new System.NotSupportedException(); + } + + + public override System.Guid Identity(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document) + { + return document.Id; + } + + + public override Marten.Linq.Selectors.ISelector BuildSelector(Marten.Internal.IMartenSession session) + { + return new Marten.Generated.DocumentStorage.LightweightDuplicateValueTypeDocSelector1638096971(session, _document); + } + + + public override object RawIdentityValue(System.Guid id) + { + return id; + } + + + public override Npgsql.NpgsqlParameter BuildManyIdParameter(System.Guid[] ids) + { + return base.BuildManyIdParameter(ids); + } + + } + + // END: LightweightDuplicateValueTypeDocDocumentStorage1638096971 + + + // START: IdentityMapDuplicateValueTypeDocDocumentStorage1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class IdentityMapDuplicateValueTypeDocDocumentStorage1638096971 : Marten.Internal.Storage.IdentityMapDocumentStorage + { + private readonly Marten.Schema.DocumentMapping _document; + + public IdentityMapDuplicateValueTypeDocDocumentStorage1638096971(Marten.Schema.DocumentMapping document) : base(document) + { + _document = document; + } + + + + public override System.Guid AssignIdentity(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, string tenantId, Marten.Storage.IMartenDatabase database) + { + if (document.Id == Guid.Empty) _setter(document, JasperFx.Core.CombGuidIdGeneration.NewGuid()); + return document.Id; + } + + + public override Marten.Internal.Operations.IStorageOperation Update(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpdateDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Insert(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.InsertDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Upsert(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpsertDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Overwrite(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + throw new System.NotSupportedException(); + } + + + public override System.Guid Identity(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document) + { + return document.Id; + } + + + public override Marten.Linq.Selectors.ISelector BuildSelector(Marten.Internal.IMartenSession session) + { + return new Marten.Generated.DocumentStorage.IdentityMapDuplicateValueTypeDocSelector1638096971(session, _document); + } + + + public override object RawIdentityValue(System.Guid id) + { + return id; + } + + + public override Npgsql.NpgsqlParameter BuildManyIdParameter(System.Guid[] ids) + { + return base.BuildManyIdParameter(ids); + } + + } + + // END: IdentityMapDuplicateValueTypeDocDocumentStorage1638096971 + + + // START: DirtyTrackingDuplicateValueTypeDocDocumentStorage1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DirtyTrackingDuplicateValueTypeDocDocumentStorage1638096971 : Marten.Internal.Storage.DirtyCheckedDocumentStorage + { + private readonly Marten.Schema.DocumentMapping _document; + + public DirtyTrackingDuplicateValueTypeDocDocumentStorage1638096971(Marten.Schema.DocumentMapping document) : base(document) + { + _document = document; + } + + + + public override System.Guid AssignIdentity(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, string tenantId, Marten.Storage.IMartenDatabase database) + { + if (document.Id == Guid.Empty) _setter(document, JasperFx.Core.CombGuidIdGeneration.NewGuid()); + return document.Id; + } + + + public override Marten.Internal.Operations.IStorageOperation Update(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpdateDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Insert(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.InsertDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Upsert(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpsertDuplicateValueTypeDocOperation1638096971 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Overwrite(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + throw new System.NotSupportedException(); + } + + + public override System.Guid Identity(ValueTypeTests.VogenIds.DuplicateValueTypeDoc document) + { + return document.Id; + } + + + public override Marten.Linq.Selectors.ISelector BuildSelector(Marten.Internal.IMartenSession session) + { + return new Marten.Generated.DocumentStorage.DirtyTrackingDuplicateValueTypeDocSelector1638096971(session, _document); + } + + + public override object RawIdentityValue(System.Guid id) + { + return id; + } + + + public override Npgsql.NpgsqlParameter BuildManyIdParameter(System.Guid[] ids) + { + return base.BuildManyIdParameter(ids); + } + + } + + // END: DirtyTrackingDuplicateValueTypeDocDocumentStorage1638096971 + + + // START: DuplicateValueTypeDocBulkLoader1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DuplicateValueTypeDocBulkLoader1638096971 : Marten.Internal.CodeGeneration.BulkLoader + { + private readonly Marten.Internal.Storage.IDocumentStorage _storage; + + public DuplicateValueTypeDocBulkLoader1638096971(Marten.Internal.Storage.IDocumentStorage storage) : base(storage) + { + _storage = storage; + } + + + public const string MAIN_LOADER_SQL = "COPY duplicated_value_type_field.mt_doc_duplicatevaluetypedoc(\"duplicate_value_type\", \"mt_dotnet_type\", \"id\", \"mt_version\", \"data\") FROM STDIN BINARY"; + + public const string TEMP_LOADER_SQL = "COPY mt_doc_duplicatevaluetypedoc_temp(\"duplicate_value_type\", \"mt_dotnet_type\", \"id\", \"mt_expected_version\", \"mt_version\", \"data\") FROM STDIN BINARY"; + + public const string COPY_NEW_DOCUMENTS_SQL = "insert into duplicated_value_type_field.mt_doc_duplicatevaluetypedoc (\"id\", \"data\", \"mt_version\", \"mt_dotnet_type\", \"duplicate_value_type\", mt_last_modified) (select mt_doc_duplicatevaluetypedoc_temp.\"id\", mt_doc_duplicatevaluetypedoc_temp.\"data\", mt_doc_duplicatevaluetypedoc_temp.\"mt_version\", mt_doc_duplicatevaluetypedoc_temp.\"mt_dotnet_type\", mt_doc_duplicatevaluetypedoc_temp.\"duplicate_value_type\", transaction_timestamp() from mt_doc_duplicatevaluetypedoc_temp left join duplicated_value_type_field.mt_doc_duplicatevaluetypedoc on mt_doc_duplicatevaluetypedoc_temp.id = duplicated_value_type_field.mt_doc_duplicatevaluetypedoc.id where duplicated_value_type_field.mt_doc_duplicatevaluetypedoc.id is null)"; + + public const string OVERWRITE_SQL = "update duplicated_value_type_field.mt_doc_duplicatevaluetypedoc target SET data = source.data, mt_version = source.mt_version, mt_dotnet_type = source.mt_dotnet_type, duplicate_value_type = source.duplicate_value_type, mt_last_modified = transaction_timestamp() FROM mt_doc_duplicatevaluetypedoc_temp source WHERE source.id = target.id"; + + public const string OVERWRITE_WITH_VERSION_SQL = "update duplicated_value_type_field.mt_doc_duplicatevaluetypedoc target SET data = source.data, mt_version = source.mt_version, mt_dotnet_type = source.mt_dotnet_type, duplicate_value_type = source.duplicate_value_type, mt_last_modified = transaction_timestamp() FROM mt_doc_duplicatevaluetypedoc_temp source WHERE source.id = target.id and target.mt_version = source.mt_expected_version"; + + public const string CREATE_TEMP_TABLE_FOR_COPYING_SQL = "create temporary table mt_doc_duplicatevaluetypedoc_temp (like duplicated_value_type_field.mt_doc_duplicatevaluetypedoc including defaults, \"mt_expected_version\" uuid)"; + + + public override string CreateTempTableForCopying() + { + return CREATE_TEMP_TABLE_FOR_COPYING_SQL; + } + + + public override string CopyNewDocumentsFromTempTable() + { + return COPY_NEW_DOCUMENTS_SQL; + } + + + public override string OverwriteDuplicatesFromTempTable() + { + return OVERWRITE_SQL; + } + + + public override string OverwriteDuplicatesFromTempTableWithVersionCheck() + { + return OVERWRITE_WITH_VERSION_SQL; + } + + + public override async System.Threading.Tasks.Task LoadRowAsync(Npgsql.NpgsqlBinaryImporter writer, ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Storage.Tenant tenant, Marten.ISerializer serializer, System.Threading.CancellationToken cancellation) + { + await writer.WriteAsync(((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).DuplicateValueType.Value, NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(document.GetType().FullName, NpgsqlTypes.NpgsqlDbType.Varchar, cancellation); + await writer.WriteAsync(((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).Id, NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(JasperFx.Core.CombGuidIdGeneration.NewGuid(), NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(serializer.ToJson(document), NpgsqlTypes.NpgsqlDbType.Jsonb, cancellation); + } + + + public override async System.Threading.Tasks.Task LoadTempRowAsync(Npgsql.NpgsqlBinaryImporter writer, ValueTypeTests.VogenIds.DuplicateValueTypeDoc document, Marten.Storage.Tenant tenant, Marten.ISerializer serializer, System.Threading.CancellationToken cancellation) + { + await writer.WriteAsync(((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).DuplicateValueType.Value, NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(document.GetType().FullName, NpgsqlTypes.NpgsqlDbType.Varchar, cancellation); + await writer.WriteAsync(((ValueTypeTests.VogenIds.DuplicateValueTypeDoc)document).Id, NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + writer.Write(System.DBNull.Value, 0); + await writer.WriteAsync(JasperFx.Core.CombGuidIdGeneration.NewGuid(), NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(serializer.ToJson(document), NpgsqlTypes.NpgsqlDbType.Jsonb, cancellation); + } + + + public override string MainLoaderSql() + { + return MAIN_LOADER_SQL; + } + + + public override string TempLoaderSql() + { + return TEMP_LOADER_SQL; + } + + } + + // END: DuplicateValueTypeDocBulkLoader1638096971 + + + // START: DuplicateValueTypeDocProvider1638096971 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DuplicateValueTypeDocProvider1638096971 : Marten.Internal.Storage.DocumentProvider + { + private readonly Marten.Schema.DocumentMapping _mapping; + + public DuplicateValueTypeDocProvider1638096971(Marten.Schema.DocumentMapping mapping) : base(new DuplicateValueTypeDocBulkLoader1638096971(new QueryOnlyDuplicateValueTypeDocDocumentStorage1638096971(mapping)), new QueryOnlyDuplicateValueTypeDocDocumentStorage1638096971(mapping), new LightweightDuplicateValueTypeDocDocumentStorage1638096971(mapping), new IdentityMapDuplicateValueTypeDocDocumentStorage1638096971(mapping), new DirtyTrackingDuplicateValueTypeDocDocumentStorage1638096971(mapping)) + { + _mapping = mapping; + } + + + } + + // END: DuplicateValueTypeDocProvider1638096971 + + +} + diff --git a/src/ValueTypeTests/ValueTypeTests.csproj b/src/ValueTypeTests/ValueTypeTests.csproj index 06dfca41a3..f7ea3a07b6 100644 --- a/src/ValueTypeTests/ValueTypeTests.csproj +++ b/src/ValueTypeTests/ValueTypeTests.csproj @@ -41,6 +41,7 @@ + diff --git a/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs b/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs new file mode 100644 index 0000000000..f094a62bd5 --- /dev/null +++ b/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs @@ -0,0 +1,74 @@ +using System; +using System.Threading.Tasks; +using JasperFx.CodeGeneration; +using JasperFx.Core; +using Marten; +using Marten.Testing.Harness; +using Shouldly; +using Vogen; + +namespace ValueTypeTests.VogenIds; + +public class duplicated_value_type_field_operations : IDisposable, IAsyncDisposable +{ + private readonly DocumentStore theStore; + private IDocumentSession theSession; + + public duplicated_value_type_field_operations() + { + theStore = DocumentStore.For(opts => + { + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = "duplicated_value_type_field"; + + opts.ApplicationAssembly = GetType().Assembly; + opts.GeneratedCodeMode = TypeLoadMode.Auto; + opts.GeneratedCodeOutputPath = + AppContext.BaseDirectory.ParentDirectory().ParentDirectory().ParentDirectory().AppendPath("Internal", "Generated"); + + opts.RegisterValueType(); + opts.Schema.For().Duplicate(x => x.DuplicateValueType); + }); + + theSession = theStore.LightweightSession(); + } + + public void Dispose() + { + theStore?.Dispose(); + theSession?.Dispose(); + } + + public async ValueTask DisposeAsync() + { + if (theStore != null) + { + await theStore.DisposeAsync(); + } + } + + [Fact] + public async Task load_document() + { + var duplicatedDoc = new DuplicateValueTypeDoc + { + Id = Guid.NewGuid(), + DuplicateValueType = DuplicateValueType.From(Guid.NewGuid()) + }; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + (await theSession.LoadAsync(duplicatedDoc.Id)) + .DuplicateValueType.ShouldBe(duplicatedDoc.DuplicateValueType); + } +} + +[ValueObject] +public readonly partial struct DuplicateValueType; + +public class DuplicateValueTypeDoc +{ + public Guid Id { get; set; } + public DuplicateValueType DuplicateValueType { get; set; } +} From fce5c055b2594e97ac7e5044be22364cb1f95774 Mon Sep 17 00:00:00 2001 From: Luis Villalaz <18101480+shield1739@users.noreply.github.com> Date: Tue, 21 Apr 2026 10:59:05 -0500 Subject: [PATCH 2/4] Extracts Duplicated ValueType Field logic into its own class --- .../Linq/Members/DuplicatedArrayField.cs | 2 +- src/Marten/Linq/Members/DuplicatedField.cs | 48 ++++--------------- .../Linq/Members/DuplicatedValueTypeField.cs | 41 ++++++++++++++++ src/Marten/Schema/DocumentMapping.cs | 4 +- 4 files changed, 54 insertions(+), 41 deletions(-) create mode 100644 src/Marten/Linq/Members/DuplicatedValueTypeField.cs diff --git a/src/Marten/Linq/Members/DuplicatedArrayField.cs b/src/Marten/Linq/Members/DuplicatedArrayField.cs index 5faceda1ad..ce1f73e925 100644 --- a/src/Marten/Linq/Members/DuplicatedArrayField.cs +++ b/src/Marten/Linq/Members/DuplicatedArrayField.cs @@ -20,7 +20,7 @@ namespace Marten.Linq.Members; internal class DuplicatedArrayField: DuplicatedField, ICollectionMember, IQueryableMemberCollection { - public DuplicatedArrayField(EnumStorage enumStorage, QueryableMember innerMember, bool useTimestampWithoutTimeZoneForDateTime = true, bool notNull = false) : base(enumStorage, innerMember, null, useTimestampWithoutTimeZoneForDateTime, notNull) + public DuplicatedArrayField(EnumStorage enumStorage, QueryableMember innerMember, bool useTimestampWithoutTimeZoneForDateTime = true, bool notNull = false) : base(enumStorage, innerMember, useTimestampWithoutTimeZoneForDateTime, notNull) { if (innerMember is not ValueCollectionMember) throw new ArgumentOutOfRangeException(nameof(innerMember), diff --git a/src/Marten/Linq/Members/DuplicatedField.cs b/src/Marten/Linq/Members/DuplicatedField.cs index 0d77727366..8144c53cc3 100644 --- a/src/Marten/Linq/Members/DuplicatedField.cs +++ b/src/Marten/Linq/Members/DuplicatedField.cs @@ -27,7 +27,7 @@ public class DuplicatedField: IQueryableMember, IComparableMember, IHasChildrenM private readonly bool useTimestampWithoutTimeZoneForDateTime; private string _columnName; - public DuplicatedField(EnumStorage enumStorage, QueryableMember innerMember, ValueTypeInfo? valueTypeInfo, + public DuplicatedField(EnumStorage enumStorage, QueryableMember innerMember, bool useTimestampWithoutTimeZoneForDateTime = true, bool notNull = false) { InnerMember = innerMember; @@ -35,8 +35,6 @@ public DuplicatedField(EnumStorage enumStorage, QueryableMember innerMember, Val Members = InnerMember.Ancestors.OfType().Append(InnerMember).Select(x => x.Member).ToArray(); - ValueTypeInfo = valueTypeInfo; - NotNull = notNull; ColumnName = MemberName.ToTableAlias(); this.useTimestampWithoutTimeZoneForDateTime = useTimestampWithoutTimeZoneForDateTime; @@ -130,33 +128,14 @@ public void PlaceValueInDictionaryForContainment(Dictionary dict /// public NpgsqlDbType DbType { get; set; } - public ValueTypeInfo? ValueTypeInfo { get; } - - internal UpsertArgument UpsertArgument + internal virtual UpsertArgument UpsertArgument => new() { - get - { - UpsertArgument upsertArgument = new() - { - Arg = "arg_" + ColumnName.ToLower() - , Column = ColumnName.ToLower() - , PostgresType = PgType - , Members = Members - , DbType = DbType - }; - - if (!IsInnerMemberValueType()) return upsertArgument; - - if (InnerMember.Member.GetRawMemberType()!.IsNullable()) - { - upsertArgument.ParameterValue = $"{InnerMember.Member.Name}.Value.{ValueTypeInfo!.ValueProperty.Name}"; - } - - upsertArgument.ParameterValue = $"{InnerMember.Member.Name}.{ValueTypeInfo!.ValueProperty.Name}"; - - return upsertArgument; - } - } + Arg = "arg_" + ColumnName.ToLower(), + Column = ColumnName.ToLower(), + PostgresType = PgType, + Members = Members, + DbType = DbType + }; public string ColumnName { @@ -187,13 +166,8 @@ string IQueryableMember.SelectorForDuplication(string pgType) throw new NotSupportedException(); } - public ISqlFragment CreateComparison(string op, ConstantExpression constant) + public virtual ISqlFragment CreateComparison(string op, ConstantExpression constant) { - if (IsInnerMemberValueType()) - { - return InnerMember.CreateComparison(op, constant); - } - if (constant.Value == null) { return op switch @@ -230,7 +204,7 @@ public static DuplicatedField For(StoreOptions options, Expression(options).QueryMembers.MemberFor(expression); - return new DuplicatedField(options.EnumStorage, (QueryableMember)inner, null, useTimestampWithoutTimeZoneForDateTime); + return new DuplicatedField(options.EnumStorage, (QueryableMember)inner, useTimestampWithoutTimeZoneForDateTime); } // I say you don't need a ForeignKey @@ -277,6 +251,4 @@ public void ReplaceMember(MemberInfo member, IQueryableMember queryableMember) { // Nothing } - - private bool IsInnerMemberValueType() => ValueTypeInfo is not null; } diff --git a/src/Marten/Linq/Members/DuplicatedValueTypeField.cs b/src/Marten/Linq/Members/DuplicatedValueTypeField.cs new file mode 100644 index 0000000000..db6dfab665 --- /dev/null +++ b/src/Marten/Linq/Members/DuplicatedValueTypeField.cs @@ -0,0 +1,41 @@ +using System.Linq.Expressions; +using JasperFx.Core.Reflection; +using Marten.Schema.Arguments; +using Weasel.Core; +using Weasel.Postgresql.SqlGeneration; + +namespace Marten.Linq.Members; + +public class DuplicatedValueTypeField: DuplicatedField +{ + public DuplicatedValueTypeField(EnumStorage enumStorage, QueryableMember innerMember, ValueTypeInfo valueTypeInfo + , bool useTimestampWithoutTimeZoneForDateTime = true, bool notNull = false): base( + enumStorage, innerMember, useTimestampWithoutTimeZoneForDateTime, notNull) + { + ValueTypeInfo = valueTypeInfo; + } + + public ValueTypeInfo ValueTypeInfo { get; } + + internal override UpsertArgument UpsertArgument + { + get + { + var upsertArgument = base.UpsertArgument; + + if (InnerMember.Member.GetRawMemberType()!.IsNullable()) + { + upsertArgument.ParameterValue = $"{InnerMember.Member.Name}.Value.{ValueTypeInfo.ValueProperty.Name}"; + } + + upsertArgument.ParameterValue = $"{InnerMember.Member.Name}.{ValueTypeInfo.ValueProperty.Name}"; + + return upsertArgument; + } + } + + public override ISqlFragment CreateComparison(string op, ConstantExpression constant) + { + return InnerMember.CreateComparison(op, constant); + } +} diff --git a/src/Marten/Schema/DocumentMapping.cs b/src/Marten/Schema/DocumentMapping.cs index a3443c3b4d..f666d462ef 100644 --- a/src/Marten/Schema/DocumentMapping.cs +++ b/src/Marten/Schema/DocumentMapping.cs @@ -756,7 +756,7 @@ public DuplicatedField DuplicateField(string memberName, string? pgType = null, } else { - duplicatedField = new DuplicatedField(enumStorage, member, null, dateTimeStorage, notNull); + duplicatedField = new DuplicatedField(enumStorage, member, dateTimeStorage, notNull); } if (pgType.IsNotEmpty()) @@ -814,7 +814,7 @@ public DuplicatedField DuplicateField(MemberInfo[] members, string? pgType = nul } else { - duplicatedField = new DuplicatedField(enumStorage, (QueryableMember)member, null, dateTimeStorage, notNull); + duplicatedField = new DuplicatedField(enumStorage, (QueryableMember)member, dateTimeStorage, notNull); } parent.ReplaceMember(members.Last(), duplicatedField); From e21af61afd683d20b4152342c2e9193582511673 Mon Sep 17 00:00:00 2001 From: Luis Villalaz <18101480+shield1739@users.noreply.github.com> Date: Tue, 21 Apr 2026 10:59:32 -0500 Subject: [PATCH 3/4] Adds Duplicated ValueType Field Vogen tests --- .../duplicated_value_type_field_operations.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs b/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs index f094a62bd5..a5b98f173c 100644 --- a/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs +++ b/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading.Tasks; using JasperFx.CodeGeneration; using JasperFx.Core; @@ -47,6 +48,17 @@ public async ValueTask DisposeAsync() } } + [Fact] + public async Task store_a_document_smoke_test() + { + var duplicatedDoc = new DuplicateValueTypeDoc(){DuplicateValueType = DuplicateValueType.From(Guid.NewGuid())}; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + (await theSession.Query().AnyAsync()).ShouldBeTrue(); + } + [Fact] public async Task load_document() { @@ -62,6 +74,57 @@ public async Task load_document() (await theSession.LoadAsync(duplicatedDoc.Id)) .DuplicateValueType.ShouldBe(duplicatedDoc.DuplicateValueType); } + + [Fact] + public async Task load_many() + { + var duplicatedDoc1 = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.From(Guid.NewGuid())}; + var duplicatedDoc2 = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.From(Guid.NewGuid())}; + var duplicatedDoc3 = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.From(Guid.NewGuid())}; + theSession.Store(duplicatedDoc1, duplicatedDoc2, duplicatedDoc3); + + await theSession.SaveChangesAsync(); + + var results = await theSession.Query().Where(x => x.Id.IsOneOf(duplicatedDoc1.Id, duplicatedDoc2.Id, duplicatedDoc3.Id)).ToListAsync(); + results.Count.ShouldBe(3); + } + + [Fact] + public async Task use_in_LINQ_where_clause() + { + var duplicatedDoc = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.From(Guid.NewGuid())}; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + var loaded = await theSession.Query() + .FirstOrDefaultAsync(x => x.DuplicateValueType == duplicatedDoc.DuplicateValueType); + + loaded.ShouldNotBeNull(); + } + + [Fact] + public async Task use_in_LINQ_duplicatedDoc_clause() + { + var duplicatedDoc = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.From(Guid.NewGuid())}; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + var loaded = await theSession.Query().OrderBy(x => x.Id).Take(3).ToListAsync(); + } + + [Fact] + public async Task use_in_LINQ_select_clause() + { + var duplicatedDoc = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.From(Guid.NewGuid())}; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + var loaded = await theSession.Query().Select(x => x.Id).Take(3).ToListAsync(); + + } } [ValueObject] From 4249f8856e56c88c3ce42d70425a6aaea6c55342 Mon Sep 17 00:00:00 2001 From: Luis Villalaz <18101480+shield1739@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:26:09 -0500 Subject: [PATCH 4/4] Adds Duplicated ValueType Field StronglyTypedId tests --- ...DuplicateValueTypeDocProvider1126046928.cs | 854 ++++++++++++++++++ .../duplicated_value_type_field_operations.cs | 137 +++ src/ValueTypeTests/ValueTypeTests.csproj | 1 + .../duplicated_value_type_field_operations.cs | 2 +- 4 files changed, 993 insertions(+), 1 deletion(-) create mode 100644 src/ValueTypeTests/Internal/Generated/DocumentStorage/DuplicateValueTypeDocProvider1126046928.cs create mode 100644 src/ValueTypeTests/StrongTypedId/duplicated_value_type_field_operations.cs diff --git a/src/ValueTypeTests/Internal/Generated/DocumentStorage/DuplicateValueTypeDocProvider1126046928.cs b/src/ValueTypeTests/Internal/Generated/DocumentStorage/DuplicateValueTypeDocProvider1126046928.cs new file mode 100644 index 0000000000..b4df910d6b --- /dev/null +++ b/src/ValueTypeTests/Internal/Generated/DocumentStorage/DuplicateValueTypeDocProvider1126046928.cs @@ -0,0 +1,854 @@ +// +#pragma warning disable +using Marten.Internal; +using Marten.Internal.Storage; +using Marten.Schema; +using Marten.Schema.Arguments; +using Npgsql; +using System; +using System.Collections.Generic; +using ValueTypeTests.StrongTypedId; +using Weasel.Core; +using Weasel.Postgresql; + +namespace Marten.Generated.DocumentStorage +{ + // START: UpsertDuplicateValueTypeDocOperation1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class UpsertDuplicateValueTypeDocOperation1126046928 : Marten.Internal.Operations.StorageOperation + { + private readonly ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc _document; + private readonly System.Guid _id; + private readonly System.Collections.Generic.Dictionary _versions; + private readonly Marten.Schema.DocumentMapping _mapping; + + public UpsertDuplicateValueTypeDocOperation1126046928(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, System.Guid id, System.Collections.Generic.Dictionary versions, Marten.Schema.DocumentMapping mapping) : base(document, id, versions, mapping) + { + _document = document; + _id = id; + _versions = versions; + _mapping = mapping; + } + + + + public override void Postprocess(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions) + { + storeVersion(); + } + + + public override System.Threading.Tasks.Task PostprocessAsync(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions, System.Threading.CancellationToken token) + { + storeVersion(); + // Nothing + return System.Threading.Tasks.Task.CompletedTask; + } + + + public override Marten.Internal.Operations.OperationRole Role() + { + return Marten.Internal.Operations.OperationRole.Upsert; + } + + + public override NpgsqlTypes.NpgsqlDbType DbType() + { + return NpgsqlTypes.NpgsqlDbType.Uuid; + } + + + public override void ConfigureParameters(Weasel.Postgresql.IGroupedParameterBuilder parameterBuilder, Weasel.Postgresql.ICommandBuilder builder, ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session) + { + builder.Append("select duplicated_value_type_field1.mt_upsert_duplicatevaluetypedoc("); + var parameter0 = parameterBuilder.AppendParameter((document is ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc ? ((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).DuplicateValueType.Value : default(System.Guid))); + var parameter1 = parameterBuilder.AppendParameter(session.Serializer.ToJson(_document)); + parameter1.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Jsonb; + // .Net Class Type + var parameter2 = parameterBuilder.AppendParameter(_document.GetType().FullName); + parameter2.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar; + var parameter3 = parameterBuilder.AppendParameter((document is ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc ? ((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).Id : default(System.Guid))); + setVersionParameter(parameterBuilder); + builder.Append(')'); + } + + } + + // END: UpsertDuplicateValueTypeDocOperation1126046928 + + + // START: InsertDuplicateValueTypeDocOperation1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class InsertDuplicateValueTypeDocOperation1126046928 : Marten.Internal.Operations.StorageOperation + { + private readonly ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc _document; + private readonly System.Guid _id; + private readonly System.Collections.Generic.Dictionary _versions; + private readonly Marten.Schema.DocumentMapping _mapping; + + public InsertDuplicateValueTypeDocOperation1126046928(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, System.Guid id, System.Collections.Generic.Dictionary versions, Marten.Schema.DocumentMapping mapping) : base(document, id, versions, mapping) + { + _document = document; + _id = id; + _versions = versions; + _mapping = mapping; + } + + + + public override void Postprocess(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions) + { + storeVersion(); + } + + + public override System.Threading.Tasks.Task PostprocessAsync(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions, System.Threading.CancellationToken token) + { + storeVersion(); + // Nothing + return System.Threading.Tasks.Task.CompletedTask; + } + + + public override Marten.Internal.Operations.OperationRole Role() + { + return Marten.Internal.Operations.OperationRole.Insert; + } + + + public override NpgsqlTypes.NpgsqlDbType DbType() + { + return NpgsqlTypes.NpgsqlDbType.Uuid; + } + + + public override void ConfigureParameters(Weasel.Postgresql.IGroupedParameterBuilder parameterBuilder, Weasel.Postgresql.ICommandBuilder builder, ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session) + { + builder.Append("select duplicated_value_type_field1.mt_insert_duplicatevaluetypedoc("); + var parameter0 = parameterBuilder.AppendParameter((document is ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc ? ((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).DuplicateValueType.Value : default(System.Guid))); + var parameter1 = parameterBuilder.AppendParameter(session.Serializer.ToJson(_document)); + parameter1.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Jsonb; + // .Net Class Type + var parameter2 = parameterBuilder.AppendParameter(_document.GetType().FullName); + parameter2.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar; + var parameter3 = parameterBuilder.AppendParameter((document is ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc ? ((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).Id : default(System.Guid))); + setVersionParameter(parameterBuilder); + builder.Append(')'); + } + + } + + // END: InsertDuplicateValueTypeDocOperation1126046928 + + + // START: UpdateDuplicateValueTypeDocOperation1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class UpdateDuplicateValueTypeDocOperation1126046928 : Marten.Internal.Operations.StorageOperation + { + private readonly ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc _document; + private readonly System.Guid _id; + private readonly System.Collections.Generic.Dictionary _versions; + private readonly Marten.Schema.DocumentMapping _mapping; + + public UpdateDuplicateValueTypeDocOperation1126046928(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, System.Guid id, System.Collections.Generic.Dictionary versions, Marten.Schema.DocumentMapping mapping) : base(document, id, versions, mapping) + { + _document = document; + _id = id; + _versions = versions; + _mapping = mapping; + } + + + + public override void Postprocess(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions) + { + storeVersion(); + postprocessUpdate(reader, exceptions); + } + + + public override async System.Threading.Tasks.Task PostprocessAsync(System.Data.Common.DbDataReader reader, System.Collections.Generic.IList exceptions, System.Threading.CancellationToken token) + { + storeVersion(); + await postprocessUpdateAsync(reader, exceptions, token); + } + + + public override Marten.Internal.Operations.OperationRole Role() + { + return Marten.Internal.Operations.OperationRole.Update; + } + + + public override NpgsqlTypes.NpgsqlDbType DbType() + { + return NpgsqlTypes.NpgsqlDbType.Uuid; + } + + + public override void ConfigureParameters(Weasel.Postgresql.IGroupedParameterBuilder parameterBuilder, Weasel.Postgresql.ICommandBuilder builder, ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session) + { + builder.Append("select duplicated_value_type_field1.mt_update_duplicatevaluetypedoc("); + var parameter0 = parameterBuilder.AppendParameter((document is ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc ? ((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).DuplicateValueType.Value : default(System.Guid))); + var parameter1 = parameterBuilder.AppendParameter(session.Serializer.ToJson(_document)); + parameter1.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Jsonb; + // .Net Class Type + var parameter2 = parameterBuilder.AppendParameter(_document.GetType().FullName); + parameter2.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar; + var parameter3 = parameterBuilder.AppendParameter((document is ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc ? ((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).Id : default(System.Guid))); + setVersionParameter(parameterBuilder); + builder.Append(')'); + } + + } + + // END: UpdateDuplicateValueTypeDocOperation1126046928 + + + // START: QueryOnlyDuplicateValueTypeDocSelector1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class QueryOnlyDuplicateValueTypeDocSelector1126046928 : Marten.Internal.CodeGeneration.DocumentSelectorWithOnlySerializer, Marten.Linq.Selectors.ISelector + { + private readonly Marten.Internal.IMartenSession _session; + private readonly Marten.Schema.DocumentMapping _mapping; + + public QueryOnlyDuplicateValueTypeDocSelector1126046928(Marten.Internal.IMartenSession session, Marten.Schema.DocumentMapping mapping) : base(session, mapping) + { + _session = session; + _mapping = mapping; + } + + + + public ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc Resolve(System.Data.Common.DbDataReader reader) + { + + ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document; + document = _serializer.FromJson(reader, 0); + return document; + } + + + public async System.Threading.Tasks.Task ResolveAsync(System.Data.Common.DbDataReader reader, System.Threading.CancellationToken token) + { + + ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document; + document = await _serializer.FromJsonAsync(reader, 0, token).ConfigureAwait(false); + return document; + } + + } + + // END: QueryOnlyDuplicateValueTypeDocSelector1126046928 + + + // START: LightweightDuplicateValueTypeDocSelector1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LightweightDuplicateValueTypeDocSelector1126046928 : Marten.Internal.CodeGeneration.DocumentSelectorWithVersions, Marten.Linq.Selectors.ISelector + { + private readonly Marten.Internal.IMartenSession _session; + private readonly Marten.Schema.DocumentMapping _mapping; + + public LightweightDuplicateValueTypeDocSelector1126046928(Marten.Internal.IMartenSession session, Marten.Schema.DocumentMapping mapping) : base(session, mapping) + { + _session = session; + _mapping = mapping; + } + + + + public ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc Resolve(System.Data.Common.DbDataReader reader) + { + var id = reader.GetFieldValue(0); + + ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document; + document = _serializer.FromJson(reader, 1); + _session.MarkAsDocumentLoaded(id, document); + return document; + } + + + public async System.Threading.Tasks.Task ResolveAsync(System.Data.Common.DbDataReader reader, System.Threading.CancellationToken token) + { + var id = await reader.GetFieldValueAsync(0, token); + + ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document; + document = await _serializer.FromJsonAsync(reader, 1, token).ConfigureAwait(false); + _session.MarkAsDocumentLoaded(id, document); + return document; + } + + } + + // END: LightweightDuplicateValueTypeDocSelector1126046928 + + + // START: IdentityMapDuplicateValueTypeDocSelector1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class IdentityMapDuplicateValueTypeDocSelector1126046928 : Marten.Internal.CodeGeneration.DocumentSelectorWithIdentityMap, Marten.Linq.Selectors.ISelector + { + private readonly Marten.Internal.IMartenSession _session; + private readonly Marten.Schema.DocumentMapping _mapping; + + public IdentityMapDuplicateValueTypeDocSelector1126046928(Marten.Internal.IMartenSession session, Marten.Schema.DocumentMapping mapping) : base(session, mapping) + { + _session = session; + _mapping = mapping; + } + + + + public ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc Resolve(System.Data.Common.DbDataReader reader) + { + var id = reader.GetFieldValue(0); + if (_identityMap.TryGetValue(id, out var existing)) return existing; + + ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document; + document = _serializer.FromJson(reader, 1); + _session.MarkAsDocumentLoaded(id, document); + _identityMap[id] = document; + return document; + } + + + public async System.Threading.Tasks.Task ResolveAsync(System.Data.Common.DbDataReader reader, System.Threading.CancellationToken token) + { + var id = await reader.GetFieldValueAsync(0, token); + if (_identityMap.TryGetValue(id, out var existing)) return existing; + + ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document; + document = await _serializer.FromJsonAsync(reader, 1, token).ConfigureAwait(false); + _session.MarkAsDocumentLoaded(id, document); + _identityMap[id] = document; + return document; + } + + } + + // END: IdentityMapDuplicateValueTypeDocSelector1126046928 + + + // START: DirtyTrackingDuplicateValueTypeDocSelector1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DirtyTrackingDuplicateValueTypeDocSelector1126046928 : Marten.Internal.CodeGeneration.DocumentSelectorWithDirtyChecking, Marten.Linq.Selectors.ISelector + { + private readonly Marten.Internal.IMartenSession _session; + private readonly Marten.Schema.DocumentMapping _mapping; + + public DirtyTrackingDuplicateValueTypeDocSelector1126046928(Marten.Internal.IMartenSession session, Marten.Schema.DocumentMapping mapping) : base(session, mapping) + { + _session = session; + _mapping = mapping; + } + + + + public ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc Resolve(System.Data.Common.DbDataReader reader) + { + var id = reader.GetFieldValue(0); + if (_identityMap.TryGetValue(id, out var existing)) return existing; + + ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document; + document = _serializer.FromJson(reader, 1); + _session.MarkAsDocumentLoaded(id, document); + _identityMap[id] = document; + StoreTracker(_session, document); + return document; + } + + + public async System.Threading.Tasks.Task ResolveAsync(System.Data.Common.DbDataReader reader, System.Threading.CancellationToken token) + { + var id = await reader.GetFieldValueAsync(0, token); + if (_identityMap.TryGetValue(id, out var existing)) return existing; + + ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document; + document = await _serializer.FromJsonAsync(reader, 1, token).ConfigureAwait(false); + _session.MarkAsDocumentLoaded(id, document); + _identityMap[id] = document; + StoreTracker(_session, document); + return document; + } + + } + + // END: DirtyTrackingDuplicateValueTypeDocSelector1126046928 + + + // START: QueryOnlyDuplicateValueTypeDocDocumentStorage1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class QueryOnlyDuplicateValueTypeDocDocumentStorage1126046928 : Marten.Internal.Storage.QueryOnlyDocumentStorage + { + private readonly Marten.Schema.DocumentMapping _document; + + public QueryOnlyDuplicateValueTypeDocDocumentStorage1126046928(Marten.Schema.DocumentMapping document) : base(document) + { + _document = document; + } + + + + public override System.Guid AssignIdentity(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, string tenantId, Marten.Storage.IMartenDatabase database) + { + if (document.Id == Guid.Empty) _setter(document, JasperFx.Core.CombGuidIdGeneration.NewGuid()); + return document.Id; + } + + + public override Marten.Internal.Operations.IStorageOperation Update(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpdateDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Insert(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.InsertDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Upsert(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpsertDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Overwrite(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + throw new System.NotSupportedException(); + } + + + public override System.Guid Identity(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document) + { + return document.Id; + } + + + public override Marten.Linq.Selectors.ISelector BuildSelector(Marten.Internal.IMartenSession session) + { + return new Marten.Generated.DocumentStorage.QueryOnlyDuplicateValueTypeDocSelector1126046928(session, _document); + } + + + public override object RawIdentityValue(System.Guid id) + { + return id; + } + + + public override Npgsql.NpgsqlParameter BuildManyIdParameter(System.Guid[] ids) + { + return base.BuildManyIdParameter(ids); + } + + } + + // END: QueryOnlyDuplicateValueTypeDocDocumentStorage1126046928 + + + // START: LightweightDuplicateValueTypeDocDocumentStorage1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LightweightDuplicateValueTypeDocDocumentStorage1126046928 : Marten.Internal.Storage.LightweightDocumentStorage + { + private readonly Marten.Schema.DocumentMapping _document; + + public LightweightDuplicateValueTypeDocDocumentStorage1126046928(Marten.Schema.DocumentMapping document) : base(document) + { + _document = document; + } + + + + public override System.Guid AssignIdentity(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, string tenantId, Marten.Storage.IMartenDatabase database) + { + if (document.Id == Guid.Empty) _setter(document, JasperFx.Core.CombGuidIdGeneration.NewGuid()); + return document.Id; + } + + + public override Marten.Internal.Operations.IStorageOperation Update(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpdateDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Insert(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.InsertDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Upsert(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpsertDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Overwrite(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + throw new System.NotSupportedException(); + } + + + public override System.Guid Identity(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document) + { + return document.Id; + } + + + public override Marten.Linq.Selectors.ISelector BuildSelector(Marten.Internal.IMartenSession session) + { + return new Marten.Generated.DocumentStorage.LightweightDuplicateValueTypeDocSelector1126046928(session, _document); + } + + + public override object RawIdentityValue(System.Guid id) + { + return id; + } + + + public override Npgsql.NpgsqlParameter BuildManyIdParameter(System.Guid[] ids) + { + return base.BuildManyIdParameter(ids); + } + + } + + // END: LightweightDuplicateValueTypeDocDocumentStorage1126046928 + + + // START: IdentityMapDuplicateValueTypeDocDocumentStorage1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class IdentityMapDuplicateValueTypeDocDocumentStorage1126046928 : Marten.Internal.Storage.IdentityMapDocumentStorage + { + private readonly Marten.Schema.DocumentMapping _document; + + public IdentityMapDuplicateValueTypeDocDocumentStorage1126046928(Marten.Schema.DocumentMapping document) : base(document) + { + _document = document; + } + + + + public override System.Guid AssignIdentity(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, string tenantId, Marten.Storage.IMartenDatabase database) + { + if (document.Id == Guid.Empty) _setter(document, JasperFx.Core.CombGuidIdGeneration.NewGuid()); + return document.Id; + } + + + public override Marten.Internal.Operations.IStorageOperation Update(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpdateDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Insert(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.InsertDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Upsert(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpsertDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Overwrite(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + throw new System.NotSupportedException(); + } + + + public override System.Guid Identity(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document) + { + return document.Id; + } + + + public override Marten.Linq.Selectors.ISelector BuildSelector(Marten.Internal.IMartenSession session) + { + return new Marten.Generated.DocumentStorage.IdentityMapDuplicateValueTypeDocSelector1126046928(session, _document); + } + + + public override object RawIdentityValue(System.Guid id) + { + return id; + } + + + public override Npgsql.NpgsqlParameter BuildManyIdParameter(System.Guid[] ids) + { + return base.BuildManyIdParameter(ids); + } + + } + + // END: IdentityMapDuplicateValueTypeDocDocumentStorage1126046928 + + + // START: DirtyTrackingDuplicateValueTypeDocDocumentStorage1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DirtyTrackingDuplicateValueTypeDocDocumentStorage1126046928 : Marten.Internal.Storage.DirtyCheckedDocumentStorage + { + private readonly Marten.Schema.DocumentMapping _document; + + public DirtyTrackingDuplicateValueTypeDocDocumentStorage1126046928(Marten.Schema.DocumentMapping document) : base(document) + { + _document = document; + } + + + + public override System.Guid AssignIdentity(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, string tenantId, Marten.Storage.IMartenDatabase database) + { + if (document.Id == Guid.Empty) _setter(document, JasperFx.Core.CombGuidIdGeneration.NewGuid()); + return document.Id; + } + + + public override Marten.Internal.Operations.IStorageOperation Update(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpdateDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Insert(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.InsertDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Upsert(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + + return new Marten.Generated.DocumentStorage.UpsertDuplicateValueTypeDocOperation1126046928 + ( + document, Identity(document), + session.Versions.ForType(), + _document + + ); + } + + + public override Marten.Internal.Operations.IStorageOperation Overwrite(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Internal.IMartenSession session, string tenant) + { + throw new System.NotSupportedException(); + } + + + public override System.Guid Identity(ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document) + { + return document.Id; + } + + + public override Marten.Linq.Selectors.ISelector BuildSelector(Marten.Internal.IMartenSession session) + { + return new Marten.Generated.DocumentStorage.DirtyTrackingDuplicateValueTypeDocSelector1126046928(session, _document); + } + + + public override object RawIdentityValue(System.Guid id) + { + return id; + } + + + public override Npgsql.NpgsqlParameter BuildManyIdParameter(System.Guid[] ids) + { + return base.BuildManyIdParameter(ids); + } + + } + + // END: DirtyTrackingDuplicateValueTypeDocDocumentStorage1126046928 + + + // START: DuplicateValueTypeDocBulkLoader1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DuplicateValueTypeDocBulkLoader1126046928 : Marten.Internal.CodeGeneration.BulkLoader + { + private readonly Marten.Internal.Storage.IDocumentStorage _storage; + + public DuplicateValueTypeDocBulkLoader1126046928(Marten.Internal.Storage.IDocumentStorage storage) : base(storage) + { + _storage = storage; + } + + + public const string MAIN_LOADER_SQL = "COPY duplicated_value_type_field1.mt_doc_duplicatevaluetypedoc(\"duplicate_value_type\", \"mt_dotnet_type\", \"id\", \"mt_version\", \"data\") FROM STDIN BINARY"; + + public const string TEMP_LOADER_SQL = "COPY mt_doc_duplicatevaluetypedoc_temp(\"duplicate_value_type\", \"mt_dotnet_type\", \"id\", \"mt_expected_version\", \"mt_version\", \"data\") FROM STDIN BINARY"; + + public const string COPY_NEW_DOCUMENTS_SQL = "insert into duplicated_value_type_field1.mt_doc_duplicatevaluetypedoc (\"id\", \"data\", \"mt_version\", \"mt_dotnet_type\", \"duplicate_value_type\", mt_last_modified) (select mt_doc_duplicatevaluetypedoc_temp.\"id\", mt_doc_duplicatevaluetypedoc_temp.\"data\", mt_doc_duplicatevaluetypedoc_temp.\"mt_version\", mt_doc_duplicatevaluetypedoc_temp.\"mt_dotnet_type\", mt_doc_duplicatevaluetypedoc_temp.\"duplicate_value_type\", transaction_timestamp() from mt_doc_duplicatevaluetypedoc_temp left join duplicated_value_type_field1.mt_doc_duplicatevaluetypedoc on mt_doc_duplicatevaluetypedoc_temp.id = duplicated_value_type_field1.mt_doc_duplicatevaluetypedoc.id where duplicated_value_type_field1.mt_doc_duplicatevaluetypedoc.id is null)"; + + public const string OVERWRITE_SQL = "update duplicated_value_type_field1.mt_doc_duplicatevaluetypedoc target SET data = source.data, mt_version = source.mt_version, mt_dotnet_type = source.mt_dotnet_type, duplicate_value_type = source.duplicate_value_type, mt_last_modified = transaction_timestamp() FROM mt_doc_duplicatevaluetypedoc_temp source WHERE source.id = target.id"; + + public const string OVERWRITE_WITH_VERSION_SQL = "update duplicated_value_type_field1.mt_doc_duplicatevaluetypedoc target SET data = source.data, mt_version = source.mt_version, mt_dotnet_type = source.mt_dotnet_type, duplicate_value_type = source.duplicate_value_type, mt_last_modified = transaction_timestamp() FROM mt_doc_duplicatevaluetypedoc_temp source WHERE source.id = target.id and target.mt_version = source.mt_expected_version"; + + public const string CREATE_TEMP_TABLE_FOR_COPYING_SQL = "create temporary table mt_doc_duplicatevaluetypedoc_temp (like duplicated_value_type_field1.mt_doc_duplicatevaluetypedoc including defaults, \"mt_expected_version\" uuid)"; + + + public override string CreateTempTableForCopying() + { + return CREATE_TEMP_TABLE_FOR_COPYING_SQL; + } + + + public override string CopyNewDocumentsFromTempTable() + { + return COPY_NEW_DOCUMENTS_SQL; + } + + + public override string OverwriteDuplicatesFromTempTable() + { + return OVERWRITE_SQL; + } + + + public override string OverwriteDuplicatesFromTempTableWithVersionCheck() + { + return OVERWRITE_WITH_VERSION_SQL; + } + + + public override async System.Threading.Tasks.Task LoadRowAsync(Npgsql.NpgsqlBinaryImporter writer, ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Storage.Tenant tenant, Marten.ISerializer serializer, System.Threading.CancellationToken cancellation) + { + await writer.WriteAsync(((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).DuplicateValueType.Value, NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(document.GetType().FullName, NpgsqlTypes.NpgsqlDbType.Varchar, cancellation); + await writer.WriteAsync(((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).Id, NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(JasperFx.Core.CombGuidIdGeneration.NewGuid(), NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(serializer.ToJson(document), NpgsqlTypes.NpgsqlDbType.Jsonb, cancellation); + } + + + public override async System.Threading.Tasks.Task LoadTempRowAsync(Npgsql.NpgsqlBinaryImporter writer, ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc document, Marten.Storage.Tenant tenant, Marten.ISerializer serializer, System.Threading.CancellationToken cancellation) + { + await writer.WriteAsync(((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).DuplicateValueType.Value, NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(document.GetType().FullName, NpgsqlTypes.NpgsqlDbType.Varchar, cancellation); + await writer.WriteAsync(((ValueTypeTests.StrongTypedId.DuplicateValueTypeDoc)document).Id, NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + writer.Write(System.DBNull.Value, 0); + await writer.WriteAsync(JasperFx.Core.CombGuidIdGeneration.NewGuid(), NpgsqlTypes.NpgsqlDbType.Uuid, cancellation); + await writer.WriteAsync(serializer.ToJson(document), NpgsqlTypes.NpgsqlDbType.Jsonb, cancellation); + } + + + public override string MainLoaderSql() + { + return MAIN_LOADER_SQL; + } + + + public override string TempLoaderSql() + { + return TEMP_LOADER_SQL; + } + + } + + // END: DuplicateValueTypeDocBulkLoader1126046928 + + + // START: DuplicateValueTypeDocProvider1126046928 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DuplicateValueTypeDocProvider1126046928 : Marten.Internal.Storage.DocumentProvider + { + private readonly Marten.Schema.DocumentMapping _mapping; + + public DuplicateValueTypeDocProvider1126046928(Marten.Schema.DocumentMapping mapping) : base(new DuplicateValueTypeDocBulkLoader1126046928(new QueryOnlyDuplicateValueTypeDocDocumentStorage1126046928(mapping)), new QueryOnlyDuplicateValueTypeDocDocumentStorage1126046928(mapping), new LightweightDuplicateValueTypeDocDocumentStorage1126046928(mapping), new IdentityMapDuplicateValueTypeDocDocumentStorage1126046928(mapping), new DirtyTrackingDuplicateValueTypeDocDocumentStorage1126046928(mapping)) + { + _mapping = mapping; + } + + + } + + // END: DuplicateValueTypeDocProvider1126046928 + + +} + diff --git a/src/ValueTypeTests/StrongTypedId/duplicated_value_type_field_operations.cs b/src/ValueTypeTests/StrongTypedId/duplicated_value_type_field_operations.cs new file mode 100644 index 0000000000..af9edd583c --- /dev/null +++ b/src/ValueTypeTests/StrongTypedId/duplicated_value_type_field_operations.cs @@ -0,0 +1,137 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using JasperFx.CodeGeneration; +using JasperFx.Core; +using Marten; +using Marten.Testing.Harness; +using Shouldly; +using StronglyTypedIds; + +namespace ValueTypeTests.StrongTypedId; + +public class duplicated_value_type_field_operations : IDisposable, IAsyncDisposable +{ + private readonly DocumentStore theStore; + private IDocumentSession theSession; + + public duplicated_value_type_field_operations() + { + theStore = DocumentStore.For(opts => + { + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = "duplicated_value_type_field1"; + + opts.ApplicationAssembly = GetType().Assembly; + opts.GeneratedCodeMode = TypeLoadMode.Auto; + opts.GeneratedCodeOutputPath = + AppContext.BaseDirectory.ParentDirectory().ParentDirectory().ParentDirectory().AppendPath("Internal", "Generated"); + + opts.RegisterValueType(); + opts.Schema.For().Duplicate(x => x.DuplicateValueType); + }); + + theSession = theStore.LightweightSession(); + } + + public void Dispose() + { + theStore?.Dispose(); + theSession?.Dispose(); + } + + public async ValueTask DisposeAsync() + { + if (theStore != null) + { + await theStore.DisposeAsync(); + } + } + + [Fact] + public async Task store_a_document_smoke_test() + { + var duplicatedDoc = new DuplicateValueTypeDoc(){DuplicateValueType = DuplicateValueType.New()}; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + (await theSession.Query().AnyAsync()).ShouldBeTrue(); + } + + [Fact] + public async Task load_document() + { + var duplicatedDoc = new DuplicateValueTypeDoc + { + Id = Guid.NewGuid(), + DuplicateValueType = DuplicateValueType.New() + }; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + (await theSession.LoadAsync(duplicatedDoc.Id)) + .DuplicateValueType.ShouldBe(duplicatedDoc.DuplicateValueType); + } + + [Fact] + public async Task load_many() + { + var duplicatedDoc1 = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.New()}; + var duplicatedDoc2 = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.New()}; + var duplicatedDoc3 = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.New()}; + theSession.Store(duplicatedDoc1, duplicatedDoc2, duplicatedDoc3); + + await theSession.SaveChangesAsync(); + + var results = await theSession.Query().Where(x => x.Id.IsOneOf(duplicatedDoc1.Id, duplicatedDoc2.Id, duplicatedDoc3.Id)).ToListAsync(); + results.Count.ShouldBe(3); + } + + [Fact] + public async Task use_in_LINQ_where_clause() + { + var duplicatedDoc = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.New()}; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + var loaded = await theSession.Query() + .FirstOrDefaultAsync(x => x.DuplicateValueType == duplicatedDoc.DuplicateValueType); + + loaded.ShouldNotBeNull(); + } + + [Fact] + public async Task use_in_LINQ_duplicatedDoc_clause() + { + var duplicatedDoc = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.New()}; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + var loaded = await theSession.Query().OrderBy(x => x.Id).Take(3).ToListAsync(); + } + + [Fact] + public async Task use_in_LINQ_select_clause() + { + var duplicatedDoc = new DuplicateValueTypeDoc{DuplicateValueType = DuplicateValueType.New()}; + theSession.Store(duplicatedDoc); + + await theSession.SaveChangesAsync(); + + var loaded = await theSession.Query().Select(x => x.Id).Take(3).ToListAsync(); + + } +} + +[StronglyTypedId(Template.Guid)] +public readonly partial struct DuplicateValueType; + +public class DuplicateValueTypeDoc +{ + public Guid Id { get; set; } + public DuplicateValueType DuplicateValueType { get; set; } +} diff --git a/src/ValueTypeTests/ValueTypeTests.csproj b/src/ValueTypeTests/ValueTypeTests.csproj index f7ea3a07b6..fcc9316abb 100644 --- a/src/ValueTypeTests/ValueTypeTests.csproj +++ b/src/ValueTypeTests/ValueTypeTests.csproj @@ -42,6 +42,7 @@ + diff --git a/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs b/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs index a5b98f173c..41ebf3e127 100644 --- a/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs +++ b/src/ValueTypeTests/VogenIds/duplicated_value_type_field_operations.cs @@ -20,7 +20,7 @@ public duplicated_value_type_field_operations() theStore = DocumentStore.For(opts => { opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "duplicated_value_type_field"; + opts.DatabaseSchemaName = "duplicated_value_type_field2"; opts.ApplicationAssembly = GetType().Assembly; opts.GeneratedCodeMode = TypeLoadMode.Auto;