public DocumentTable(DocumentMapping mapping) : base(mapping.Table) { var pgIdType = TypeMappings.GetPgType(mapping.IdMember.GetMemberType()); AddPrimaryKey(new TableColumn("id", pgIdType)); AddColumn("data", "jsonb", "NOT NULL"); AddColumn <LastModifiedColumn>(); AddColumn <VersionColumn>(); AddColumn <DotNetTypeColumn>(); foreach (var field in mapping.DuplicatedFields) { AddColumn(new DuplicatedFieldColumn(field)); } if (mapping.IsHierarchy()) { AddColumn(new DocumentTypeColumn(mapping)); } if (mapping.DeleteStyle == DeleteStyle.SoftDelete) { AddColumn <DeletedColumn>(); AddColumn <DeletedAtColumn>(); } Indexes.AddRange(mapping.Indexes); ForeignKeys.AddRange(mapping.ForeignKeys); }
public UpsertFunction(DocumentMapping mapping, DbObjectName identifier = null, bool disableConcurrency = false) : base(identifier ?? mapping.UpsertFunction) { _disableConcurrency = disableConcurrency; if (mapping == null) { throw new ArgumentNullException(nameof(mapping)); } _tableName = mapping.Table; var table = new DocumentTable(mapping); if (table.PrimaryKeys.Count > 1) { _primaryKeyConstraintName = mapping.Table.Name + "_pkey"; } else { _primaryKeyConstraintName = "pk_" + mapping.Table.Name; } var idType = mapping.IdMember.GetMemberType(); var pgIdType = TypeMappings.GetPgType(idType); Arguments.Add(new UpsertArgument { Arg = "docId", PostgresType = pgIdType, Column = "id", Members = new[] { mapping.IdMember } }); Arguments.Add(new DocJsonBodyArgument()); Arguments.AddRange(mapping.DuplicatedFields.Select(x => x.UpsertArgument)); Arguments.Add(new VersionArgument()); Arguments.Add(new DotNetTypeArgument()); if (mapping.IsHierarchy()) { Arguments.Add(new DocTypeArgument()); } if (mapping.UseOptimisticConcurrency) { Arguments.Add(new CurrentVersionArgument()); } if (mapping.TenancyStyle == TenancyStyle.Conjoined) { Arguments.Add(new TenantIdArgument()); _tenantWhereClause = $"{_tableName.QualifiedName}.{TenantIdColumn.Name} = {TenantIdArgument.ArgName}"; _andTenantWhereClause = $" and {_tenantWhereClause}"; } }
// TODO -- just inject the type alias and simplify the operation classes private void buildOperationMethod(GeneratedType type, DocumentOperations operations, string methodName) { var operationType = (GeneratedType)typeof(DocumentOperations).GetProperty(methodName).GetValue(operations); var method = type.MethodFor(methodName); if (_mapping.IsHierarchy()) { method.Frames .Code($@" return new Marten.Generated.{operationType.TypeName} ( {{0}}, Identity({{0}}), {{1}}.Versions.ForType<{_mapping.DocumentType.FullNameInCode()}, {_mapping.IdType.FullNameInCode()}>(), {{2}} );" , new Use(_mapping.DocumentType), Use.Type <IMartenSession>(), Use.Type <DocumentMapping>()); } else { method.Frames .Code($@" return new Marten.Generated.{operationType.TypeName} ( {{0}}, Identity({{0}}), {{1}}.Versions.ForType<{_mapping.DocumentType.FullNameInCode()}, {_mapping.IdType.FullNameInCode()}>() );" , new Use(_mapping.DocumentType), Use.Type <IMartenSession>()); } }
public static DocumentProvider <T> FromPreBuiltTypes <T>(Assembly assembly, DocumentMapping mapping) { var queryOnly = assembly.ExportedTypes.FirstOrDefault(x => x.Name == DocumentStorageBuilder.DeriveTypeName(mapping, StorageStyle.QueryOnly)); var lightweight = assembly.ExportedTypes.FirstOrDefault(x => x.Name == DocumentStorageBuilder.DeriveTypeName(mapping, StorageStyle.Lightweight)); var identityMap = assembly.ExportedTypes.FirstOrDefault(x => x.Name == DocumentStorageBuilder.DeriveTypeName(mapping, StorageStyle.IdentityMap)); var dirtyTracking = assembly.ExportedTypes.FirstOrDefault(x => x.Name == DocumentStorageBuilder.DeriveTypeName(mapping, StorageStyle.DirtyTracking)); var bulkWriterType = assembly.ExportedTypes.FirstOrDefault(x => x.Name == new BulkLoaderBuilder(mapping).TypeName); var slot = new DocumentProvider <T> { QueryOnly = (IDocumentStorage <T>)Activator.CreateInstance(queryOnly, mapping), Lightweight = (IDocumentStorage <T>)Activator.CreateInstance(lightweight, mapping), IdentityMap = (IDocumentStorage <T>)Activator.CreateInstance(identityMap, mapping), DirtyTracking = (IDocumentStorage <T>)Activator.CreateInstance(dirtyTracking, mapping), }; slot.BulkLoader = mapping.IsHierarchy() ? (IBulkLoader <T>)Activator.CreateInstance(bulkWriterType, slot.QueryOnly, mapping) : (IBulkLoader <T>)Activator.CreateInstance(bulkWriterType, slot.QueryOnly); return(slot); }
public static void DeserializeAsync(this FramesCollection frames, DocumentMapping mapping, int index) { var documentType = mapping.DocumentType; var document = new Variable(documentType, DocumentVariableName); if (!mapping.IsHierarchy()) { frames.Code($@" {documentType.FullNameInCode()} document; BLOCK:using (var json = reader.GetTextReader({index})) document = _serializer.FromJson<{documentType.FullNameInCode()}>(json); END ").Creates(document); } else { frames.CodeAsync($@" {documentType.FullNameInCode()} document; var typeAlias = await reader.GetFieldValueAsync<string>({index + 1}, {{0}}).ConfigureAwait(false); BLOCK:using (var json = reader.GetTextReader({index})) document = ({documentType.FullNameInCode()}) _serializer.FromJson(_mapping.TypeFor(typeAlias), json); END ", Use.Type <CancellationToken>()).Creates(document); } }
public DocumentTable(DocumentMapping mapping) : base(mapping.TableName) { // validate to ensure document has an Identity field or property mapping.CompileAndValidate(); _mapping = mapping; foreach (var index in mapping.IgnoredIndexes) { IgnoredIndexes.Add(index); } var idColumn = new IdColumn(mapping); AddColumn(idColumn).AsPrimaryKey(); if (mapping.TenancyStyle == TenancyStyle.Conjoined) { AddColumn(mapping.Metadata.TenantId).AsPrimaryKey(); Indexes.Add(new DocumentIndex(mapping, TenantIdColumn.Name)); } AddColumn <DataColumn>(); AddIfActive(_mapping.Metadata.LastModified); AddIfActive(_mapping.Metadata.Version); AddIfActive(_mapping.Metadata.DotNetType); AddIfActive(_mapping.Metadata.CorrelationId); AddIfActive(_mapping.Metadata.CausationId); AddIfActive(_mapping.Metadata.LastModifiedBy); AddIfActive(_mapping.Metadata.Headers); foreach (var field in mapping.DuplicatedFields.Where(x => !x.OnlyForSearching)) { AddColumn(new DuplicatedFieldColumn(field)); } if (mapping.IsHierarchy()) { Indexes.Add(new DocumentIndex(_mapping, SchemaConstants.DocumentTypeColumn)); AddColumn(_mapping.Metadata.DocumentType); } if (mapping.DeleteStyle == DeleteStyle.SoftDelete) { AddColumn(_mapping.Metadata.IsSoftDeleted); Indexes.Add(new DocumentIndex(mapping, SchemaConstants.DeletedColumn)); AddColumn(_mapping.Metadata.SoftDeletedAt); } Indexes.AddRange(mapping.Indexes); ForeignKeys.AddRange(mapping.ForeignKeys); }
public DocumentTable(DocumentMapping mapping) : base(mapping.TableName) { // validate to ensure document has an Identity field or property mapping.Validate(); _mapping = mapping; var idColumn = new IdColumn(mapping); if (mapping.TenancyStyle == TenancyStyle.Conjoined) { AddPrimaryKeys(new List <TableColumn> { idColumn, mapping.Metadata.TenantId }); Indexes.Add(new IndexDefinition(mapping, TenantIdColumn.Name)); } else { AddPrimaryKey(idColumn); } AddColumn <DataColumn>(); AddIfActive(_mapping.Metadata.LastModified); AddIfActive(_mapping.Metadata.Version); AddIfActive(_mapping.Metadata.DotNetType); AddIfActive(_mapping.Metadata.CorrelationId); AddIfActive(_mapping.Metadata.CausationId); AddIfActive(_mapping.Metadata.LastModifiedBy); AddIfActive(_mapping.Metadata.Headers); foreach (var field in mapping.DuplicatedFields) { AddColumn(new DuplicatedFieldColumn(field)); } if (mapping.IsHierarchy()) { Indexes.Add(new IndexDefinition(_mapping, SchemaConstants.DocumentTypeColumn)); AddColumn(_mapping.Metadata.DocumentType); } if (mapping.DeleteStyle == DeleteStyle.SoftDelete) { AddColumn(_mapping.Metadata.IsSoftDeleted); Indexes.Add(new IndexDefinition(mapping, SchemaConstants.DeletedColumn)); AddColumn(_mapping.Metadata.SoftDeletedAt); } Indexes.AddRange(mapping.Indexes); ForeignKeys.AddRange(mapping.ForeignKeys); }
public DocumentProvider <T> Generate <T>() { var assembly = new GeneratedAssembly(new GenerationRules("Marten.Generated")); var operations = new DocumentOperations(assembly, _mapping, _options); assembly.Namespaces.Add(typeof(CommandExtensions).Namespace); assembly.Namespaces.Add(typeof(TenantIdArgument).Namespace); assembly.Namespaces.Add(typeof(NpgsqlCommand).Namespace); var queryOnly = new DocumentStorageBuilder(_mapping, StorageStyle.QueryOnly, x => x.QueryOnlySelector) .Build(assembly, operations); var lightweight = new DocumentStorageBuilder(_mapping, StorageStyle.Lightweight, x => x.LightweightSelector) .Build(assembly, operations); var identityMap = new DocumentStorageBuilder(_mapping, StorageStyle.IdentityMap, x => x.IdentityMapSelector) .Build(assembly, operations); var dirtyTracking = new DocumentStorageBuilder(_mapping, StorageStyle.DirtyTracking, x => x.DirtyCheckingSelector) .Build(assembly, operations); var bulkWriterType = new BulkLoaderBuilder(_mapping).BuildType(assembly); var compiler = new AssemblyGenerator(); compiler.ReferenceAssembly(typeof(IDocumentStorage <>).Assembly); compiler.ReferenceAssembly(typeof(T).Assembly); compiler.Compile(assembly); var slot = new DocumentProvider <T> { QueryOnly = (IDocumentStorage <T>)Activator.CreateInstance(queryOnly.CompiledType, _mapping), Lightweight = (IDocumentStorage <T>)Activator.CreateInstance(lightweight.CompiledType, _mapping), IdentityMap = (IDocumentStorage <T>)Activator.CreateInstance(identityMap.CompiledType, _mapping), DirtyTracking = (IDocumentStorage <T>)Activator.CreateInstance(dirtyTracking.CompiledType, _mapping), Operations = operations, QueryOnlyType = queryOnly, LightweightType = lightweight, IdentityMapType = identityMap, DirtyTrackingType = dirtyTracking }; slot.BulkLoader = _mapping.IsHierarchy() ? (IBulkLoader <T>)Activator.CreateInstance(bulkWriterType.CompiledType, slot.QueryOnly, _mapping) : (IBulkLoader <T>)Activator.CreateInstance(bulkWriterType.CompiledType, slot.QueryOnly); slot.BulkLoaderType = bulkWriterType; return(slot); }
public DocumentTable(DocumentMapping mapping) : base(mapping.Table) { // validate to ensure document has an Identity field or property mapping.Validate(); var pgIdType = TypeMappings.GetPgType(mapping.IdMember.GetMemberType()); var pgTextType = TypeMappings.GetPgType(string.Empty.GetType()); var idColumn = new TableColumn("id", pgIdType); if (mapping.TenancyStyle == TenancyStyle.Conjoined) { AddPrimaryKeys(new List <TableColumn> { idColumn, new TenantIdColumn() }); Indexes.Add(new IndexDefinition(mapping, TenantIdColumn.Name)); } else { AddPrimaryKey(idColumn); } AddColumn("data", "jsonb", "NOT NULL"); AddColumn <LastModifiedColumn>(); AddColumn <VersionColumn>(); AddColumn <DotNetTypeColumn>(); foreach (var field in mapping.DuplicatedFields) { AddColumn(new DuplicatedFieldColumn(field)); } if (mapping.IsHierarchy()) { AddColumn(new DocumentTypeColumn(mapping)); } if (mapping.DeleteStyle == DeleteStyle.SoftDelete) { AddColumn <DeletedColumn>(); Indexes.Add(new IndexDefinition(mapping, DocumentMapping.DeletedColumn)); AddColumn <DeletedAtColumn>(); } Indexes.AddRange(mapping.Indexes); ForeignKeys.AddRange(mapping.ForeignKeys); }
public GeneratedType BuildType(GeneratedAssembly assembly) { var upsertFunction = _mapping.Schema.Upsert; var arguments = orderArgumentsForBulkWriting(upsertFunction); var columns = arguments.Select(x => $"\\\"{x.Column}\\\"").Join(", "); var type = assembly.AddType(TypeName, typeof(BulkLoader <,>).MakeGenericType(_mapping.DocumentType, _mapping.IdType)); if (_mapping.IsHierarchy()) { type.AllInjectedFields.Add(new InjectedField(typeof(DocumentMapping), "mapping")); } type.MethodFor("MainLoaderSql") .Frames .ReturnNewStringConstant("MAIN_LOADER_SQL", $"COPY {_mapping.TableName.QualifiedName}({columns}) FROM STDIN BINARY"); type.MethodFor("TempLoaderSql").Frames .ReturnNewStringConstant("TEMP_LOADER_SQL", $"COPY {_tempTable}({columns}) FROM STDIN BINARY"); type.MethodFor(nameof(CopyNewDocumentsFromTempTable)) .Frames.ReturnNewStringConstant("COPY_NEW_DOCUMENTS_SQL", CopyNewDocumentsFromTempTable()); type.MethodFor(nameof(OverwriteDuplicatesFromTempTable)) .Frames.ReturnNewStringConstant("OVERWRITE_SQL", OverwriteDuplicatesFromTempTable()); type.MethodFor(nameof(CreateTempTableForCopying)) .Frames.ReturnNewStringConstant("CREATE_TEMP_TABLE_FOR_COPYING_SQL", CreateTempTableForCopying().Replace("\"", "\\\"")); var load = type.MethodFor("LoadRow"); foreach (var argument in arguments) { argument.GenerateBulkWriterCode(type, load, _mapping); } var loadAsync = type.MethodFor("LoadRowAsync"); foreach (var argument in arguments) { argument.GenerateBulkWriterCodeAsync(type, loadAsync, _mapping); } return(type); }
public UpsertFunction(DocumentMapping mapping) : base(mapping.UpsertFunction) { if (mapping == null) { throw new ArgumentNullException(nameof(mapping)); } _tableName = mapping.Table; _primaryKeyConstraintName = "pk_" + mapping.Table.Name; var idType = mapping.IdMember.GetMemberType(); var pgIdType = TypeMappings.GetPgType(idType); Arguments.Add(new UpsertArgument { Arg = "docId", PostgresType = pgIdType, Column = "id", Members = new[] { mapping.IdMember } }); Arguments.Add(new DocJsonBodyArgument()); Arguments.AddRange(mapping.DuplicatedFields.Select(x => x.UpsertArgument)); Arguments.Add(new VersionArgument()); Arguments.Add(new DotNetTypeArgument()); if (mapping.IsHierarchy()) { Arguments.Add(new DocTypeArgument()); } if (mapping.UseOptimisticConcurrency) { Arguments.Add(new CurrentVersionArgument()); } if (mapping.TenancyStyle == TenancyStyle.Conjoined) { Arguments.Add(new TenantIdArgument()); } }
public GeneratedType BuildType(GeneratedAssembly assembly) { var baseType = typeof(StorageOperation <,>).MakeGenericType(_mapping.DocumentType, _mapping.IdType); var type = assembly.AddType(ClassName, baseType); if (_mapping.IsHierarchy()) { type.AllInjectedFields.Add(new InjectedField(typeof(DocumentMapping), "mapping")); } type.MethodFor("Role").Frames.Return(Constant.ForEnum(_role)); type.MethodFor("DbType").Frames.Return(Constant.ForEnum(TypeMappings.ToDbType(_mapping.IdType))); type.MethodFor("CommandText").Frames.Return(Constant.ForString(CommandText)); buildConfigureMethod(type); buildPostprocessingMethods(type); return(type); }
public GeneratedType BuildType(GeneratedAssembly assembly) { var upsertFunction = _mapping.Schema.Upsert; var arguments = orderArgumentsForBulkWriting(upsertFunction); var columns = arguments.Select(x => $"\\\"{x.Column}\\\"").Join(", "); var type = assembly.AddType($"{_mapping.DocumentType.Name.Sanitize()}BulkLoader", typeof(BulkLoader <,>).MakeGenericType(_mapping.DocumentType, _mapping.IdType)); if (_mapping.IsHierarchy()) { type.AllInjectedFields.Add(new InjectedField(typeof(DocumentMapping), "mapping")); } type.MethodFor("MainLoaderSql").Frames .Return($"COPY {_mapping.TableName.QualifiedName}({columns}) FROM STDIN BINARY"); type.MethodFor("TempLoaderSql").Frames .Return($"COPY {_tempTable}({columns}) FROM STDIN BINARY"); type.MethodFor(nameof(CopyNewDocumentsFromTempTable)) .Frames.Return(CopyNewDocumentsFromTempTable()); type.MethodFor(nameof(OverwriteDuplicatesFromTempTable)) .Frames.Return(OverwriteDuplicatesFromTempTable()); type.MethodFor(nameof(CreateTempTableForCopying)) .Frames.Return(CreateTempTableForCopying().Replace("\"", "\\\"")); var load = type.MethodFor("LoadRow"); foreach (var argument in arguments) { argument.GenerateBulkWriterCode(type, load, _mapping); } return(type); }
public static void DeserializeDocumentAsync(this FramesCollection frames, DocumentMapping mapping, int index) { var documentType = mapping.DocumentType; var document = new Variable(documentType, DocumentVariableName); if (!mapping.IsHierarchy()) { frames.Code($@" {documentType.FullNameInCode()} document; document = _serializer.FromJson<{documentType.FullNameInCode()}>(reader, {index}); ").Creates(document); } else { frames.CodeAsync($@" {documentType.FullNameInCode()} document; var typeAlias = await reader.GetFieldValueAsync<string>({index + 1}, {{0}}); document = ({documentType.FullNameInCode()}) (await _serializer.FromJsonAsync(_mapping.TypeFor(typeAlias), reader, {index}, {{0}})); ", Use.Type <CancellationToken>()).Creates(document); } }
public GeneratedType BuildType(GeneratedAssembly assembly) { var upsertFunction = new UpsertFunction(_mapping); var arguments = upsertFunction.OrderedArguments().Where(x => !(x is CurrentVersionArgument)).ToArray(); var columns = arguments.Select(x => $"\\\"{x.Column}\\\"").Join(", "); var type = assembly.AddType($"{_mapping.DocumentType.Name.Sanitize()}BulkLoader", typeof(BulkLoader <,>).MakeGenericType(_mapping.DocumentType, _mapping.IdType)); if (_mapping.IsHierarchy()) { type.AllInjectedFields.Add(new InjectedField(typeof(DocumentMapping), "mapping")); } type.MethodFor("MainLoaderSql").Frames .Return($"COPY {_mapping.Table.QualifiedName}({columns}) FROM STDIN BINARY"); type.MethodFor("TempLoaderSql").Frames .Return($"COPY {_tempTable}({columns}) FROM STDIN BINARY"); type.MethodFor(nameof(CopyNewDocumentsFromTempTable)) .Frames.Return(CopyNewDocumentsFromTempTable()); type.MethodFor(nameof(OverwriteDuplicatesFromTempTable)) .Frames.Return(OverwriteDuplicatesFromTempTable()); type.MethodFor(nameof(CreateTempTableForCopying)) .Frames.Return(CreateTempTableForCopying().Replace("\"", "\\\"")); var load = type.MethodFor("LoadRow"); for (int i = 0; i < arguments.Length; i++) { arguments[i].GenerateBulkWriterCode(type, load, _mapping); } return(type); }
private void writeReturnOfOperation(GeneratedMethod method, GeneratedType operationType) { var assembly = method.ParentType.ParentAssembly; var tenantDeclaration = ""; if (_mapping.TenancyStyle == TenancyStyle.Conjoined) { tenantDeclaration = ", tenant"; } if (_mapping.IsHierarchy()) { method.Frames .Code($@" return new {assembly.Namespace}.{operationType.TypeName} ( {{0}}, Identity({{0}}), {{1}}.Versions.ForType<{_mapping.DocumentType.FullNameInCode()}, {_mapping.IdType.FullNameInCode()}>(), {{2}} {tenantDeclaration} );" , new Use(_mapping.DocumentType), Use.Type <IMartenSession>(), Use.Type <DocumentMapping>()); } else { method.Frames .Code($@" return new {assembly.Namespace}.{operationType.TypeName} ( {{0}}, Identity({{0}}), {{1}}.Versions.ForType<{_mapping.DocumentType.FullNameInCode()}, {_mapping.IdType.FullNameInCode()}>(), {{2}} {tenantDeclaration} );" , new Use(_mapping.DocumentType), Use.Type <IMartenSession>(), Use.Type <DocumentMapping>()); } }
public GeneratedType BuildType(GeneratedAssembly assembly) { var typeName = $"{_style}{_mapping.DocumentType.Name.Sanitize()}Selector"; var baseType = determineBaseType(); var type = assembly.AddType(typeName, baseType); var interfaceType = typeof(ISelector <>).MakeGenericType(_mapping.DocumentType); type.Implements(interfaceType); var sync = type.MethodFor("Resolve"); var async = type.MethodFor("ResolveAsync"); var versionPosition = _mapping.IsHierarchy() ? 3 : 2; switch (_style) { case StorageStyle.QueryOnly: sync.Frames.Deserialize(_mapping); async.Frames.DeserializeAsync(_mapping); break; case StorageStyle.IdentityMap: sync.Frames.GetId(_mapping); async.Frames.GetIdAsync(_mapping); sync.Frames.CheckExistingFirst(); async.Frames.CheckExistingFirst(); sync.Frames.Deserialize(_mapping); async.Frames.DeserializeAsync(_mapping); sync.Frames.MarkAsLoaded(); async.Frames.MarkAsLoaded(); sync.Frames.StoreVersion(false, _mapping, versionPosition); async.Frames.StoreVersion(true, _mapping, versionPosition); sync.Frames.StoreInIdentityMap(_mapping); async.Frames.StoreInIdentityMap(_mapping); break; case StorageStyle.DirtyTracking: sync.Frames.GetId(_mapping); async.Frames.GetIdAsync(_mapping); sync.Frames.CheckExistingFirst(); async.Frames.CheckExistingFirst(); sync.Frames.Deserialize(_mapping); async.Frames.DeserializeAsync(_mapping); sync.Frames.MarkAsLoaded(); async.Frames.MarkAsLoaded(); sync.Frames.StoreVersion(false, _mapping, versionPosition); async.Frames.StoreVersion(true, _mapping, versionPosition); sync.Frames.StoreInIdentityMap(_mapping); async.Frames.StoreInIdentityMap(_mapping); sync.Frames.StoreTracker(); async.Frames.StoreTracker(); break; case StorageStyle.Lightweight: sync.Frames.GetId(_mapping); async.Frames.GetIdAsync(_mapping); sync.Frames.Deserialize(_mapping); async.Frames.DeserializeAsync(_mapping); sync.Frames.MarkAsLoaded(); async.Frames.MarkAsLoaded(); sync.Frames.StoreVersion(false, _mapping, versionPosition); async.Frames.StoreVersion(true, _mapping, versionPosition); break; default: throw new InvalidOperationException(); } sync.Frames.Return(_mapping.DocumentType); if (_style == StorageStyle.QueryOnly && !_mapping.IsHierarchy()) { async.Frames.Code("return Task.FromResult(document);"); } else { async.Frames.Return(_mapping.DocumentType); } return(type); }
public UpsertFunction(DocumentMapping mapping, DbObjectName identifier = null, bool disableConcurrency = false) : base(identifier ?? mapping.UpsertFunction) { _mapping = mapping; _disableConcurrency = disableConcurrency; if (mapping == null) { throw new ArgumentNullException(nameof(mapping)); } _tableName = mapping.TableName; var table = new DocumentTable(mapping); _primaryKeyConstraintName = table.PrimaryKeyName; var idType = mapping.IdMember.GetMemberType(); var pgIdType = PostgresqlProvider.Instance.GetDatabaseType(idType, mapping.EnumStorage); Arguments.Add(new UpsertArgument { Arg = "docId", PostgresType = pgIdType, Column = "id", Members = new[] { mapping.IdMember } }); Arguments.Add(new DocJsonBodyArgument()); Arguments.AddRange(mapping.DuplicatedFields.Where(x => !x.OnlyForSearching).Select(x => x.UpsertArgument)); // These two arguments need to be added this way if (mapping.Metadata.Version.Enabled) { Arguments.Add(new VersionArgument()); } if (mapping.Metadata.DotNetType.Enabled) { Arguments.Add(new DotNetTypeArgument()); } AddIfActive(mapping.Metadata.CorrelationId); AddIfActive(mapping.Metadata.CausationId); AddIfActive(mapping.Metadata.LastModifiedBy); AddIfActive(mapping.Metadata.Headers); if (mapping.IsHierarchy()) { Arguments.Add(new DocTypeArgument()); } if (mapping.UseOptimisticConcurrency) { Arguments.Add(new CurrentVersionArgument()); } if (mapping.TenancyStyle == TenancyStyle.Conjoined) { Arguments.Add(new TenantIdArgument()); _tenantWhereClause = $"{_tableName.QualifiedName}.{TenantIdColumn.Name} = {TenantIdArgument.ArgName}"; _andTenantWhereClause = $" and {_tenantWhereClause}"; } }
public DocumentProvider <T> Generate <T>() { var assembly = new GeneratedAssembly(new GenerationRules("Marten.Generated")); var operations = new DocumentOperations(assembly, _mapping, _options); assembly.Namespaces.Add(typeof(CommandExtensions).Namespace); assembly.Namespaces.Add(typeof(TenantIdArgument).Namespace); assembly.Namespaces.Add(typeof(NpgsqlCommand).Namespace); var queryOnly = new DocumentStorageBuilder(_mapping, StorageStyle.QueryOnly, x => x.QueryOnlySelector) .Build(assembly, operations); var lightweight = new DocumentStorageBuilder(_mapping, StorageStyle.Lightweight, x => x.LightweightSelector) .Build(assembly, operations); var identityMap = new DocumentStorageBuilder(_mapping, StorageStyle.IdentityMap, x => x.IdentityMapSelector) .Build(assembly, operations); var dirtyTracking = new DocumentStorageBuilder(_mapping, StorageStyle.DirtyTracking, x => x.DirtyCheckingSelector) .Build(assembly, operations); var bulkWriterType = new BulkLoaderBuilder(_mapping).BuildType(assembly); var compiler = new AssemblyGenerator(); compiler.ReferenceAssembly(typeof(IDocumentStorage <>).Assembly); compiler.ReferenceAssembly(typeof(T).Assembly); try { compiler.Compile(assembly); } catch (Exception e) { if (e.Message.Contains("is inaccessible due to its protection level")) { throw new InvalidOperationException($"Requested document type '{_mapping.DocumentType.FullNameInCode()}' must be either scoped as 'public' or the assembly holding it must use the {nameof(InternalsVisibleToAttribute)} pointing to 'Marten.Generated'", e); } throw; } var slot = new DocumentProvider <T> { QueryOnly = (IDocumentStorage <T>)Activator.CreateInstance(queryOnly.CompiledType, _mapping), Lightweight = (IDocumentStorage <T>)Activator.CreateInstance(lightweight.CompiledType, _mapping), IdentityMap = (IDocumentStorage <T>)Activator.CreateInstance(identityMap.CompiledType, _mapping), DirtyTracking = (IDocumentStorage <T>)Activator.CreateInstance(dirtyTracking.CompiledType, _mapping), Operations = operations, QueryOnlyType = queryOnly, LightweightType = lightweight, IdentityMapType = identityMap, DirtyTrackingType = dirtyTracking }; slot.BulkLoader = _mapping.IsHierarchy() ? (IBulkLoader <T>)Activator.CreateInstance(bulkWriterType.CompiledType, slot.QueryOnly, _mapping) : (IBulkLoader <T>)Activator.CreateInstance(bulkWriterType.CompiledType, slot.QueryOnly); slot.BulkLoaderType = bulkWriterType; return(slot); }
public GeneratedType BuildType(GeneratedAssembly assembly) { var typeName = $"{_style}{_mapping.DocumentType.Name}Selector"; var baseType = determineBaseType(); var type = assembly.AddType(typeName, baseType); var interfaceType = typeof(ISelector <>).MakeGenericType(_mapping.DocumentType); type.Implements(interfaceType); var sync = type.MethodFor("Resolve"); var async = type.MethodFor("ResolveAsync"); var versionPosition = _mapping.IsHierarchy() ? 3 : 2; switch (_style) { case StorageStyle.QueryOnly: sync.Frames.Deserialize(_mapping); async.Frames.DeserializeAsync(_mapping); break; case StorageStyle.IdentityMap: sync.Frames.Deserialize(_mapping); async.Frames.DeserializeAsync(_mapping); sync.Frames.GetId(_mapping); async.Frames.GetIdAsync(_mapping); sync.Frames.StoreVersion(false, _mapping, versionPosition); async.Frames.StoreVersion(true, _mapping, versionPosition); sync.Frames.StoreInIdentityMap(_mapping); async.Frames.StoreInIdentityMap(_mapping); break; case StorageStyle.DirtyTracking: sync.Frames.Deserialize(_mapping); async.Frames.DeserializeAsync(_mapping); sync.Frames.GetId(_mapping); async.Frames.GetIdAsync(_mapping); sync.Frames.StoreVersion(false, _mapping, versionPosition); async.Frames.StoreVersion(true, _mapping, versionPosition); // TODO -- this needs to be a little different sync.Frames.StoreInIdentityMap(_mapping); async.Frames.StoreInIdentityMap(_mapping); break; case StorageStyle.Lightweight: sync.Frames.Deserialize(_mapping); async.Frames.DeserializeAsync(_mapping); sync.Frames.GetId(_mapping); async.Frames.GetIdAsync(_mapping); sync.Frames.StoreVersion(false, _mapping, versionPosition); async.Frames.StoreVersion(true, _mapping, versionPosition); break; default: throw new NotImplementedException("Not yet supporting dirty checking"); } sync.Frames.Return(_mapping.DocumentType); if (_style == StorageStyle.QueryOnly && !_mapping.IsHierarchy()) { async.Frames.Code("return Task.FromResult(document);"); } else { async.Frames.Return(_mapping.DocumentType); } return(type); }
public UpsertFunction(DocumentMapping mapping, DbObjectName identifier = null, bool disableConcurrency = false) : base(identifier ?? mapping.UpsertFunction) { _mapping = mapping; _disableConcurrency = disableConcurrency; if (mapping == null) { throw new ArgumentNullException(nameof(mapping)); } _tableName = mapping.TableName; // TODO -- it'd be nice to not need this here. var table = new DocumentTable(mapping); if (table.PrimaryKeys.Count > 1) { _primaryKeyConstraintName = mapping.TableName.Name + "_pkey"; } else { _primaryKeyConstraintName = "pk_" + mapping.TableName.Name; } var idType = mapping.IdMember.GetMemberType(); var pgIdType = TypeMappings.GetPgType(idType, mapping.EnumStorage); Arguments.Add(new UpsertArgument { Arg = "docId", PostgresType = pgIdType, Column = "id", Members = new[] { mapping.IdMember } }); Arguments.Add(new DocJsonBodyArgument()); Arguments.AddRange(mapping.DuplicatedFields.Select(x => x.UpsertArgument)); // TODO -- see the columns below if (mapping.Metadata.Version.Enabled) { Arguments.Add(new VersionArgument()); } if (mapping.Metadata.DotNetType.Enabled) { Arguments.Add(new DotNetTypeArgument()); } AddIfActive(mapping.Metadata.CorrelationId); AddIfActive(mapping.Metadata.CausationId); AddIfActive(mapping.Metadata.LastModifiedBy); AddIfActive(mapping.Metadata.Headers); if (mapping.IsHierarchy()) { Arguments.Add(new DocTypeArgument()); } if (mapping.UseOptimisticConcurrency) { Arguments.Add(new CurrentVersionArgument()); } if (mapping.TenancyStyle == TenancyStyle.Conjoined) { Arguments.Add(new TenantIdArgument()); _tenantWhereClause = $"{_tableName.QualifiedName}.{TenantIdColumn.Name} = {TenantIdArgument.ArgName}"; _andTenantWhereClause = $" and {_tenantWhereClause}"; } }