//This is not working //TODO: Fix syntax of updateCommand private void UpdateUsingEntityCommand(User entity) { using (EntityConnection entityConnection = new EntityConnection("name=AppEntities")) { entityConnection.Open(); using (EntityTransaction entityTransaction = entityConnection.BeginTransaction(IsolationLevel.Serializable)) { string updateCommand = "UPDATE AppEntities.USERS AS U " + "SET U.FirstName = @FirstName, " + "U.LastName = @lastName, " + "U.Username = @userName, " + "U.City = @city " + "WHERE U.Id = @Id"; using (EntityCommand command = new EntityCommand(updateCommand, entityConnection, entityTransaction)) { EntityParameter firstName = new EntityParameter() { ParameterName = "firstName", Value = entity.FirstName }; EntityParameter lastName = new EntityParameter() { ParameterName = "lastName", Value = entity.LastName }; EntityParameter username = new EntityParameter() { ParameterName = "username", Value = entity.Username }; EntityParameter city = new EntityParameter() { ParameterName = "city", Value = entity.City }; EntityParameter id = new EntityParameter() { ParameterName = "Id", Value = entity.Id }; command.Parameters.Add(firstName); command.Parameters.Add(lastName); command.Parameters.Add(username); command.Parameters.Add(city); command.Parameters.Add(id); try { command.ExecuteNonQuery(); entityTransaction.Commit(); } catch (Exception ex) { entityTransaction.Rollback(); } } } } }
/// <summary> /// Rolls back the underlying store transaction /// </summary> public void Rollback() { _entityTransaction.Rollback(); }
private void ProcessPackageEdits(IEnumerable <PackageEdit> editsForThisPackage, EntitiesContext entitiesContext) { // List of Work to do: // 1) Backup old blob, if the original has not been backed up yet // 2) Downloads blob, create new NUPKG locally // 3) Upload blob // 4) Update the database PackageEdit edit = editsForThisPackage.OrderByDescending(pe => pe.Timestamp).First(); var blobClient = StorageAccount.CreateCloudBlobClient(); var packagesContainer = Util.GetPackagesBlobContainer(blobClient); var latestPackageFileName = Util.GetPackageFileName(edit.Package.PackageRegistration.Id, edit.Package.Version); var originalPackageFileName = Util.GetBackupOfOriginalPackageFileName(edit.Package.PackageRegistration.Id, edit.Package.Version); var originalPackageBackupBlob = packagesContainer.GetBlockBlobReference(originalPackageFileName); var latestPackageBlob = packagesContainer.GetBlockBlobReference(latestPackageFileName); var edits = new List <Action <ManifestMetadata> > { (m) => { m.Authors = edit.Authors; }, (m) => { m.Copyright = edit.Copyright; }, (m) => { m.Description = edit.Description; }, (m) => { m.IconUrl = edit.IconUrl; }, (m) => { m.LicenseUrl = edit.LicenseUrl; }, (m) => { m.ProjectUrl = edit.ProjectUrl; }, (m) => { m.ReleaseNotes = edit.ReleaseNotes; }, (m) => { m.RequireLicenseAcceptance = edit.RequiresLicenseAcceptance; }, (m) => { m.Summary = edit.Summary; }, (m) => { m.Title = edit.Title; }, (m) => { m.Tags = edit.Tags; }, }; Log.Info( "Processing Edit Key={0}, PackageId={1}, Version={2}", edit.Key, edit.Package.PackageRegistration.Id, edit.Package.Version); if (!WhatIf) { edit.TriedCount += 1; int nr = entitiesContext.SaveChanges(); if (nr != 1) { throw new ApplicationException( String.Format("Something went terribly wrong, only one entity should be updated but actually {0} entities were updated", nr)); } } ArchiveOriginalPackageBlob(originalPackageBackupBlob, latestPackageBlob); using (var readWriteStream = new MemoryStream()) { // Download to memory CloudBlockBlob downloadSourceBlob = WhatIf ? latestPackageBlob : originalPackageBackupBlob; Log.Info("Downloading original package blob to memory {0}", downloadSourceBlob.Name); downloadSourceBlob.DownloadToStream(readWriteStream); // Rewrite in memory Log.Info("Rewriting nupkg package in memory", downloadSourceBlob.Name); NupkgRewriter.RewriteNupkgManifest(readWriteStream, edits); // Get updated hash code, and file size Log.Info("Computing updated hash code of memory stream"); var newPackageFileSize = readWriteStream.Length; var hashAlgorithm = HashAlgorithm.Create("SHA512"); byte[] hashBytes = hashAlgorithm.ComputeHash(readWriteStream.GetBuffer()); var newHash = Convert.ToBase64String(hashBytes); if (!WhatIf) { // Snapshot the blob var blobSnapshot = latestPackageBlob.CreateSnapshot(); // Start Transaction: Complete the edit in the gallery DB. // Use explicit SQL transactions instead of EF operation-grouping // so that we can manually roll the transaction back on a blob related failure. ObjectContext objectContext = (entitiesContext as IObjectContextAdapter).ObjectContext; ((objectContext.Connection) as EntityConnection).Open(); // must open in order to begin transaction using (EntityTransaction transaction = ((objectContext.Connection) as EntityConnection).BeginTransaction()) { edit.Apply(hashAlgorithm: "SHA512", hash: newHash, packageFileSize: newPackageFileSize); // Add to transaction: delete all the pending edits of this package. foreach (var eachEdit in editsForThisPackage) { entitiesContext.DeleteOnCommit(eachEdit); } entitiesContext.SaveChanges(); // (transaction is still not committed, but do some EF legwork up-front of modifying the blob) try { // Reupload blob Log.Info("Uploading blob from memory {0}", latestPackageBlob.Name); readWriteStream.Position = 0; latestPackageBlob.UploadFromStream(readWriteStream); } catch (Exception e) { // Uploading the updated nupkg failed. // Rollback the transaction, which restores the Edit to PackageEdits so it can be attempted again. Log.Error("(error) - package edit blob update failed. Rolling back the DB transaction."); Log.ErrorException("(exception", e); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); transaction.Rollback(); return; } try { transaction.Commit(); } catch (Exception e) { // Commit changes to DB failed. // Since our blob update wasn't part of the transaction (and doesn't AFAIK have a 'commit()' operator we can utilize for the type of blobs we are using) // try, (single attempt) to roll back the blob update by restoring the previous snapshot. Log.Error("(error) - package edit DB update failed. Trying to roll back the blob to its previous snapshot."); Log.ErrorException("(exception", e); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); try { latestPackageBlob.StartCopyFromBlob(blobSnapshot); } catch (Exception e2) { // In this case it may not be the end of the world - the package metadata mismatches the edit now, // but there's still an edit in the queue, waiting to be rerun and put everything back in synch. Log.Error("(error) - rolling back the package blob to its previous snapshot failed."); Log.ErrorException("(exception", e2); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); } } } } } }