protected static Entity create(EntityClass parent, entitySpec entitySpec, Type type, Action <string> log, bool throwOnCircularReference) { log?.Invoke($"create: {type.Name} - {entitySpec.name}"); if (!string.IsNullOrEmpty(entitySpec.aggregation)) { return(new EntityAggregation(entitySpec, log)); } if (!string.IsNullOrEmpty(entitySpec.formula)) { return(new EntityFormula(entitySpec, log)); } var fieldInfo = new LinkedFieldInfo(type, entitySpec.name); if (fieldInfo.IEnumerable != null) { return(new EntityClass(parent, entitySpec, fieldInfo.IEnumerable.GetGenericArguments()[0], fieldInfo, log, throwOnCircularReference)); } if (!entitySpec.AnyNotStar()) { return(new EntityPlainField(entitySpec, fieldInfo, log)); } throw new Exception("Unknown error"); }
public EntityPlainField(entitySpec entitySpec, LinkedFieldInfo fieldInfo, Action <string> log) : base(entitySpec) { log?.Invoke($"EntityPlainField ctor: {entitySpec.name}/{entitySpec.fields?.Count ?? 0} - {fieldInfo.FieldType} "); FieldInfo = fieldInfo; FieldType = FieldInfo.FieldType; }
public entitySpec Add(entitySpec entitySpec) { if (fields == null) { fields = new List <entitySpec>(); } fields.Add(entitySpec); return(this); }
public DataExtract(Type type, entitySpec entitySpec, ITableManager tableManager = null, Action <string> log = null) { if (type == null) { throw new NullReferenceException(nameof(type)); } if (entitySpec == null) { throw new NullReferenceException(nameof(entitySpec)); } Type = type; TopEntity = Entity.Create(null, entitySpec, Type, log); TableManager = tableManager ?? new InMemoryTableManager(); }
public static EntityClass Create(EntityClass parent, entitySpec entitySpec, Type type, Action <string> log, bool throwOnCircularReference = true) { return(new EntityClass( parent, new entitySpec { name = entitySpec.name ?? type.Name, externalname = entitySpec.externalname, fields = entitySpec.fields, where = entitySpec.where }, type, null, log, throwOnCircularReference)); }
public EntityAggregation(entitySpec entitySpec, Action <string> log) : base(entitySpec) { if (string.IsNullOrEmpty(entitySpec.aggregationtype)) { AggregationType = AggregationType.Sum; } else { AggregationType = (AggregationType)Enum.Parse(typeof(AggregationType), entitySpec.aggregationtype, true); } if (string.IsNullOrEmpty(entitySpec.formula)) { return; } _evaluator = new EvaluateRpn(new Rpn(entitySpec.formula), new List <NameAndType> { new NameAndType("@", typeof(double)) }); }
public EntityClass( EntityClass parent, entitySpec entitySpec, Type type, LinkedFieldInfo fieldInfo, Action <string> log, bool throwOnCircularReference) : base(entitySpec) { log?.Invoke( $"EntityClass ctor: {entitySpec.name}/{entitySpec.fields?.Count ?? 0} - {type?.Name} - {fieldInfo?.FieldType} - {fieldInfo?.IEnumerable?.Name}"); TableName = parent != null && Spec.externalname == null ? string.Join("_", parent.TableName, ExternalName) : ExternalName; FieldInfo = fieldInfo; FieldType = fieldInfo?.FieldType; if (!Spec.Any() || isStarExpansionAndNoRealSubProperties(type)) { // not sure if this should be allowed... Fields.Add(new EntitySolitaire(type)); } breakDownSubEntities(type, log, throwOnCircularReference); // move the nosave fields to always be at the end of the list var noSaveFields = Fields.Where(_ => _.NoSave).ToList(); Fields.RemoveAll(_ => _.NoSave); SaveableFieldCount = Fields.Count; Fields.AddRange(noSaveFields); // this is temporary - to be able to serialze a contract with "*" since it was digging up so much garbage... // need to investigae each "garbage" occurrence and handle it more elegantly Fields.RemoveAll(_ => _ is EntityPlainField && SqlHelpers.Field2Sql(_.NameAndType.Name, _.NameAndType.Type, false, 0, true) == null); Lists.RemoveAll(_ => !_.Fields.Any() && !_.Lists.Any()); if (Fields.Count(_ => _.Spec.primarykey) > 1) { throw new Exception("There may be no more than one primary key field"); } PrimaryKeyIndex = Fields.FindIndex(_ => _.Spec.primarykey); EffectiveFieldCount = Fields.Count + 1; for (var fi = 0; fi < Fields.Count; fi++) { Fields[fi].ParentInitialized(this, fi); } for (var li = 0; li < Lists.Count; li++) { Lists[li].ParentInitialized(this, li); } for (var i = 0; i < Fields.Count; i++) { Fields[i].ResultSetIndex = i; } var fieldsThenFormulas = Fields.Where(_ => !(_ is EntityAggregation)).ToList(); SortWithFormulasLast(fieldsThenFormulas); _fieldsThenNonAggregatedFormulas = fieldsThenFormulas.Where(_ => !_.IsBasedOnAggregation).ToArray(); _aggregatedFormulas = fieldsThenFormulas.Where(_ => _.IsBasedOnAggregation).ToArray(); if (!string.IsNullOrEmpty(Spec.where)) { _whereClause = new WhereClause(Spec.where, Fields, _fieldsThenNonAggregatedFormulas); } if (PrimaryKeyIndex >= 0 && Fields[PrimaryKeyIndex].IsBasedOnAggregation) { throw new Exception($"The primary key must not be based on an aggregation (table '{TableName}')"); } }
private static IEnumerable <Entity> expansionOverStar( Action <string> log, EntityClass parent, Type masterType, entitySpec subEntitySpec, HashSet <Type> detectCircularRef, bool throwOnCircularReference, string prefix = "", Type subType = null) { if (subEntitySpec.name != "*") { yield return(create(parent, subEntitySpec, masterType, log, throwOnCircularReference)); yield break; } subType = subType ?? masterType; if (detectCircularRef.Contains(subType)) { if (throwOnCircularReference) { throw new Exception("Circular reference detected while processing inclusion of all fields ('*')"); } else { yield return(new EntityClass(parent, entitySpec.Begin(prefix.TrimEnd(".".ToCharArray())), masterType, null, log, true)); yield break; } } detectCircularRef.Add(subType); foreach (var nameAndType in LinkedFieldInfo.GetAllFieldsAndProperties(subType)) { if (nameAndType.Type == typeof(object)) { continue; } var spec = entitySpec.Begin(prefix + nameAndType.Name); var subProperties = LinkedFieldInfo.GetAllFieldsAndProperties(nameAndType.Type); if (LinkedFieldInfo.CheckForIEnumerable(nameAndType.Type) != null) { spec.Add("*"); yield return(create(parent, spec, masterType, log, throwOnCircularReference)); } else if (!subProperties.Any()) { yield return(create(parent, spec, masterType, log, throwOnCircularReference)); } foreach (var liftedSubProperty in subProperties) { if (liftedSubProperty.Type == typeof(object)) { continue; } var propName = $"{prefix}{nameAndType.Name}.{liftedSubProperty.Name}"; if (LinkedFieldInfo.GetAllFieldsAndProperties(liftedSubProperty.Type).Any()) { foreach (var q in expansionOverStar(log, parent, masterType, "*", detectCircularRef, throwOnCircularReference, propName + ".", liftedSubProperty.Type)) { yield return(q); } } else { yield return(create(parent, entitySpec.Begin(propName).Add("*"), masterType, log, throwOnCircularReference)); } //yield return create(propName, masterType, log); } } detectCircularRef.Remove(subType); }
public EntityFormula(entitySpec entitySpec, Action <string> log) : base(entitySpec) { log?.Invoke($"EntityFormula ctor: {entitySpec.name}/{entitySpec.fields?.Count ?? 0} - {entitySpec.formula} "); }
protected Entity(entitySpec entitySpec) { Spec = entitySpec; NoSave = entitySpec.nosave; }