/// <summary> Clear state data function for this storage provider. </summary> /// <remarks> /// </remarks> /// <see cref="IStorageProvider#ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); try { if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerStorageProvider_ClearingData, $"Clearing: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource} Catalog={this.sqlconnBuilder.InitialCatalog}"); } var entity = new KeyValueStore() { GrainKeyId = primaryKey }; using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { db.KeyValues.Attach(entity); db.KeyValues.Remove(entity); await db.SaveChangesAsync(); } } catch (Exception ex) { Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_DeleteError, $"Error clearing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} in to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider#ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ReadingData, $"Reading: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} from DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}"); } try { using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { switch (this.useJsonOrBinaryFormat) { case StorageFormatEnum.Binary: case StorageFormatEnum.Both: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => s.BinaryContent).SingleOrDefaultAsync(); if (value != null) { //data = SerializationManager.DeserializeFromByteArray<Dictionary<string, object>>(value); grainState.State = SerializationManager.DeserializeFromByteArray <object>(value); } } break; case StorageFormatEnum.Json: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => s.JsonContext).SingleOrDefaultAsync(); if (!string.IsNullOrEmpty(value)) { //data = JsonConvert.DeserializeObject<Dictionary<string, object>>(value, jsonSettings); grainState.State = JsonConvert.DeserializeObject(value, grainState.State.GetType(), jsonSettings); } } break; default: break; } } grainState.ETag = Guid.NewGuid().ToString(); } catch (Exception ex) { Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ReadError, $"Error reading: GrainType={grainType} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider#ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, GrainState grainState) { var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvide_ReadingData, "Reading: GrainType={0} Pk={1} Grainid={2} from DataSource={3}", grainType, primaryKey, grainReference, this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog); } var data = new Dictionary <string, object>(); using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { switch (this.useJsonOrBinaryFormat) { case StorageFormatEnum.Binary: case StorageFormatEnum.Both: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => s.BinaryContent).SingleOrDefaultAsync(); if (value != null) { data = SerializationManager.DeserializeFromByteArray <Dictionary <string, object> >(value); } } break; case StorageFormatEnum.Json: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => s.JsonContext).SingleOrDefaultAsync(); if (!string.IsNullOrEmpty(value)) { data = JsonConvert.DeserializeObject <Dictionary <string, object> >(value, jsonSettings); } } break; default: break; } } grainState.SetAll(data); grainState.Etag = Guid.NewGuid().ToString(); }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider#WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WritingData, $"Writing: GrainType={grainType} PrimaryKey={primaryKey} GrainId={grainReference} ETag={grainState.ETag} to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}"); } try { var data = grainState.State; byte[] payload = null; string jsonpayload = string.Empty; if (this.useJsonOrBinaryFormat != StorageFormatEnum.Json) { payload = SerializationManager.SerializeToByteArray(data); } if (this.useJsonOrBinaryFormat == StorageFormatEnum.Json || this.useJsonOrBinaryFormat == StorageFormatEnum.Both) { jsonpayload = JsonConvert.SerializeObject(data, jsonSettings); } //we really need to be writing an Etag to the db as well var kvb = new KeyValueStore() { JsonContext = jsonpayload, BinaryContent = payload, GrainKeyId = primaryKey, }; using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { db.Set <KeyValueStore>().AddOrUpdate(kvb); await db.SaveChangesAsync(); } } catch (Exception ex) { Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WriteError, $"Error writing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Clear state data function for this storage provider. </summary> /// <remarks> /// </remarks> /// <see cref="IStorageProvider#ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); try { if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ClearingData, $"Clearing: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource} Catalog={this.sqlconnBuilder.InitialCatalog}"); } var entity = new KeyValueStore() { GrainKeyId = primaryKey }; using (var conn = new SqlConnection(this.sqlconnBuilder.ConnectionString)) using (var db = new KeyValueDbContext(conn, true)) { db.KeyValues.Attach(entity); db.KeyValues.Remove(entity); await db.SaveChangesAsync(); grainState.ETag = null; //if(grainState.State is GrainState) // ((GrainState)grainState.State).Etag = null; } } catch (DbUpdateConcurrencyException conCurrenyEx) { //someone has deleted has this record already Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_DeleteError, $"DbUpdateConcurrencyException ---- we will ignore this Error clearing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} in to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", conCurrenyEx); //dont throw --- move on } catch (Exception ex) { Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_DeleteError, $"Error clearing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} in to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider#WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, GrainState grainState) { var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvide_WritingData, "Writing: GrainType={0} PrimaryKey={1} Grainid={2} ETag={3} to DataSource={4}", grainType, primaryKey, grainReference, grainState.Etag, this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog); } var data = grainState.AsDictionary(); byte[] payload = null; string jsonpayload = string.Empty; if (this.useJsonOrBinaryFormat != StorageFormatEnum.Json) { payload = SerializationManager.SerializeToByteArray(data); } if (this.useJsonOrBinaryFormat == StorageFormatEnum.Json || this.useJsonOrBinaryFormat == StorageFormatEnum.Both) { jsonpayload = JsonConvert.SerializeObject(data, jsonSettings); } //await redisDatabase.StringSetAsync(primaryKey, json); var kvb = new KeyValueStore() { JsonContext = jsonpayload, BinaryContent = payload, GrainKeyId = primaryKey, }; using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { db.Set <KeyValueStore>().AddOrUpdate(kvb); await db.SaveChangesAsync(); } }
/// <summary> Clear state data function for this storage provider. </summary> /// <remarks> /// </remarks> /// <see cref="IStorageProvider#ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, GrainState grainState) { var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerStorageProvider_ClearingData, "Clearing: GrainType={0} Pk={1} Grainid={2} ETag={3} DeleteStateOnClear={4} from DataSource={5}", grainType, primaryKey, grainReference, grainState.Etag, this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog); } var entity = new KeyValueStore() { GrainKeyId = primaryKey }; using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { db.KeyValues.Attach(entity); db.KeyValues.Remove(entity); await db.SaveChangesAsync(); } }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider#ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ReadingData, $"Reading: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} from DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}"); } try { using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { switch (this.useJsonOrBinaryFormat) { case StorageFormatEnum.Binary: case StorageFormatEnum.Both: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => new { s.BinaryContent, s.ETag } ).SingleOrDefaultAsync(); if (value != null) { //data = SerializationManager.DeserializeFromByteArray<Dictionary<string, object>>(value); grainState.State = SerializationManager.DeserializeFromByteArray<object>(value.BinaryContent); grainState.ETag = value.ETag; if(grainState.State is GrainState) ((GrainState)grainState.State).Etag = value.ETag; } } break; case StorageFormatEnum.Json: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => new { s.JsonContext, s.ETag }).SingleOrDefaultAsync(); if (value != null && !string.IsNullOrEmpty(value.JsonContext)) { //data = JsonConvert.DeserializeObject<Dictionary<string, object>>(value, jsonSettings); grainState.State = JsonConvert.DeserializeObject(value.JsonContext, grainState.State.GetType(), jsonSettings); grainState.ETag = value.ETag; if(grainState.State is GrainState) ((GrainState)grainState.State).Etag = value.ETag; } } break; default: break; } } } catch (Exception ex) { Log.Error((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ReadError, $"Error reading: GrainType={grainType} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Clear state data function for this storage provider. </summary> /// <remarks> /// </remarks> /// <see cref="IStorageProvider#ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); try { if (Log.IsVerbose3) { Log.Verbose3((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerStorageProvider_ClearingData, $"Clearing: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource} Catalog={this.sqlconnBuilder.InitialCatalog}"); } var entity = new KeyValueStore() { GrainKeyId = primaryKey }; using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { db.KeyValues.Attach(entity); db.KeyValues.Remove(entity); grainState.ETag = null; if(grainState.State is GrainState) ((GrainState)grainState.State).Etag = null; await db.SaveChangesAsync(); } } catch (Exception ex) { Log.Error((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_DeleteError, $"Error clearing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} in to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider#WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if(grainState.State is GrainState) //WARN: HACK, such a hack grainState.ETag = ((GrainState)grainState.State).Etag; var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WritingData, $"Writing: GrainType={grainType} PrimaryKey={primaryKey} GrainId={grainReference} ETag={grainState.ETag} to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}"); } try { var data = grainState.State; byte[] payload = null; string jsonpayload = string.Empty; if (this.useJsonOrBinaryFormat != StorageFormatEnum.Json) { payload = SerializationManager.SerializeToByteArray(data); } if (this.useJsonOrBinaryFormat == StorageFormatEnum.Json || this.useJsonOrBinaryFormat == StorageFormatEnum.Both) { jsonpayload = JsonConvert.SerializeObject(data, jsonSettings); } var kvb = new KeyValueStore() { JsonContext = jsonpayload, BinaryContent = payload, GrainKeyId = primaryKey, ETag = Guid.NewGuid().ToString() }; using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { if(grainState.ETag != null) { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => s.ETag).SingleOrDefaultAsync(); if(value != null && value != grainState.ETag) { string error = $"Etag mismatch during WriteStateAsync for grain {primaryKey}: Expected = {value ?? "null"} Received = {grainState.ETag}"; Log.Error(0, error); throw new InconsistentStateException(error); } } db.Set<KeyValueStore>().AddOrUpdate(kvb); grainState.ETag = kvb.ETag; if(grainState.State is GrainState) ((GrainState)grainState.State).Etag = kvb.ETag; await db.SaveChangesAsync(); } } catch (Exception ex) { Log.Error((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WriteError, $"Error writing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider#WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (grainState.State is GrainState) //WARN: HACK, such a hack { grainState.ETag = ((GrainState)grainState.State).Etag; } var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WritingData, $"Writing: GrainType={grainType} PrimaryKey={primaryKey} GrainId={grainReference} ETag={grainState.ETag} to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}"); } try { var data = grainState.State; byte[] payload = null; string jsonpayload = string.Empty; if (this.useJsonOrBinaryFormat != StorageFormatEnum.Json) { payload = SerializationManager.SerializeToByteArray(data); } if (this.useJsonOrBinaryFormat == StorageFormatEnum.Json || this.useJsonOrBinaryFormat == StorageFormatEnum.Both) { jsonpayload = JsonConvert.SerializeObject(data, jsonSettings); } var kvb = new KeyValueStore() { JsonContext = jsonpayload, BinaryContent = payload, GrainKeyId = primaryKey, ETag = Guid.NewGuid().ToString() }; using (var conn = new SqlConnection(this.sqlconnBuilder.ConnectionString)) using (var db = new KeyValueDbContext(conn, true)) { if (grainState.ETag != null) { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => s.ETag).SingleOrDefaultAsync(); if (value != null && value != grainState.ETag) { string error = $"Error writing Etag mismatch: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} Expected = {value ?? "null"} Received = {grainState.ETag}"; Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WriteError, error); throw new InconsistentStateException(error); } } db.Set <KeyValueStore>().AddOrUpdate(kvb); grainState.ETag = kvb.ETag; if (grainState.State is GrainState) { ((GrainState)grainState.State).Etag = kvb.ETag; } await db.SaveChangesAsync(); } } catch (Exception ex) { Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WriteError, $"Error writing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider#ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ReadingData, $"Reading: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} from DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}"); } try { using (var conn = new SqlConnection(this.sqlconnBuilder.ConnectionString)) using (var db = new KeyValueDbContext(conn, true)) { switch (this.useJsonOrBinaryFormat) { case StorageFormatEnum.Binary: case StorageFormatEnum.Both: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => new { s.BinaryContent, s.ETag }).SingleOrDefaultAsync(); if (value != null) { //data = SerializationManager.DeserializeFromByteArray<Dictionary<string, object>>(value); grainState.State = _serializationManager.DeserializeFromByteArray <object>(value.BinaryContent); grainState.ETag = value.ETag; if (grainState.State is GrainState) { ((GrainState)grainState.State).Etag = value.ETag; } } } break; case StorageFormatEnum.Json: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => new { s.JsonContext, s.ETag }).SingleOrDefaultAsync(); if (value != null && !string.IsNullOrEmpty(value.JsonContext)) { //data = JsonConvert.DeserializeObject<Dictionary<string, object>>(value, jsonSettings); grainState.State = JsonConvert.DeserializeObject(value.JsonContext, grainState.State.GetType(), jsonSettings); grainState.ETag = value.ETag; if (grainState.State is GrainState) { ((GrainState)grainState.State).Etag = value.ETag; } } } break; default: break; } } } catch (Exception ex) { Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ReadError, $"Error reading: GrainType={grainType} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); if (!throwOnDeserializeError) { await ClearStateAsync(grainType, grainReference, grainState); } else { throw; //this is the default behavior if config option is missing } } }