示例#1
0
 /// <summary>
 /// Extended constructor when also storing the persistance ID-Info
 /// </summary>
 public AttributeDefinition(int appId, string name, string type, bool isTitle, int attributeId, int sortOrder, IDeferredEntitiesList metaSource = null) : base(name, type)
 {
     AppId          = appId;
     IsTitle        = isTitle;
     AttributeId    = attributeId;
     SortOrder      = sortOrder;
     metadataSource = metaSource;
 }
        /// <summary>Get Data to populate ICache</summary>
        /// <param name="entityIds">null or a List of EntitiIds</param>
        /// <param name="appId">AppId (can be different than the appId on current context (e.g. if something is needed from the default appId, like MetaData)</param>
        /// <param name="source">DataSource to get child entities</param>
        /// <param name="entitiesOnly">If only the CachItem.Entities is needed, this can be set to true to imporove performance</param>
        /// <returns>Item1: EntityModels, Item2: all ContentTypes, Item3: Assignment Object Types</returns>
        internal AppDataPackage GetAppDataPackage(int[] entityIds, int appId, IDeferredEntitiesList source, bool entitiesOnly = false)
        {
            var contentTypes = GetEavContentTypes(appId);

            var metadataForGuid = new Dictionary<int, Dictionary<Guid, IEnumerable<IEntity>>>();
            var metadataForNumber = new Dictionary<int, Dictionary<int, IEnumerable<IEntity>>>();
            var metadataForString = new Dictionary<int, Dictionary<string, IEnumerable<IEntity>>>();

            var relationships = new List<EntityRelationshipItem>();

            #region Prepare & Extend EntityIds
            if (entityIds == null)
                entityIds = new int[0];

            var filterByEntityIds = entityIds.Any();

            // Ensure published Versions of Drafts are also loaded (if filtered by EntityId, otherwise all Entities from the app are loaded anyway)
            if (filterByEntityIds)
                entityIds = entityIds.Union(from e in Context.SqlDb.Entities
                                            where e.PublishedEntityId.HasValue && !e.IsPublished && entityIds.Contains(e.EntityID) && !entityIds.Contains(e.PublishedEntityId.Value) && e.ChangeLogDeleted == null
                                            select e.PublishedEntityId.Value).ToArray();
            #endregion

            #region Get Entities with Attribute-Values from Database

            var entitiesWithAandVfromDb = from e in Context.SqlDb.Entities
                                 where
                                     !e.ChangeLogIDDeleted.HasValue &&
                                     e.Set.AppID == appId &&
                                     e.Set.ChangeLogIDDeleted == null &&
                                     (	// filter by EntityIds (if set)
                                         !filterByEntityIds ||
                                         entityIds.Contains(e.EntityID) ||
                                         (e.PublishedEntityId.HasValue && entityIds.Contains(e.PublishedEntityId.Value))	// also load Drafts
                                         )
                                 orderby
                                     e.EntityID	// guarantees Published appear before draft
                                 select new
                                 {
                                     e.EntityID,
                                     e.EntityGUID,
                                     e.AttributeSetID,
                                     Metadata = new Metadata
                                     {
                                         TargetType = e.AssignmentObjectTypeID,
                                         KeyGuid = e.KeyGuid,
                                         KeyNumber = e.KeyNumber,
                                         KeyString = e.KeyString
                                     },
                                     e.IsPublished,
                                     e.PublishedEntityId,
                                     e.Owner, // new 2016-03-01
                                     Modified = e.ChangeLogModified.Timestamp,
                                     RelatedEntities = from r in e.EntityParentRelationships
                                                       group r by r.AttributeID
                                                           into rg
                                                           select new
                                                           {
                                                               AttributeID = rg.Key,
                                                               Childs = rg.OrderBy(c => c.SortOrder).Select(c => c.ChildEntityID)
                                                           },
                                     Attributes = from v in e.Values
                                                  where !v.ChangeLogIDDeleted.HasValue
                                                  group v by v.AttributeID
                                                      into vg
                                                      select new
                                                      {
                                                          AttributeID = vg.Key,
                                                          Values = from v2 in vg
                                                                   orderby v2.ChangeLogIDCreated
                                                                   select new
                                                                   {
                                                                       v2.ValueID,
                                                                       v2.Value,
                                                                       Languages = from l in v2.ValuesDimensions
                                                                                   select new Data.Dimension
                                                                                   {
                                                                                       DimensionId = l.DimensionID,
                                                                                       ReadOnly = l.ReadOnly,
                                                                                       Key = l.Dimension.ExternalKey.ToLower()
                                                                                   },
                                                                       v2.ChangeLogIDCreated
                                                                   }
                                                      }
                                 };
            #endregion

            #region Build EntityModels
            var entities = new Dictionary<int, IEntity>();
            var entList = new List<IEntity>();

            foreach (var e in entitiesWithAandVfromDb)
            {
                var contentType = (ContentType)contentTypes[e.AttributeSetID];
                var newEntity = new Data.Entity(e.EntityGUID, e.EntityID, e.EntityID, e.Metadata /* e.AssignmentObjectTypeID */, contentType, e.IsPublished, relationships, e.Modified, e.Owner);

                var allAttribsOfThisType = new Dictionary<int, IAttributeManagement>();	// temporary Dictionary to set values later more performant by Dictionary-Key (AttributeId)
                IAttributeManagement titleAttrib = null;

                // Add all Attributes from that Content-Type
                foreach (var definition in contentType.AttributeDefinitions.Values)
                {
                    var newAttribute = AttributeHelperTools.GetAttributeManagementModel(definition);
                    newEntity.Attributes.Add(((IAttributeBase)newAttribute).Name, newAttribute);
                    allAttribsOfThisType.Add(definition.AttributeId, newAttribute);
                    if (newAttribute.IsTitle)
                        titleAttrib = newAttribute;
                }

                // If entity is a draft, add references to Published Entity
                if (!e.IsPublished && e.PublishedEntityId.HasValue)
                {
                    // Published Entity is already in the Entities-List as EntityIds is validated/extended before and Draft-EntityID is always higher as Published EntityId
                    newEntity.PublishedEntity = entities[e.PublishedEntityId.Value];
                    ((Data.Entity)newEntity.PublishedEntity).DraftEntity = newEntity;
                    newEntity.EntityId = e.PublishedEntityId.Value;
                }

                #region Add metadata-lists based on AssignmentObjectTypes

                // unclear why #1 is handled in a special way - why should this not be cached? I believe 1 means no specific assignment
                if (e.Metadata.HasMetadata && !entitiesOnly)
                {
                    // Try guid first. Note that an item can be assigned to both a guid, string and an int if necessary, though not commonly used
                    if (e.Metadata.KeyGuid.HasValue)
                    {
                        // Ensure that this assignment-Type (like 4 = entity-assignment) already has a dictionary for storage
                        if (!metadataForGuid.ContainsKey(e.Metadata.TargetType)) // ensure AssignmentObjectTypeID
                            metadataForGuid.Add(e.Metadata.TargetType, new Dictionary<Guid, IEnumerable<IEntity>>());

                        // Ensure that the assignment type (like 4) the target guid (like a350320-3502-afg0-...) has an empty list of items
                        if (!metadataForGuid[e.Metadata.TargetType].ContainsKey(e.Metadata.KeyGuid.Value)) // ensure Guid
                            metadataForGuid[e.Metadata.TargetType][e.Metadata.KeyGuid.Value] = new List<IEntity>();

                        // Now all containers must exist, add this item
                        ((List<IEntity>)metadataForGuid[e.Metadata.TargetType][e.Metadata.KeyGuid.Value]).Add(newEntity);
                    }
                    if (e.Metadata.KeyNumber.HasValue)
                    {
                        if (!metadataForNumber.ContainsKey(e.Metadata.TargetType)) // ensure AssignmentObjectTypeID
                            metadataForNumber.Add(e.Metadata.TargetType, new Dictionary<int, IEnumerable<IEntity>>());

                        if (!metadataForNumber[e.Metadata.TargetType].ContainsKey(e.Metadata.KeyNumber.Value)) // ensure Guid
                            metadataForNumber[e.Metadata.TargetType][e.Metadata.KeyNumber.Value] = new List<IEntity>();

                        ((List<IEntity>)metadataForNumber[e.Metadata.TargetType][e.Metadata.KeyNumber.Value]).Add(newEntity);
                    }
                    if (!string.IsNullOrEmpty(e.Metadata.KeyString))
                    {
                        if (!metadataForString.ContainsKey(e.Metadata.TargetType)) // ensure AssignmentObjectTypeID
                            metadataForString.Add(e.Metadata.TargetType, new Dictionary<string, IEnumerable<IEntity>>());

                        if (!metadataForString[e.Metadata.TargetType].ContainsKey(e.Metadata.KeyString)) // ensure Guid
                            metadataForString[e.Metadata.TargetType][e.Metadata.KeyString] = new List<IEntity>();

                        ((List<IEntity>)metadataForString[e.Metadata.TargetType][e.Metadata.KeyString]).Add(newEntity);
                    }
                }

                #endregion

                #region add Related-Entities Attributes
                foreach (var r in e.RelatedEntities)
                {
                    var attributeModel = allAttribsOfThisType[r.AttributeID];
                    var valueModel = Value.GetValueModel(((IAttributeBase)attributeModel).Type, r.Childs, source);
                    var valuesModelList = new List<IValue> { valueModel };
                    attributeModel.Values = valuesModelList;
                    attributeModel.DefaultValue = (IValueManagement)valuesModelList.FirstOrDefault();
                }
                #endregion

                #region Add "normal" Attributes (that are not Entity-Relations)
                foreach (var a in e.Attributes)
                {
                    IAttributeManagement attributeModel;
                    try
                    {
                        attributeModel = allAttribsOfThisType[a.AttributeID];
                    }
                    catch (KeyNotFoundException)
                    {
                        continue;
                    }
                    if (attributeModel.IsTitle)
                        newEntity.Title = attributeModel;
                    var valuesModelList = new List<IValue>();

                    #region Add all Values
                    foreach (var v in a.Values)
                    {
                        var valueModel = Value.GetValueModel(((IAttributeBase)attributeModel).Type, v.Value, v.Languages, v.ValueID, v.ChangeLogIDCreated);
                        valuesModelList.Add(valueModel);
                    }
                    #endregion

                    attributeModel.Values = valuesModelList;
                    attributeModel.DefaultValue = (IValueManagement)valuesModelList.FirstOrDefault();
                }

                // Special treatment in case there is no title - sometimes happens if the title-field is re-defined and ol data might no have this
                //if(newEntity.Title == null)
                //    newEntity.Title = titleAttrib;
                #endregion

                entities.Add(e.EntityID, newEntity);
                entList.Add(newEntity);
            }
            #endregion

            #region Populate Entity-Relationships (after all EntityModels are created)
            var relationshipsRaw = from r in Context.SqlDb.EntityRelationships
                                   where r.Attribute.AttributesInSets.Any(s => s.Set.AppID == appId && (!filterByEntityIds || (!r.ChildEntityID.HasValue || entityIds.Contains(r.ChildEntityID.Value)) || entityIds.Contains(r.ParentEntityID)))
                                   orderby r.ParentEntityID, r.AttributeID, r.ChildEntityID
                                   select new { r.ParentEntityID, r.Attribute.StaticName, r.ChildEntityID };
            foreach (var relationship in relationshipsRaw)
            {
                try
                {
                    if(entities.ContainsKey(relationship.ParentEntityID) && (!relationship.ChildEntityID.HasValue || entities.ContainsKey(relationship.ChildEntityID.Value)))
                        relationships.Add(new EntityRelationshipItem(entities[relationship.ParentEntityID], relationship.ChildEntityID.HasValue ? entities[relationship.ChildEntityID.Value] : null));
                }
                catch (KeyNotFoundException) { } // may occour if not all entities are loaded - edited 2rm 2015-09-29: Should not occur anymore
            }
            #endregion

            return new AppDataPackage(entities, entList, contentTypes, metadataForGuid, metadataForNumber, metadataForString, relationships);
        }
