コード例 #1
0
        /// <summary>
        /// Updates the entity in the database and returns the updated entity
        /// Careful insert checks revisions to detect write-write conflicts
        /// </summary>
        public virtual void Update(
            Entity entity,
            bool carefully = false
            )
        {
            string type = EntityUtils.GetEntityStringType(entity.GetType());

            if (string.IsNullOrEmpty(entity.EntityKey))
            {
                throw new ArgumentException(
                          "Provided entity has not been inserted yet"
                          );
            }

            try
            {
                JsonObject oldDocument = FindDocument(entity.EntityId);

                if (oldDocument == null)
                {
                    throw new ArangoException(404, 1202, "document not found");
                }

                JsonObject newDocument = SerializeEntity(entity);

                // set timestamps
                // (serializer instead of direct setting, because the serializer
                // does not store "Z" (timezone), so deserialization does not
                // correct for timezones and loads it as it is)
                newDocument["CreatedAt"] = oldDocument["CreatedAt"];
                newDocument["UpdatedAt"] = Serializer.ToJson(DateTime.UtcNow);

                // if we aren't careful, then don't even send the _rev key
                // (just to make sure the database won't throw a conflict)
                // (this probably doesn't help with anything, but why not do it)
                if (!carefully)
                {
                    newDocument.Remove("_rev");
                }

                var newAttributes = arango.ExecuteAqlQuery(new AqlQuery()
                                                           .Replace(() => newDocument)
                                                           .CheckRevs(carefully)
                                                           .In(EntityUtils.CollectionFromType(type))
                                                           .Return("NEW")
                                                           ).First().AsJsonObject;

                EntitySerializer.SetAttributes(
                    entity,
                    newAttributes,
                    DeserializationContext.ServerStorageToServer
                    );
            }
            catch (ArangoException e) when(e.ErrorNumber == 1200)
            {
                // write-write conflict

                /*
                 * Write-write conflict (1200) can be thrown even when we
                 * don't explicitly check for revisions. This comes down
                 * to the way ArangoDB works. If it tries to acquire a write
                 * lock on a document and fails, it doesn't retry and throws
                 * the conflict error (it fails because someone else is
                 * currently writing to that document). Giving up on the write
                 * is ok in this situation as it could be though of as the
                 * other process immediately overwriting our update.
                 *
                 * https://github.com/arangodb/arangodb/issues/9702
                 */

                // When we are careful, we need to notify the user by
                // throwing a conflict exception
                if (carefully)
                {
                    throw new EntityRevConflictException(
                              "Entity has been modified since the last refresh"
                              );
                }

                // When we aren't careful, we just warn the user and
                // ignore the fact the write failed. (see the note above)
                log.Warning(
                    "Entity wasn't saved due to a write-write conflict " +
                    "(other process was saving the same entity at the " +
                    "same time).\nCheck out documentation for the method " +
                    "entity.SaveCarefully() to learn more.",
                    e
                    );
            }
            catch (ArangoException e) when(e.ErrorNumber == 1202)
            {
                // document not found
                throw new EntityPersistenceException(
                          "Entity has not yet been inserted, or already deleted"
                          );
            }
            catch (ArangoException e) when(e.ErrorNumber == 1203)
            {
                // collection not found
                throw new EntityPersistenceException(
                          "Entity has not yet been inserted, or already deleted"
                          );
            }
        }