Пример #1
0
        //private void ExtendSaveContentTypes(IEnumerable<ContentType> contentTypes)
        //    => Storage.DoWhileQueueingRelationships(() => contentTypes.ToList().ForEach(ExtendSaveContentTypes));

        ///// <summary>
        ///// Import an AttributeSet with all Attributes and AttributeMetaData
        ///// </summary>
        //private void ExtendSaveContentTypes(ContentType contentType)
        //{
        //    // initialize destinationSet - create or test existing if ok
        //    var foundSet = _dbDeepAccess.ContentType.GetOrCreateContentType(contentType);
        //    if (foundSet == null) // something went wrong, skip this import
        //        return;
        //    var contentTypeId = foundSet.Value;

        //    // append all Attributes
        //    foreach (var newAtt in contentType.Attributes.Cast<AttributeDefinition>())
        //    {
        //        var destAttribId = _dbDeepAccess.AttributesDefinition.GetOrCreateAttributeDefinition(contentTypeId, newAtt);

        //        // save additional entities containing AttributeMetaData for this attribute
        //        if (newAtt.InternalAttributeMetaData != null)
        //            SaveAttributeMetadata(destAttribId, newAtt.InternalAttributeMetaData);
        //    }

        //    // optionally re-order the attributes if specified in import
        //    if (contentType.OnSaveSortAttributes)
        //        _dbDeepAccess.ContentType.SortAttributes(contentTypeId, contentType);
        //}


        ///// <summary>
        ///// Save additional entities describing the attribute
        ///// </summary>
        ///// <param name="attributeId"></param>
        ///// <param name="metadata"></param>
        //private void SaveAttributeMetadata(int attributeId, List<Entity> metadata)
        //{
        //    var entities = new List<IEntity>();
        //    foreach (var entity in metadata)
        //    {
        //        var md = (Metadata) entity.Metadata;
        //        // Validate Entity
        //        md.TargetType = Constants.MetadataForAttribute;

        //        // Set KeyNumber
        //        if (attributeId == 0 || attributeId < 0) // < 0 is ef-core temp id
        //            throw new Exception($"trying to add metadata to attribute {attributeId} but attribute isn't saved yet");//_dbDeepAccess.SqlDb.SaveChanges();

        //        md.KeyNumber = attributeId;

        //        //// Get guid of previously existing assignment - if it exists
        //        //var existingMetadata = _dbDeepAccess.Entities
        //        //    .GetAssignedEntities(Constants.MetadataForAttribute, keyNumber: attributeId)
        //        //    .FirstOrDefault(e => e.AttributeSetId == attributeId);

        //        //if (existingMetadata != null)
        //        //    entity.SetGuid(existingMetadata.EntityGuid);

        //        //entities.Add(CreateMergedForSaving(entity, _entireApp, SaveOptions));
        //        entities.Add(entity);
        //    }
        //    Storage.Save(entities, SaveOptions.Build(ZoneId)); // don't use the standard save options, as this is attributes only
        //}



        private void MergeContentTypeUpdateWithExisting(IContentType contentType)
        {
            var existing = _entireApp.ContentTypes.Values.FirstOrDefault(ct => ct.StaticName == contentType.StaticName);

            if (existing == null)
            {
                return;
            }

            foreach (var newAttrib in contentType.Attributes)
            {
                var existAttrib = existing.Attributes.FirstOrDefault(a => a.Name == newAttrib.Name);
                if (existAttrib == null)
                {
                    continue;
                }

                var impMeta     = ((AttributeDefinition)newAttrib).Items;
                var newMetaList = new List <IEntity>();
                foreach (var newMd in impMeta)
                {
                    var existingMetadata = _entireApp.GetMetadata(Constants.MetadataForAttribute, existAttrib.AttributeId, newMd.Type.StaticName).FirstOrDefault();
                    if (existingMetadata == null)
                    {
                        newMetaList.Add(newMd);
                    }
                    else
                    {
                        newMetaList.Add(EntitySaver.CreateMergedForSaving(existingMetadata, newMd, SaveOptions) as Entity);
                    }
                }
                ((AttributeDefinition)newAttrib).AddItems(newMetaList);
            }
        }
Пример #2
0
        /// <summary>
        /// Update an entity
        /// </summary>
        /// <param name="id"></param>
        /// <param name="values"></param>
        public void UpdateParts(int id, Dictionary <string, object> values)
        {
            var saveOptions = SaveOptions.Build(_appManager.ZoneId);

            saveOptions.PreserveUntouchedAttributes = true;
            saveOptions.PreserveUnknownLanguages    = true;

            var orig    = _appManager.Cache.List[id];
            var tempEnt = new Entity(_appManager.AppId, 0, "", values);
            var saveEnt = EntitySaver.CreateMergedForSaving(orig, tempEnt, saveOptions);

            Save(saveEnt, saveOptions);
        }
Пример #3
0
        public void TestContravariance()
        {
            ISave <User> saver = new GenericSaver <Entity>();

            ISave <User> userSaver = new EntitySaver();

            var user = new User();

            saver.Save(user);

            #region contravariance delegates
            Action <Entity> entityAction = entity => entity.Name = "123";

            Action <User> userAction = entityAction;
            #endregion
        }
