/// <summary> /// Applies expand for the given <see cref="IQueryable"/>. /// </summary> /// <param name="queryable">The queryable to expand.</param> /// <param name="entityQuery">The entity query containing the expand information.</param> /// <param name="elementType">The element type of the queryable.</param> /// <param name="postExecuteExpandPaths">An output parameter with expand paths that have to be expanded after the query execution.</param> /// <returns>The expanded queryable.</returns> protected virtual IQueryable ApplyExpand(IQueryable queryable, EntityQuery entityQuery, Type elementType, out List <string> postExecuteExpandPaths) { postExecuteExpandPaths = null; if (EntityQuery.ApplyExpand != null) { return(EntityQuery.ApplyExpand(entityQuery, queryable, elementType)); } if (entityQuery.ExpandClause == null) { return(queryable); } if (!_entityMetadataProvider.IsEntityType(elementType)) { throw new InvalidOperationException($"Unknown entity type {elementType}."); } var metadata = _entityMetadataProvider.GetMetadata(elementType); if (!CanApplyQueryExpands(queryable, metadata, entityQuery)) { postExecuteExpandPaths = entityQuery.ExpandClause.PropertyPaths.ToList(); return(queryable); } foreach (var propertyPath in entityQuery.ExpandClause.PropertyPaths) { queryable = ApplyQueryExpand(queryable, propertyPath.Replace('/', '.')); } return(queryable); }
private EntityMetadata GetMetadata(string entityTypeName) { var entityName = BreezeHelper.GetEntityName(entityTypeName); var metadata = _classMetadataProvider.Get(entityName); if (metadata == null) { throw new InvalidOperationException($"Unknown entity name: {entityName}"); } return(_entityMetadataProvider.GetMetadata(metadata.MappedClass)); }
private ModelMetadata GetTypeMetadata(Type type) { if (_entityMetadataProvider.IsEntityType(type)) { return(_entityMetadataProvider.GetMetadata(type)); } if (_clientModelMetadataProvider.IsClientModel(type)) { return(_clientModelMetadataProvider.GetMetadata(type)); } return(null); }
/// <summary> /// Builds <see cref="BreezeMetadata"/>. /// </summary> /// <returns>The breeze metadata.</returns> public BreezeMetadata Build() { var metadata = new BreezeMetadata { StructuralTypes = new List <StructuralType>(), ResourceEntityTypeMap = new Dictionary <string, string>(), EnumTypes = new List <EnumType>(), LocalQueryComparisonOptions = _localQueryComparisonOptions ?? "caseInsensitiveSQL" }; _addedTypes.Clear(); _entityMetadata = _classMetadataProvider.GetAll() .Select(o => o.MappedClass) .Where(o => o != null) .Where(o => _includePredicate?.Invoke(o) ?? true) .Distinct() .Select(o => new { MappedClass = o, Metadata = _entityMetadataProvider.GetMetadata(o) }) .ToDictionary(o => o.MappedClass, o => o.Metadata); foreach (var entityMetadata in _entityMetadata.Values) { AddEntityType(entityMetadata, metadata); } if (_clientModelAssemblies == null) { return(metadata); } // Add client models _clientModelMetadata = _clientModelAssemblies?.SelectMany(assembly => assembly.GetTypes() .Where(t => t.IsClass && !t.IsAbstract && _clientModelMetadataProvider.IsClientModel(t))) .Where(t => _includePredicate?.Invoke(t) ?? true) .Select(o => _clientModelMetadataProvider.GetMetadata(o)) .ToDictionary(o => o.Type, o => o); foreach (var modelMetadata in _clientModelMetadata.Values) { AddClientModelType(modelMetadata, metadata); } return(metadata); }
private static IEnumerable <PropertyInfo> GetProperties(Type instanceType, String propertyPath, IEntityMetadataProvider entityMetadataProvider, ICollection <PropertyInfo> syntheticProperties, bool throwOnError = true) { var propertyNames = propertyPath.Split('.'); var nextInstanceType = instanceType; var nextMetadata = entityMetadataProvider.IsEntityType(nextInstanceType) ? entityMetadataProvider.GetMetadata(instanceType) : null; foreach (var propertyName in propertyNames) { PropertyInfo property; if (nextMetadata != null && nextMetadata.SyntheticForeignKeyProperties.TryGetValue(propertyName, out var syntheticProperty)) { yield return(GetProperty(nextInstanceType, syntheticProperty.AssociationPropertyName, throwOnError)); property = GetProperty(syntheticProperty.EntityType, syntheticProperty.IdentifierPropertyName, throwOnError); syntheticProperties?.Add(property); } else { property = GetProperty(nextInstanceType, propertyName, throwOnError); } if (property != null) { yield return(property); nextInstanceType = property.PropertyType; nextMetadata = entityMetadataProvider.IsEntityType(nextInstanceType) ? entityMetadataProvider.GetMetadata(nextInstanceType) : null; } else { break; } } }
public SaveBundle GetSaveBundle() { var entities = new List <JObject>(); var saveBundle = new SaveBundle { Entities = entities, SaveOptions = new SaveOptions() }; foreach (var pair in _typeEntities) { var session = _sessionProvider.Get(pair.Key); var sessionImpl = session.GetSessionImplementation(); var context = sessionImpl.PersistenceContext; var entityType = pair.Key; var entityTypeInfo = pair.Value; var entityMetadata = entityTypeInfo.EntityMetadata; var persister = entityMetadata.EntityPersister; foreach (var entityInfo in entityTypeInfo.EntitiesInfo.Values) { var entity = entityInfo.Entity; var originalValues = new JObject(); var unmappedValues = new JObject(); var entityAspect = new JObject { ["entityTypeName"] = $"{entityType.Name}:#{entityType.Namespace}", ["originalValuesMap"] = originalValues, ["entityState"] = entityInfo.EntityState.ToString() }; if (entityMetadata.AutoGeneratedKeyType != AutoGeneratedKeyType.None) { var autoGeneratedKey = new JObject { ["propertyName"] = entityMetadata.IdentifierPropertyNames[0], ["autoGeneratedKeyType"] = entityMetadata.AutoGeneratedKeyType.ToString() }; entityAspect["autoGeneratedKey"] = autoGeneratedKey; } var entityData = new JObject(); for (var i = 0; i < entityMetadata.IdentifierPropertyNames.Count; i++) { var idPropertyName = entityMetadata.IdentifierPropertyNames[i]; var idValue = GetToken(entityMetadata.IdentifierPropertyGetters[i](entity)); if (entityMetadata.SyntheticForeignKeyProperties.ContainsKey(idPropertyName)) { unmappedValues.Add(idPropertyName, idValue); } else { entityData.Add(idPropertyName, idValue); } } var propertyTypes = persister.PropertyTypes; for (var i = 0; i < propertyTypes.Length; i++) { var propertyType = propertyTypes[i]; var propertyName = persister.PropertyNames[i]; if (propertyType.IsCollectionType) { continue; } var currentValue = persister.GetPropertyValue(entity, i); if (entityMetadata.Associations.TryGetValue(propertyName, out var association)) { var associatedEntityMetadata = _entityMetadataProvider.GetMetadata(association.EntityType); for (var j = 0; j < association.ForeignKeyPropertyNames.Count; j++) { var fkValue = currentValue != null ? associatedEntityMetadata.IdentifierPropertyGetters[j](currentValue) : null; var fkPropertyName = association.ForeignKeyPropertyNames[j]; if (entityMetadata.SyntheticForeignKeyProperties.ContainsKey(fkPropertyName)) { unmappedValues.Add(fkPropertyName, GetToken(fkValue)); } } continue; } entityData.Add(propertyName, GetToken(currentValue)); } if (context.IsEntryFor(entity)) { var entry = context.GetEntry(entity); var idTypes = entityTypeInfo.IdentifierTypes; for (var i = 0; i < idTypes.Length; i++) { var newId = entityMetadata.IdentifierPropertyGetters[i](entity); if (idTypes[i].IsDirty(entityInfo.IdentifierValues[i], newId, sessionImpl)) { originalValues[entityMetadata.IdentifierPropertyNames[i]] = GetToken(newId); } } for (var i = 0; i < propertyTypes.Length; i++) { var propertyType = propertyTypes[i]; if (propertyType.IsCollectionType) { continue; } var propertyName = persister.PropertyNames[i]; var originalValue = entry.LoadedState[i]; var currentValue = persister.GetPropertyValue(entity, i); if (!propertyTypes[i].IsDirty(originalValue, currentValue, sessionImpl)) { continue; } if (entityMetadata.Associations.TryGetValue(propertyName, out var association)) { foreach (var fkProperty in association.ForeignKeyPropertyNames) { if (entityMetadata.SyntheticForeignKeyProperties.TryGetValue(fkProperty, out var syntheticProperty)) { originalValues[fkProperty] = GetToken(syntheticProperty.GetIdentifierFunction(originalValue)); } } } else { originalValues[propertyName] = GetToken(originalValue); } } } entityData.Add("__unmapped", unmappedValues); entityData.Add("entityAspect", entityAspect); entities.Add(entityData); } } return(saveBundle); }
private ClientModelMetadata Create(Type clientType) { if (!IsClientModel(clientType)) { return(null); } var properties = clientType.GetProperties().ToDictionary(o => o.Name); var syntheticProperties = new List <SyntheticForeignKeyProperty>(); var associations = new Dictionary <string, Association>(); var clientProperties = new List <ClientModelProperty>(properties.Count); foreach (var property in clientType.GetProperties()) { var propertyType = property.PropertyType; if (property.GetCustomAttribute <ComplexTypeAttribute>() != null) { clientProperties.Add(new ClientModelProperty( property.Name, propertyType, true, null, true, false, false, false)); continue; } var isCollection = propertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(propertyType); var elementType = isCollection ? propertyType.GetGenericArguments()[0] : propertyType; var relatedEntityMetadata = _entityMetadataProvider.IsEntityType(elementType) ? _entityMetadataProvider.GetMetadata(elementType) : null; if (relatedEntityMetadata != null || IsClientModel(elementType)) { clientProperties.Add( isCollection // Add a one to many relation ? CreateCollectionNavigationProperty( clientType, property, elementType, relatedEntityMetadata, associations) // Add a many to one relation : CreateEntityNavigationProperty( clientType, property, properties, relatedEntityMetadata, syntheticProperties, associations) ); continue; } clientProperties.Add(new ClientModelProperty( property.Name, propertyType, false, _dataTypeProvider.GetDataType(propertyType), BreezeHelper.IsNullable(propertyType), property.Name == nameof(IClientModel.Id), false, false)); } return(new ClientModelMetadata( clientType, null, // TODO: base type AutoGeneratedKeyType.KeyGenerator, clientProperties, syntheticProperties.ToDictionary(o => o.Name), new List <Type>(), // TODO: base type new List <string>(), // TODO: base type IdentifierPropertyNames, IdentifierPropertyGetters, IdentifierPropertyTypes, IdentifierPropertyDataTypes, IdentifierPropertyTypeLengths, new HashSet <string>(associations.Values.Where(o => o.IsScalar).SelectMany(o => o.ForeignKeyPropertyNames)), associations )); }
public override IEnumerable <Validator> GetValidators(DataProperty dataProperty, Type type) { Validator validator; var addedValidators = new HashSet <string>(); if (!dataProperty.IsNullable) { ModelMetadata modelMetadata = null; if (_entityMetadataProvider.IsEntityType(type)) { modelMetadata = _entityMetadataProvider.GetMetadata(type); } else if (_clientModelMetadataProvider.IsClientModel(type)) { modelMetadata = _clientModelMetadataProvider.GetMetadata(type); } // Do not permit default values for foreign key properties if (modelMetadata?.ForeignKeyPropertyNames.Contains(dataProperty.NameOnServer) == true || dataProperty.DataType == DataType.String) { addedValidators.Add("fvNotEmpty"); validator = new Validator("fvNotEmpty"); validator.MergeLeft(FluentValidators.GetParameters(new NotEmptyValidator(null))); yield return(validator); } else { addedValidators.Add("fvNotNull"); validator = new Validator("fvNotNull"); validator.MergeLeft(FluentValidators.GetParameters(new NotNullValidator())); yield return(validator); } } if (dataProperty.MaxLength.HasValue) { addedValidators.Add("fvLength"); validator = new Validator("fvLength"); validator.MergeLeft(FluentValidators.GetParameters(new LengthValidator(0, dataProperty.MaxLength.Value))); yield return(validator); } if (dataProperty.DataType.HasValue && TryGetDataTypeValidator(dataProperty.DataType.Value, out validator)) { yield return(validator); } if (!_typePropertyValidators.TryGetValue(type, out var propertyValidators)) { if (!(_validatorFactory.GetValidator(type) is IEnumerable <IValidationRule> validationRules)) { yield break; } propertyValidators = validationRules.OfType <PropertyRule>().Where(IsRuleSupported).ToLookup(o => o.PropertyName); _typePropertyValidators.Add(type, propertyValidators); } // Add fluent validations foreach (var propertyRule in propertyValidators[dataProperty.NameOnServer]) { var currentValidator = propertyRule.CurrentValidator; var name = FluentValidators.GetName(currentValidator); if (string.IsNullOrEmpty(name) || addedValidators.Contains(name)) { continue; } validator = new Validator(name); validator.MergeLeft(FluentValidators.GetParameters(currentValidator)); yield return(validator); } }