public void VerifyColumnType(CorrelationProperty correlationProperty) { var columnType = MySqlCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); var name = correlationProperty.Name; writer.Write($@" set @column_type_{name} = ( select concat(column_type,' character set ', character_set_name) from information_schema.columns where table_schema = database() and table_name = @tableNameNonQuoted and column_name = 'Correlation_{name}' ); set @query = IF( @column_type_{name} <> '{columnType}', 'call sqlpersistence_raiseerror(concat(\'Incorrect data type for Correlation_{name}. Expected {columnType} got \', @column_type_{name}, \'.\'));', 'select \'Column Type OK\' status'); prepare script from @query; execute script; deallocate prepare script; "); }
static void TrySetCorrelationPropertyValue(ISagaData newSagaData, CorrelationProperty correlationProperty, object body, ITransactionContext transactionContext) { try { if (IgnoredProperties.Contains(correlationProperty.PropertyName)) { return; } var correlationPropertyInfo = newSagaData.GetType().GetProperty(correlationProperty.PropertyName); if (correlationPropertyInfo == null) { return; } var valueFromMessage = correlationProperty.ValueFromMessage(new MessageContext(transactionContext), body); correlationPropertyInfo.SetValue(newSagaData, valueFromMessage); } catch (Exception) { // if this fails it might be because the property is not settable.... just leave it to the programmer in the other end to set it } }
public void VerifyColumnType(CorrelationProperty correlationProperty) { string columnType; if (correlationProperty.Type == CorrelationPropertyType.String) { columnType = "character varying"; } else { columnType = PostgreSqlCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); } var name = correlationProperty.Name; writer.Write($@" columnType := ( select data_type from information_schema.columns where table_schema = schema and table_name = tableNameNonQuoted and column_name = 'Correlation_{name}' ); if columnType <> '{columnType}' then raise exception 'Incorrect data type for Correlation_{name}. Expected ""{columnType}"" got ""%""', columnType; end if; "); }
public void VerifyColumnType(CorrelationProperty correlationProperty) { var columnType = OracleCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); var name = OracleCorrelationPropertyName(correlationProperty); writer.Write($@" select data_type || case when char_length > 0 then '(' || char_length || ')' else case when data_precision is not null then '(' || data_precision || case when data_scale is not null and data_scale > 0 then ',' || data_scale end || ')' end end into dataType from all_tab_columns where table_name = '{tableName}' and column_name = '{name}' and owner = currentSchema; if(dataType <> '{columnType}') then raise_application_error(-20000, 'Incorrect data type for Correlation_{name}. Expected ""{columnType}"" got ""' || dataType || '"".'); end if; "); }
public void VerifyColumnType(CorrelationProperty correlationProperty) { string columnType; if (correlationProperty.Type == CorrelationPropertyType.String) { columnType = "nvarchar"; } else { columnType = MsSqlServerCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); } var name = correlationProperty.Name; writer.Write($@" declare @dataType_{name} nvarchar(max); set @dataType_{name} = ( select data_type from INFORMATION_SCHEMA.COLUMNS where table_name = @tableNameWithoutSchema and table_schema = @schema and column_name = 'Correlation_{name}' ); if (@dataType_{name} <> '{columnType}') begin declare @error_{name} nvarchar(max) = N'Incorrect data type for Correlation_{name}. Expected {columnType} got ' + @dataType_{name} + '.'; throw 50000, @error_{name}, 0 end "); }
public void WriteCreateIndex(CorrelationProperty correlationProperty) { var indexName = CreateSagaIndexName(saga.TableSuffix, correlationProperty.Name); writer.Write($@" script = 'create unique index if not exists ""' || tablePrefix || '{indexName}"" on ""' || schema || '"".""' || tableNameNonQuoted || '"" using btree (""Correlation_{correlationProperty.Name}"" asc);'; execute script;" ); }
public SagaDefinition(string tableSuffix, string name, CorrelationProperty correlationProperty = null, CorrelationProperty transitionalCorrelationProperty = null) { Guard.AgainstNullAndEmpty(nameof(tableSuffix), tableSuffix); Guard.AgainstNullAndEmpty(nameof(name), name); TableSuffix = tableSuffix; Name = name; CorrelationProperty = correlationProperty; TransitionalCorrelationProperty = transitionalCorrelationProperty; }
string OracleCorrelationPropertyName(CorrelationProperty property) { var name = "CORR_" + property.Name.ToUpper(); if (name.Length > 30) { name = name.Substring(0, 30); } return(name); }
public void AddProperty(CorrelationProperty correlationProperty) { var columnType = PostgreSqlCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); var name = correlationProperty.Name; writer.Write($@" script = 'alter table ""' || schema || '"".""' || tableNameNonQuoted || '"" add column if not exists ""Correlation_{name}"" {columnType}'; execute script; "); }
public void WriteCreateIndex(CorrelationProperty correlationProperty) { var columnName = OracleCorrelationPropertyName(correlationProperty); var indexName = CreateSagaIndexName(tableName, correlationProperty.Name); writer.Write($@" select count(*) into n from user_indexes where table_name = '{tableName}' and index_name = '{indexName}'; if(n = 0) then sqlStatement := 'create unique index ""{indexName}"" on ""{tableName}"" ({columnName} ASC)'; execute immediate sqlStatement; end if; "); }
public void AddProperty(CorrelationProperty correlationProperty) { var columnType = OracleCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); var name = OracleCorrelationPropertyName(correlationProperty); writer.Write($@" select count(*) into n from all_tab_columns where table_name = '{tableName}' and column_name = '{name}' and owner = currentSchema; if(n = 0) then sqlStatement := 'alter table ""{tableName}"" add ( {name} {columnType} )'; execute immediate sqlStatement; end if; "); }
public static SagaDefinition GetSagaDefinition(Type sagaType, BuildSqlDialect sqlDialect) { if (SagaTypeHasIntermediateBaseClass(sagaType)) { throw new Exception("Saga implementations must inherit from either Saga<T> or SqlSaga<T> directly. Deep class hierarchies are not supported."); } var saga = (Saga)FormatterServices.GetUninitializedObject(sagaType); var mapper = new ConfigureHowToFindSagaWithMessage(); methodInfo.Invoke(saga, new object[] { mapper }); CorrelationProperty correlationProperty = null; if (mapper.CorrelationType != null) { correlationProperty = new CorrelationProperty( name: mapper.CorrelationProperty, type: CorrelationPropertyTypeReader.GetCorrelationPropertyType(mapper.CorrelationType)); } var transitionalCorrelationPropertyName = GetSagaMetadataProperty(sagaType, saga, "TransitionalCorrelationPropertyName", att => att.TransitionalCorrelationProperty); CorrelationProperty transitional = null; if (transitionalCorrelationPropertyName != null) { var sagaDataType = sagaType.BaseType.GetGenericArguments()[0]; var transitionalProperty = sagaDataType.GetProperty(transitionalCorrelationPropertyName, AnyInstanceMember); transitional = new CorrelationProperty(transitionalCorrelationPropertyName, CorrelationPropertyTypeReader.GetCorrelationPropertyType(transitionalProperty.PropertyType)); } var tableSuffixOverride = GetSagaMetadataProperty(sagaType, saga, "TableSuffix", att => att.TableSuffix); var tableSuffix = tableSuffixOverride ?? sagaType.Name; if (sqlDialect == BuildSqlDialect.Oracle) { tableSuffix = tableSuffix.Substring(0, Math.Min(27, tableSuffix.Length)); } return(new SagaDefinition( tableSuffix: tableSuffix, name: sagaType.FullName, correlationProperty: correlationProperty, transitionalCorrelationProperty: transitional)); }
public static SagaDefinition GetSagaDefinition(Type sagaType, BuildSqlDialect sqlDialect) { var saga = (Saga)FormatterServices.GetUninitializedObject(sagaType); var mapper = new ConfigureHowToFindSagaWithMessage(); methodInfo.Invoke(saga, new object[] { mapper }); CorrelationProperty correlationProperty = null; if (mapper.CorrelationType != null) { correlationProperty = new CorrelationProperty( name: mapper.CorrelationProperty, type: CorrelationPropertyTypeReader.GetCorrelationPropertyType(mapper.CorrelationType)); } var transitionalCorrelationPropertyName = (string)sagaType .GetProperty("TransitionalCorrelationPropertyName", AnyInstanceMember) .GetValue(saga); CorrelationProperty transitional = null; if (transitionalCorrelationPropertyName != null) { var sagaDataType = sagaType.BaseType.GetGenericArguments()[0]; var transitionalProperty = sagaDataType.GetProperty(transitionalCorrelationPropertyName, AnyInstanceMember); transitional = new CorrelationProperty(transitionalCorrelationPropertyName, CorrelationPropertyTypeReader.GetCorrelationPropertyType(transitionalProperty.PropertyType)); } var tableSuffixOverride = (string)sagaType.GetProperty("TableSuffix", AnyInstanceMember).GetValue(saga); var tableSuffix = tableSuffixOverride ?? sagaType.Name; if (sqlDialect == BuildSqlDialect.Oracle) { tableSuffix = tableSuffix.Substring(0, Math.Min(27, tableSuffix.Length)); } return(new SagaDefinition( tableSuffix: tableSuffix, name: sagaType.FullName, correlationProperty: correlationProperty, transitionalCorrelationProperty: transitional)); }
public void AddProperty(CorrelationProperty correlationProperty) { var columnType = MsSqlServerCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); var name = correlationProperty.Name; writer.Write($@" if not exists ( select * from sys.columns where name = N'Correlation_{name}' and object_id = object_id(@tableName) ) begin declare @createColumn_{name} nvarchar(max); set @createColumn_{name} = ' alter table ' + @tableName + N' add Correlation_{name} {columnType};'; exec(@createColumn_{name}); end "); }
public void VerifyColumnType(CorrelationProperty correlationProperty) { var columnType = MsSqlServerCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); var name = correlationProperty.Name; writer.Write($@" declare @dataType_{name} nvarchar(max); set @dataType_{name} = ( select data_type from information_schema.columns where table_name = ' + @tableName + N' and column_name = 'Correlation_{name}' ); if (@dataType_{name} <> '{columnType}') begin declare @error_{name} nvarchar(max) = N'Incorrect data type for Correlation_{name}. Expected {columnType} got ' + @dataType_{name} + '.'; throw 50000, @error_{name}, 0 end "); }
public void AddProperty(CorrelationProperty correlationProperty) { var columnType = MySqlCorrelationPropertyTypeConverter.GetColumnType(correlationProperty.Type); var name = correlationProperty.Name; writer.Write($@" select count(*) into @exist from information_schema.columns where table_schema = database() and column_name = 'Correlation_{name}' and table_name = @tableNameNonQuoted; set @query = IF( @exist <= 0, concat('alter table ', @tableNameQuoted, ' add column Correlation_{name} {columnType}'), 'select \'Column Exists\' status'); prepare script from @query; execute script; deallocate prepare script; "); }
public void WriteCreateIndex(CorrelationProperty correlationProperty) { var name = correlationProperty.Name; writer.Write($@" if not exists ( select * from sys.indexes where name = N'Index_Correlation_{name}' and object_id = object_id(@tableName) ) begin declare @createIndex_{name} nvarchar(max); set @createIndex_{name} = N' create unique index Index_Correlation_{name} on ' + @tableName + N'(Correlation_{name}) where Correlation_{name} is not null;'; exec(@createIndex_{name}); end "); }
public void WriteCreateIndex(CorrelationProperty correlationProperty) { var name = correlationProperty.Name; writer.Write($@" select count(*) into @exist from information_schema.statistics where table_schema = database() and index_name = 'Index_Correlation_{name}' and table_name = @tableNameNonQuoted; set @query = IF( @exist <= 0, concat('create unique index Index_Correlation_{name} on ', @tableNameQuoted, '(Correlation_{name})'), 'select \'Index Exists\' status'); prepare script from @query; execute script; deallocate prepare script; "); }
private static void ValidateCorrelation(ICollection <CorrelationProperty> initializerProperties, ICollection <CorrelationProperty> followerProperties, string memberName, Activity activity) { if (followerProperties == null && initializerProperties == null) { return; } if (followerProperties == null || initializerProperties == null) { throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName)); } if (initializerProperties.Count != followerProperties.Count) { throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName)); } IEnumerator <CorrelationProperty> initializerValues = initializerProperties.GetEnumerator(); IEnumerator <CorrelationProperty> followerValues = followerProperties.GetEnumerator(); while (initializerValues.MoveNext() && followerValues.MoveNext()) { IComparable initializerValue = initializerValues.Current.Value as IComparable; object followerValue = followerValues.Current.Value; // if (!initializerValues.Current.Name.Equals(followerValues.Current.Name, StringComparison.OrdinalIgnoreCase)) { CorrelationProperty followerProperty = null; IEnumerator <CorrelationProperty> followerEnumerator = followerProperties.GetEnumerator(); while (followerEnumerator.MoveNext()) { // We don't need to be concerned with culture here because the names we are comparing // are parameter names on methods in an interface. if (initializerValues.Current.Name.Equals(followerEnumerator.Current.Name, StringComparison.OrdinalIgnoreCase)) { // We found a matching Name in the follower collection. // Saving the followerProperty rather than followerEnumerator.Current.Value here // because the latter could be null and still be correct. I need something // that indicates that we actually found a matching CorrelationProperty in the // collection. So instead of having a separate bool, I just have a reference // to the matching CorrelationProperty. followerProperty = followerEnumerator.Current; break; } // If we get here, the name of the parameter doesn't match, so just move to the next element in the // followerEnumerator. } // If we found a followerProperty with a matching name, use it. // In the highly, possibly impossible, event that we didn't find an element in the // followerProperties collection with a matching name, we fall thru with // followerValue = followerValues.Current.Value, which is exactly what the previous // code had, and we act just like we did before. if (followerProperty != null) { followerValue = followerProperty.Value; } } if (initializerValue != null && (initializerValue.CompareTo(followerValue) != 0)) { throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName)); } else if (initializerValues.Current.Value == null && followerValue == null) { return; } else if (initializerValue == null && followerValue != null && !followerValue.Equals(initializerValues.Current.Value)) { throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName)); } } }
private static void ValidateCorrelation(ICollection <CorrelationProperty> initializerProperties, ICollection <CorrelationProperty> followerProperties, string memberName, Activity activity) { if (followerProperties == null && initializerProperties == null) { return; } if (followerProperties == null || initializerProperties == null) { throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName)); } if (initializerProperties.Count != followerProperties.Count) { throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName)); } IEnumerator <CorrelationProperty> initializerValues = initializerProperties.GetEnumerator(); IEnumerator <CorrelationProperty> followerValues = followerProperties.GetEnumerator(); while (initializerValues.MoveNext() && followerValues.MoveNext()) { IComparable initializerValue = initializerValues.Current.Value as IComparable; object followerValue = followerValues.Current.Value; // Bug DevDiv2\DevDiv 552322 - http://vstfdevdiv.redmond.corp.microsoft.com:8080/DevDiv2/DevDiv/_workitems#_a=edit&id=552322 // Reflection does not guarantee ordering, so the two collections (arrays) of // CorrelationProperties may not be in the same order, based on Name. So we need to check all the // elements of the followerProperties for the Name of the current initializerValue. // The collections MIGHT be in the same order. Before searching the followerProperties collection for an element with a matching // name, see if the current element in the initializerValues and followerValues enumerators have a matching name. // If they do match, just fall thru because followerValue is already set to followerValues.Current.Value; if (!initializerValues.Current.Name.Equals(followerValues.Current.Name, StringComparison.OrdinalIgnoreCase)) { CorrelationProperty followerProperty = null; IEnumerator <CorrelationProperty> followerEnumerator = followerProperties.GetEnumerator(); while (followerEnumerator.MoveNext()) { // We don't need to be concerned with culture here because the names we are comparing // are parameter names on methods in an interface. if (initializerValues.Current.Name.Equals(followerEnumerator.Current.Name, StringComparison.OrdinalIgnoreCase)) { // We found a matching Name in the follower collection. // Saving the followerProperty rather than followerEnumerator.Current.Value here // because the latter could be null and still be correct. I need something // that indicates that we actually found a matching CorrelationProperty in the // collection. So instead of having a separate bool, I just have a reference // to the matching CorrelationProperty. followerProperty = followerEnumerator.Current; break; } // If we get here, the name of the parameter doesn't match, so just move to the next element in the // followerEnumerator. } // If we found a followerProperty with a matching name, use it. // In the highly, possibly impossible, event that we didn't find an element in the // followerProperties collection with a matching name, we fall thru with // followerValue = followerValues.Current.Value, which is exactly what the previous // code had, and we act just like we did before. if (followerProperty != null) { followerValue = followerProperty.Value; } } if (initializerValue != null && (initializerValue.CompareTo(followerValue) != 0)) { throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName)); } else if (initializerValues.Current.Value == null && followerValue == null) { return; } else if (initializerValue == null && followerValue != null && !followerValue.Equals(initializerValues.Current.Value)) { throw new InvalidOperationException(SR.GetString(SR.Error_CorrelationViolationException, memberName, activity.QualifiedName)); } } }
public Task Store(ISagaData data, CorrelationProperty correlationProperty, CancellationToken cancellationToken) => throw new NotSupportedException(SR.NoConfiguredSagaStorage);
public Task Configure(CancellationToken cancellationToken = default) { var variant = (SqlTestVariant)Variant.Values[0]; var dialect = variant.Dialect; var buildDialect = variant.BuildDialect; var connectionFactory = variant.ConnectionFactory; var pessimisticMode = variant.UsePessimisticMode; if (SessionTimeout.HasValue) { dialect = new TimeoutSettingDialect(dialect, (int)SessionTimeout.Value.TotalSeconds); } var infoCache = new SagaInfoCache( null, Serializer.JsonSerializer, reader => new JsonTextReader(reader), writer => new JsonTextWriter(writer), "PersistenceTests_", dialect, SagaMetadataCollection, name => ShortenSagaName(name)); var connectionManager = new ConnectionManager(connectionFactory); SagaIdGenerator = new DefaultSagaIdGenerator(); SagaStorage = new SagaPersister(infoCache, dialect); SynchronizedStorage = new SynchronizedStorage(connectionManager, infoCache, null); SynchronizedStorageAdapter = new StorageAdapter(connectionManager, infoCache, dialect, null); OutboxStorage = CreateOutboxPersister(connectionManager, dialect, false, false); SupportsPessimisticConcurrency = pessimisticMode; GetContextBagForSagaStorage = () => { var contextBag = new ContextBag(); contextBag.Set(new IncomingMessage("MessageId", new Dictionary <string, string>(), new byte[0])); return(contextBag); }; GetContextBagForOutbox = () => { var contextBag = new ContextBag(); contextBag.Set(new IncomingMessage("MessageId", new Dictionary <string, string>(), new byte[0])); return(contextBag); }; using (var connection = connectionFactory()) { connection.Open(); foreach (var saga in SagaMetadataCollection) { CorrelationProperty correlationProperty = null; if (saga.TryGetCorrelationProperty(out var propertyMetadata)) { correlationProperty = new CorrelationProperty(propertyMetadata.Name, CorrelationPropertyType.String); } var tableName = ShortenSagaName(saga.SagaType.Name); var definition = new SagaDefinition(tableName, saga.EntityName, correlationProperty); connection.ExecuteCommand(SagaScriptBuilder.BuildDropScript(definition, buildDialect), "PersistenceTests"); connection.ExecuteCommand(SagaScriptBuilder.BuildCreateScript(definition, buildDialect), "PersistenceTests"); } connection.ExecuteCommand(OutboxScriptBuilder.BuildDropScript(buildDialect), "PersistenceTests"); connection.ExecuteCommand(OutboxScriptBuilder.BuildCreateScript(buildDialect), "PersistenceTests"); } return(Task.CompletedTask); }