Пример #4
0
        /// <summary>
        /// Import an Entity with all values
        /// </summary>
        private Entity CreateMergedForSaving(Entity update, AppDataPackage appDataPackage, SaveOptions saveOptions)
        {
            #region try to get AttributeSet or otherwise cancel & log error

            var dbAttrSet = appDataPackage.ContentTypes.Values
                            .FirstOrDefault(ct => String.Equals(ct.StaticName, update.Type.StaticName, StringComparison.InvariantCultureIgnoreCase));

            if (dbAttrSet == null) // AttributeSet not Found
            {
                Storage.Log.Add(new LogItem(EventLogEntryType.Error, "ContentType not found for " + update.Type.StaticName));
                return(null);
            }

            #endregion

            // Find existing Enties - meaning both draft and non-draft
            List <IEntity> existingEntities = null;
            if (update.EntityGuid != Guid.Empty)
            {
                existingEntities = appDataPackage.List.Where(e => e.EntityGuid == update.EntityGuid).ToList();
            }

            #region Simplest case - nothing existing to update: return entity

            if (existingEntities == null || !existingEntities.Any())
            {
                return(update);
            }

            #endregion

            Storage.Log.Add(new LogItem(EventLogEntryType.Information, $"FYI: Entity {update.EntityId} already exists for guid {update.EntityGuid}"));

            // now update (main) entity id from existing - since it already exists
            var original = existingEntities.First();
            update.ChangeIdForSaving(original.EntityId);
            return(EntitySaver.CreateMergedForSaving(original, update, saveOptions) as Entity);
        }
Пример #5
0
        private void SaveChangedLists(Dictionary <string, List <int?> > values)
        {
            // ensure that there are never more presentations than values
            if (values.ContainsKey(AppConstants.Presentation))
            {
                var contentCount = Content.Count;
                if (values.ContainsKey(AppConstants.Content))
                {
                    contentCount = values[AppConstants.Content].Count;
                }
                if (values[AppConstants.Presentation].Count > contentCount)
                {
                    throw new Exception("Presentation may not contain more items than Content.");
                }
            }

            // 2017-04-01 2dm centralizing eav access
            var dicObj   = values.ToDictionary(x => x.Key, x => x.Value as object);
            var newEnt   = new Entity(_appId, 0, _contentGroupEntity.Type, dicObj);
            var saveOpts = SaveOptions.Build(_zoneId);

            saveOpts.PreserveUntouchedAttributes = true;

            var saveEnt = new EntitySaver(Log).CreateMergedForSaving(_contentGroupEntity, newEnt, saveOpts);

            if (_versioningEnabled)
            {
                // Force saving as draft if needed (if versioning is enabled)
                ((Entity)saveEnt).PlaceDraftInBranch = true;
                ((Entity)saveEnt).IsPublished        = false;
            }

            new AppManager(_zoneId, _appId).Entities.Save(saveEnt, saveOpts);

            // Refresh content group entity (ensures contentgroup is up to date)
            _contentGroupEntity = new ContentGroupManager(_zoneId, _appId, _showDrafts, _versioningEnabled, Log).GetContentGroup(_contentGroupEntity.EntityGuid)._contentGroupEntity;
        }
        /// <inheritdoc />
        protected override void HandleEvent(SessionStatusChangeEventArgs args)
        {
            //The reason this system is so simple is basically the other threads just need a way to queue up
            //cleanup on the main thread. The reasoning being that GameObject destruction needs to occur
            //as well as collection modification needs to happen, and the main thread is where the majority if collection
            //iteration should be taking place.

            //it's possible that we're attempting to clean up an entity for a connection
            //that doesn't have one. This can happen if they disconnect during claim or before claim.
            if (!ConnectionToEntityMap.ContainsKey(args.Details.ConnectionId))
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"ConnectionId: {args.Details.ConnectionId} had entity exit cleanup but contained no entity. This is not an error.");
                }

                //We may be in this method, handling cleanup for an entity that has a claim going on
                //in the claim handler, but is still awaiting a response for character data from the gameserver. MEANING we could end up with hanging entites.
                //This is not mitgated here, but inside the player entery factory
                //which SHOULD make a check for the connection still being valid AFTER creation
                //Not before because we still want to create, and then deconstruct. Reasoning being that gameserver session
                //will still be claimed unless we go through th cleanup process.
                return;
            }

            NetworkEntityGuid entityGuid = ConnectionToEntityMap[args.Details.ConnectionId];

            //First we need to save the entity data since it DOES own an entity.
            UnityExtended.UnityMainThreadContext.PostAsync(async() =>
            {
                //Nothing should really be taking a write lock, except session entry I guess.
                //This could be bad
                //We no longer do a read lock because Player Entry is actually trying to
                //aquire a write lock and this could block if for a LONG time. KILLING the server basically
                //So, we just assume it's safe to save entity data. Even if it's changing mid save like this.
                //using(await LockingPolicy.ReaderLockAsync(null, CancellationToken.None))
                {
                    //We know that an entity exists, so we must save it. Before we even queue it up for removal.
                    await EntitySaver.SaveAsync(entityGuid)
                    .ConfigureAwait(true);
                }

                //At this point we MUST write lock, since we are actually modifying entity collections and entries
                using (await LockingPolicy.WriterLockAsync(null, CancellationToken.None))                //we can use async await since we're in a async context too!! Which is good.
                {
                    SessionDestructor.Destroy(new PlayerSessionDeconstructionContext(args.Details.ConnectionId));
                }

                //TODO: We have a big problem if this fails, we need to handle it properly. Otherwise the player cannot log in again.\
                ProjectVersionStage.AssertBeta();

                //We need to async send the release request, a very important part of session cleanup.
                //if this failes we have BIG problems. BIG BIG BIG.
                await ZoneClientGameService.ReleaseActiveSession(entityGuid.EntityId)
                .ConfigureAwait(false);

                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"Cleaned up Entity Player Session for ConnectionId: {args.Details.ConnectionId} Guid: {entityGuid} {entityGuid.EntityType}:{entityGuid.EntityId}");
                }
            });
        }