/// <summary>
        /// Build a segment to predicate mapper
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        public virtual IRelativeRouteToPredicateMapper BuildMapper(PropertyInfo propertyInfo)
        {
            if (propertyInfo.PropertyType == typeof(DateTime))
            {
                return(new RouteDateSegmentAttribute.DateUrlSegmentMapper(DateSegmentFormat.YearMonthDay));
            }

            if (propertyInfo.GetCustomAttributes <ForeignKeyAttribute>().Any())
            {
                var foreignKeyInfo = DataReferenceFacade.GetForeignKeyProperties(propertyInfo.DeclaringType)
                                     .FirstOrDefault(p => p.SourcePropertyName == propertyInfo.Name);

                if (foreignKeyInfo != null)
                {
                    var targetType     = foreignKeyInfo.TargetType;
                    var dataTypeMapper = AttributeBasedRoutingHelper.GetPredicateMapper(targetType);
                    if (dataTypeMapper != null)
                    {
                        var typeConst = typeof(DataReferenceRelativeRouteToPredicateMapper <,>)
                                        .MakeGenericType(targetType, foreignKeyInfo.SourcePropertyInfo.PropertyType)
                                        .GetConstructors().Single();

                        return((IRelativeRouteToPredicateMapper)typeConst.Invoke(new object[] { dataTypeMapper }));
                    }
                }
            }

            var type        = typeof(DefaultRelativeRouteToPredicateMapper <>).MakeGenericType(propertyInfo.PropertyType);
            var constructor = type.GetConstructor(new Type[0]);

            return(constructor.Invoke(null) as IRelativeRouteToPredicateMapper);
        }
Пример #2
0
        private void Delete <T>(IEnumerable <T> dataset, bool suppressEventing, CascadeDeleteType cascadeDeleteType, bool referencesFromAllScopes, HashSet <DataSourceId> dataPendingDeletion)
            where T : class, IData
        {
            Verify.ArgumentNotNull(dataset, nameof(dataset));

            dataset = dataset.Evaluate();

            foreach (var data in dataset)
            {
                var dataSourceId = data.DataSourceId;
                if (!dataPendingDeletion.Contains(dataSourceId))
                {
                    dataPendingDeletion.Add(dataSourceId);
                }
            }

            if (cascadeDeleteType != CascadeDeleteType.Disable)
            {
                foreach (IData data in dataset)
                {
                    Verify.ArgumentCondition(data != null, nameof(dataset), "dataset may not contain nulls");

                    Type interfaceType = data.DataSourceId.InterfaceType;

                    // Not deleting references if the data is versioned and not all of the
                    // versions of the element are to be deleted
                    if (data is IVersioned && interfaceType.GetKeyProperties().Count == 1)
                    {
                        var key      = data.GetUniqueKey();
                        var versions = DataFacade.TryGetDataVersionsByUniqueKey(interfaceType, key).ToList();

                        if (versions.Count > 1 &&
                            (dataset.Count() < versions.Count ||
                             !versions.All(v => dataPendingDeletion.Contains(v.DataSourceId))))
                        {
                            continue;
                        }
                    }

                    using (new DataScope(data.DataSourceId.DataScopeIdentifier))
                    {
                        var allReferences = DataReferenceFacade.GetRefereesInt(data, referencesFromAllScopes, (a, b) => true);

                        if (allReferences.Count == 0)
                        {
                            continue;
                        }

                        Verify.IsTrue(cascadeDeleteType != CascadeDeleteType.Disallow, "One of the given datas is referenced by one or more datas");

                        var optionalReferences    = allReferences.Where(kvp => kvp.Item2.IsOptionalReference);
                        var notOptionalReferences = allReferences.Where(kvp => !kvp.Item2.IsOptionalReference &&
                                                                        !dataPendingDeletion.Contains(kvp.Item1.DataSourceId)).Evaluate();

                        foreach (var reference in optionalReferences)
                        {
                            var referee = reference.Item1;
                            reference.Item2.SourcePropertyInfo.SetValue(referee, null, null);
                            DataFacade.Update(referee, false, true, false);
                        }

                        foreach (var refereeInfo in notOptionalReferences)
                        {
                            if (!refereeInfo.Item2.AllowCascadeDeletes)
                            {
                                throw new InvalidOperationException("One of the given data items is referenced by one or more data items that do not allow cascade delete.");
                            }
                        }

                        var toDelete = notOptionalReferences.Select(_ => _.Item1);
                        Delete <IData>(toDelete, suppressEventing, cascadeDeleteType, referencesFromAllScopes);
                    }
                }
            }


            Dictionary <string, Dictionary <Type, List <IData> > > sortedDatas = dataset.ToDataProviderAndInterfaceTypeSortedDictionary();

            foreach (KeyValuePair <string, Dictionary <Type, List <IData> > > providerPair in sortedDatas)
            {
                foreach (KeyValuePair <Type, List <IData> > interfaceTypePair in providerPair.Value)
                {
                    DataProviderPluginFacade.Delete(providerPair.Key, interfaceTypePair.Value.Select(d => d.DataSourceId));

                    if (DataCachingFacade.IsTypeCacheable(interfaceTypePair.Key))
                    {
                        DataCachingFacade.RemoveFromCache(interfaceTypePair.Value);
                    }
                }
            }


            if (!suppressEventing)
            {
                foreach (IData element in dataset)
                {
                    DataEventSystemFacade.FireDataDeletedEvent(element.DataSourceId.InterfaceType, element);
                }
            }
        }