示例#3
0
 /// <summary>
 /// Initializes a new instance of the EntityRelationship class.
 /// </summary>
 /// <param name="fullEntitiesListForLookup">DataSource to retrieve child entities</param>
 /// <param name="entityIds">List of IDs to initialize with</param>
 public EntityRelationship(IDeferredEntitiesList fullEntitiesListForLookup, IEnumerable <int?> entityIds = null)
 {
     EntityIds       = entityIds ?? EntityIdsEmpty;
     _fullEntityList = fullEntitiesListForLookup;
 }
示例#4
0
 public AppDataPackage GetDataForCache(IDeferredEntitiesList targetCacheForDeferredLookups)
 {
     return new DbLoadIntoEavDataStructure(Context).GetAppDataPackage(null, AppId, targetCacheForDeferredLookups);
 }
示例#5
0
        /// <summary>
        /// Creates a Typed Value Model
        /// </summary>
        public static IValue Build(string attributeType, object value, List <ILanguage> languages, IDeferredEntitiesList fullEntityListForLookup = null)
        {
            if (languages == null)
            {
                languages = new List <ILanguage>();
            }
            Value typedModel;
            var   stringValue = value as string;

            try
            {
                var type = (AttributeTypeEnum)Enum.Parse(typeof(AttributeTypeEnum), attributeType);
                switch (type)
                {
                case AttributeTypeEnum.Boolean:
                    bool typedBoolean;
                    typedModel = new Value <bool?>(value as bool? ?? (bool.TryParse(stringValue, out typedBoolean)
                            ? typedBoolean
                            : new bool?()));
                    break;

                case AttributeTypeEnum.DateTime:
                    DateTime typedDateTime;
                    typedModel = new Value <DateTime?>(value as DateTime? ?? (DateTime.TryParse(stringValue, CultureInfo.InvariantCulture,
                                                                                                DateTimeStyles.None, out typedDateTime)
                                                     ? typedDateTime
                                                     : new DateTime?()));
                    break;

                case AttributeTypeEnum.Number:
                    decimal?newDec = null;
                    if (!(value is string && string.IsNullOrEmpty(value as string)))     // only try converting if it's not an empty string
                    {
                        try
                        {
                            newDec = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
                        }
                        catch
                        {
                            // ignored
                        }

                        // if it's still blank, try another method
                        // note: 2dm added this 2017-08-29 after a few bugs, but it may not be necessary any more, as the bug was something else
                        if (newDec == null)
                        {
                            try
                            {
                                if (decimal.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal typedDecimal))
                                {
                                    newDec = typedDecimal;
                                }
                            }
                            catch
                            {
                                // ignored
                            }
                        }
                    }
                    typedModel = new Value <decimal?>(newDec);
                    break;

                case AttributeTypeEnum.Entity:
                    var entityIds = value as IEnumerable <int?> ?? (value as IEnumerable <int>)?.Select(x => (int?)x).ToList();
                    if (entityIds != null)
                    {
                        typedModel = new Value <EntityRelationship>(new EntityRelationship(fullEntityListForLookup, entityIds));
                    }
                    else if (value is EntityRelationship)
                    {
                        typedModel = new Value <EntityRelationship>(new EntityRelationship(fullEntityListForLookup, ((EntityRelationship)value).EntityIds));
                    }
                    else
                    {
                        var entityIdEnum = value as IEnumerable;     // note: strings are also enum!
                        if (value is string && !String.IsNullOrEmpty(stringValue))
                        {
                            entityIdEnum = stringValue.Split(',').ToList();
                        }
                        // this is the case when we get a CSV-string with GUIDs
                        var entityGuids = entityIdEnum?.Cast <object>().Select(x =>
                        {
                            var v = x?.ToString().Trim();
                            // this is the case when an export contains a list with nulls as a special code
                            if (v == null || v == Constants.EmptyRelationship)
                            {
                                return(new Guid?());
                            }
                            var guid = Guid.Parse(v);
                            return(guid == Guid.Empty ? new Guid?() : guid);
                        }).ToList() ?? new List <Guid?>(0);
                        typedModel = new Value <List <Guid?> >(entityGuids);
                    }
                    break;

                // ReSharper disable RedundantCaseLabel
                case AttributeTypeEnum.String:      // most common case
                case AttributeTypeEnum.Empty:       // empty - should actually not contain anything!
                case AttributeTypeEnum.Custom:      // custom value, currently just parsed as string for manual processing as needed
                case AttributeTypeEnum.Hyperlink:   // special case, handled as string
                case AttributeTypeEnum.Undefined:   // backup case, where it's not known...
                // ReSharper restore RedundantCaseLabel
                default:
                    typedModel = new Value <string>(stringValue);
                    break;
                }
            }
            catch
            {
                typedModel = new Value <string>(stringValue);
            }

            typedModel.Languages = languages;

            return((IValue)typedModel);
        }