/// <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); }
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); } } }