public override void CreateUninitializedItem(HttpContext context, string id, int timeout) { Debug.Assert(context != null); SecUtility.CheckParameter(ref id, true, true, false, TableStorageConstants.MaxStringPropertySizeInChars, "id"); if (timeout < 0) { throw new ArgumentException("Parameter timeout must be a non-negative integer!"); } try { TableStorageDataServiceContext svc = CreateDataServiceContext(); SessionRow session = new SessionRow(id, _applicationName); session.Lock = 0; // no lock session.Initialized = false; session.Id = id; session.Timeout = timeout; session.ExpiresUtc = DateTime.UtcNow.AddMinutes(timeout); svc.AddObject(_tableName, session); svc.SaveChangesWithRetries(); } catch (InvalidOperationException e) { throw new ProviderException("Error accessing the data store.", e); } }
// Because of limited transactional support in the table storage offering, this function gives limited guarantees // for inserting all users into all roles. // We do not recommend using this function because of missing transactional support. public override void AddUsersToRoles(string[] usernames, string[] roleNames) { SecUtility.CheckArrayParameter(ref roleNames, true, true, true, MaxTableRoleNameLength, "roleNames"); SecUtility.CheckArrayParameter(ref usernames, true, true, true, Constants.MaxTableUsernameLength, "usernames"); RoleRow row; try { TableStorageDataServiceContext svc = CreateDataServiceContext(); foreach (string role in roleNames) { if (!RoleExists(role)) { throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist!", role)); } foreach (string user in usernames) { row = new RoleRow(_applicationName, role, user); try { svc.AddObject(_tableName, row); svc.SaveChangesWithRetries(); } catch (InvalidOperationException e) { HttpStatusCode status; if (TableStorageHelpers.EvaluateException(e, out status) && status == HttpStatusCode.Conflict) { // this element already exists or was created in a failed retry // this is not a fatal error; continue adding elements Log.Write(EventKind.Warning, string.Format(CultureInfo.InstalledUICulture, "The user {0} already exists in the role {1}.", user, role)); svc.Detach(row); } else { throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "Error adding user {0} to role {1}", user, role)); } } } } } catch (InvalidOperationException e) { throw new ProviderException("Error while accessing the data store.", e); } }
public override void CreateRole(string roleName) { SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename"); try { TableStorageDataServiceContext svc = CreateDataServiceContext(); RoleRow newRole = new RoleRow(_applicationName, roleName, string.Empty); svc.AddObject(_tableName, newRole); svc.SaveChangesWithRetries(); } catch (InvalidOperationException e) { HttpStatusCode status; // when retry policies are used we cannot distinguish between a conflict and success // so, in the case of a conflict, we just retrun success here if (TableStorageHelpers.EvaluateException(e, out status) && status == HttpStatusCode.Conflict) { return; // the role already exists } throw new ProviderException("Error accessing role table.", e); } }
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { Debug.Assert(context != null); SecUtility.CheckParameter(ref id, true, true, false, TableStorageConstants.MaxStringPropertySizeInChars, "id"); _providerRetry(() => { TableStorageDataServiceContext svc = CreateDataServiceContext(); SessionRow session; if (!newItem) { session = GetSession(id, svc); if (session == null || session.Lock != (int)lockId) { Debug.Assert(false); return; } } else { session = new SessionRow(id, _applicationName); session.Lock = 1; session.LockDateUtc = DateTime.UtcNow; } session.Initialized = true; Debug.Assert(session.Timeout >= 0); session.Timeout = item.Timeout; session.ExpiresUtc = DateTime.UtcNow.AddMinutes(session.Timeout); session.Locked = false; // yes, we always create a new blob here session.BlobName = GetBlobNamePrefix(id) + Guid.NewGuid().ToString("N"); // Serialize the session and write the blob byte[] items, statics; SerializeSession(item, out items, out statics); string serializedItems = Convert.ToBase64String(items); string serializedStatics = Convert.ToBase64String(statics); MemoryStream output = new MemoryStream(); StreamWriter writer = new StreamWriter(output); try { writer.WriteLine(serializedItems); writer.WriteLine(serializedStatics); writer.Flush(); // for us, it shouldn't matter whether newItem is set to true or false // because we always create the entire blob and cannot append to an // existing one _blobProvider.UploadStream(session.BlobName, output); writer.Close(); output.Close(); } catch (Exception e) { if (!newItem) { ReleaseItemExclusive(svc, session, lockId); } throw new ProviderException("Error accessing the data store.", e); } finally { if (writer != null) { writer.Close(); } if (output != null) { output.Close(); } } if (newItem) { svc.AddObject(_tableName, session); svc.SaveChangesWithRetries(); } else { // Unlock the session and save changes ReleaseItemExclusive(svc, session, lockId); } }); }
// shows alternative ways of generating DataServiceContext objects internal static void RunSamples2() { StorageAccountInfo account = null; try { account = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration(); TableStorage tableStorage = TableStorage.Create(account); tableStorage.RetryPolicy = RetryPolicies.RetryN(3, TimeSpan.FromSeconds(1)); // the DataServiceContext object inherits its retry policy from tableStorage in this case TableStorageDataServiceContext svc = tableStorage.GetDataServiceContext(); Console.WriteLine("Table creation, delete and list samples..."); string sampleTableName = SampleDataServiceContext.SampleTableName; tableStorage.TryCreateTable(sampleTableName); DeleteAllEntriesFromSampleTable(svc, sampleTableName); Console.WriteLine("List all tables in the account."); IEnumerable <string> tables2 = tableStorage.ListTables(); foreach (string n1 in tables2) { Console.WriteLine(n1); } Console.WriteLine("Inserting entities into the table..."); SampleEntity t = new SampleEntity("samplepartitionkey", "samplerowkey"); svc.AddObject(sampleTableName, t); svc.SaveChangesWithRetries(); //Detach the existing entity so that we can demonstrate the server side //error when you try to insert an same object with the same keys svc.Detach(t); // Insert an entity with the same keys Console.WriteLine("Try to insert the same entity into the table and show how to deal with error conditions."); t = new SampleEntity("samplepartitionkey", "samplerowkey"); svc.AddObject(sampleTableName, t); try { svc.SaveChangesWithRetries(); // getting here is an error because inserting the same row twice raises an exception Console.WriteLine("Should not get here. Succeeded inserting two entities with the same keys"); } catch (Exception e) { HttpStatusCode status; StorageExtendedErrorInformation errorInfo; if (TableStorageHelpers.EvaluateException(e, out status, out errorInfo) && status == HttpStatusCode.Conflict) { // the row has already been inserted before, this is expected here if (errorInfo != null) { Console.WriteLine("Attempting to insert row with same keys resulted in error {0} : {1}", errorInfo.ErrorCode, errorInfo.ErrorMessage); } } else { throw; } } svc.Detach(t); Console.WriteLine("Insert a large item into the table."); t = new SampleEntity("samplepartitionkey", "samplerowkey1"); t.B = new String('a', 1000); svc.AddObject(sampleTableName, t); svc.SaveChangesWithRetries(); Console.WriteLine("Create a normal DataServiceContext object (not TableStorageDataServiceContext) and attach it to a TableStorage object."); DataServiceContext svc2 = new DataServiceContext( TableStorage.GetServiceBaseUri(account.BaseUri, account.UsePathStyleUris, account.AccountName)); tableStorage.Attach(svc2); var qResult = from c in svc2.CreateQuery <SampleEntity>(sampleTableName) where c.RowKey == "samplerowkey1" select c; foreach (SampleEntity cust in qResult) { if (cust.B != t.B) { Console.WriteLine("Sample failed. Did not read the entity property just written"); } } Console.WriteLine("Insert many rows in a table and show the API for dealing with query result pagination."); int num = 2100; Console.WriteLine("Inserting {0} rows.", num.ToString(CultureInfo.CurrentUICulture)); for (int i = 0; i < num; i++) { t = new SampleEntity("samplestring", i.ToString(CultureInfo.InvariantCulture)); svc.AddObject(sampleTableName, t); svc.SaveChangesWithRetries(); if ((i + 1) % 50 == 0) { Console.WriteLine("Inserted row {0}.", (i + 1).ToString(CultureInfo.CurrentUICulture)); } } Console.WriteLine("Executing query that will return many results. This can take a while..."); var qResult2 = from c in svc.CreateQuery <SampleEntity>(sampleTableName) where c.PartitionKey == "samplestring" select c; TableStorageDataServiceQuery <SampleEntity> tableStorageQuery = new TableStorageDataServiceQuery <SampleEntity>(qResult2 as DataServiceQuery <SampleEntity>); IEnumerable <SampleEntity> res = tableStorageQuery.ExecuteAllWithRetries(); Console.WriteLine("Retrieved query results:"); foreach (SampleEntity entity in res) { Console.WriteLine("Partition key: {0}, row key: {1}.", entity.PartitionKey, entity.RowKey); } Console.WriteLine("Delete all entries in the sample table."); DeleteAllEntriesFromSampleTable(tableStorage.GetDataServiceContext(), sampleTableName); tableStorage.DeleteTable(sampleTableName); Console.WriteLine("Table samples finished!"); } catch (DataServiceRequestException dsre) { Console.WriteLine("DataServiceRequestException: " + GetExceptionMessage(dsre)); ShowTableStorageErrorMessage(account.BaseUri.ToString()); } catch (InvalidOperationException ioe) { Console.WriteLine("Storage service error: " + GetExceptionMessage(ioe)); ShowTableStorageErrorMessage(account.BaseUri.ToString()); } }