public string OriginExpression(string propertyName, OriginAttribute origin, DialectExpressionSelector expressionSelector, string aliasPrefix, List <Attribute> extraJoins) { if (aliasPrefix.Length >= 1000) { throw new DivideByZeroException("Infinite origin recursion detected!"); } var org = GetOriginProperty(propertyName); var originProperty = org.Item1; if (aliasPrefix.Length == 0) { aliasPrefix = origin.Join; } else { aliasPrefix = aliasPrefix + "_" + origin.Join; } var columnAttr = originProperty.GetCustomAttribute <ColumnAttribute>(); if (columnAttr != null) { return(aliasPrefix + "." + SqlSyntax.AutoBracket(columnAttr.Name)); } else { var originDictionary = GetPropertyDictionary(org.Item2); var expressionAttr = originProperty.GetCustomAttributes <ExpressionAttribute>(); if (expressionAttr.Any()) { var expression = expressionSelector.GetBestMatch(expressionAttr, x => x.Dialect); return(originDictionary.PrefixAliases(expression.Value, aliasPrefix, expressionSelector, extraJoins)); } else { var originOrigin = originProperty.GetCustomAttribute <OriginAttribute>(); if (originOrigin != null) { originDictionary.PrefixAliases(originOrigin.Join + ".Dummy", aliasPrefix, expressionSelector, extraJoins); return(originDictionary.OriginExpression(originProperty.Name, originOrigin, expressionSelector, aliasPrefix, extraJoins)); } else { return(aliasPrefix + "." + SqlSyntax.AutoBracket(originProperty.Name)); } } } }
public void Initialize() { if (isInitialized) { return; } lock (this.initializeLock) { Dictionary <string, FieldInfo> rowFields; Dictionary <string, IPropertyInfo> rowProperties; GetRowFieldsAndProperties(out rowFields, out rowProperties); var expressionSelector = new DialectExpressionSelector(connectionKey); var rowCustomAttributes = this.rowType.GetCustomAttributes().ToList(); foreach (var fieldInfo in this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)) { if (fieldInfo.FieldType.IsSubclassOf(typeof(Field))) { var field = (Field)fieldInfo.GetValue(this); IPropertyInfo property; if (!rowProperties.TryGetValue(fieldInfo.Name, out property)) { property = null; } ColumnAttribute column = null; DisplayNameAttribute display = null; SizeAttribute size = null; ExpressionAttribute expression = null; ScaleAttribute scale = null; MinSelectLevelAttribute selectLevel = null; ForeignKeyAttribute foreignKey = null; LeftJoinAttribute leftJoin = null; InnerJoinAttribute innerJoin = null; DefaultValueAttribute defaultValue = null; TextualFieldAttribute textualField = null; DateTimeKindAttribute dateTimeKind = null; PermissionAttributeBase readPermission = null; PermissionAttributeBase insertPermission = null; PermissionAttributeBase updatePermission = null; FieldFlags addFlags = (FieldFlags)0; FieldFlags removeFlags = (FieldFlags)0; OriginPropertyDictionary propertyDictionary = null; if (property != null) { var origin = property.GetAttribute <OriginAttribute>(); column = property.GetAttribute <ColumnAttribute>(); display = property.GetAttribute <DisplayNameAttribute>(); size = property.GetAttribute <SizeAttribute>(); var expressions = property.GetAttributes <ExpressionAttribute>(); if (expressions.Any()) { expression = expressionSelector.GetBestMatch(expressions, x => x.Dialect); } scale = property.GetAttribute <ScaleAttribute>(); selectLevel = property.GetAttribute <MinSelectLevelAttribute>(); foreignKey = property.GetAttribute <ForeignKeyAttribute>(); leftJoin = property.GetAttributes <LeftJoinAttribute>() .FirstOrDefault(x => x.ToTable == null && x.OnCriteria == null); innerJoin = property.GetAttributes <InnerJoinAttribute>() .FirstOrDefault(x => x.ToTable == null && x.OnCriteria == null); defaultValue = property.GetAttribute <DefaultValueAttribute>(); textualField = property.GetAttribute <TextualFieldAttribute>(); dateTimeKind = property.GetAttribute <DateTimeKindAttribute>(); readPermission = property.GetAttribute <ReadPermissionAttribute>(); insertPermission = property.GetAttribute <InsertPermissionAttribute>() ?? property.GetAttribute <ModifyPermissionAttribute>() ?? readPermission; updatePermission = property.GetAttribute <UpdatePermissionAttribute>() ?? property.GetAttribute <ModifyPermissionAttribute>() ?? readPermission; if (origin != null) { propertyDictionary = propertyDictionary ?? OriginPropertyDictionary.GetPropertyDictionary(this.rowType); try { if (!expressions.Any() && expression == null) { expression = new ExpressionAttribute(propertyDictionary.OriginExpression( property.Name, origin, expressionSelector, "", rowCustomAttributes)); } if (display == null) { display = new DisplayNameAttribute(propertyDictionary.OriginDisplayName(property.Name, origin)); } if (size == null) { size = propertyDictionary.OriginAttribute <SizeAttribute>(property.Name, origin); } if (scale == null) { scale = propertyDictionary.OriginAttribute <ScaleAttribute>(property.Name, origin); } } catch (DivideByZeroException) { throw new InvalidProgramException(String.Format( "Infinite recursion detected while determining origins " + "for property '{0}' on row type '{1}'", property.Name, rowType.FullName)); } } var insertable = property.GetAttribute <InsertableAttribute>(); var updatable = property.GetAttribute <UpdatableAttribute>(); if (insertable != null && !insertable.Value) { removeFlags |= FieldFlags.Insertable; } if (updatable != null && !updatable.Value) { removeFlags |= FieldFlags.Updatable; } foreach (var attr in property.GetAttributes <SetFieldFlagsAttribute>()) { addFlags |= attr.Add; removeFlags |= attr.Remove; } } if (ReferenceEquals(null, field)) { if (property == null) { throw new InvalidProgramException(String.Format( "Field {0} in type {1} is null and has no corresponding property in entity!", fieldInfo.Name, rowType.Name)); } object[] prm = new object[7]; prm[0] = this; // owner prm[1] = column == null ? property.Name : (column.Name.TrimToNull() ?? property.Name); prm[2] = display != null ? new LocalText(display.DisplayName) : null; prm[3] = size != null ? size.Value : 0; var defaultFlags = FieldFlags.Default; if (fieldInfo.FieldType.GetCustomAttribute <NotMappedAttribute>() != null) { defaultFlags |= FieldFlags.NotMapped; } prm[4] = (defaultFlags ^ removeFlags) | addFlags; prm[5] = null; prm[6] = null; FieldInfo storage; if (rowFields.TryGetValue("_" + property.Name, out storage) || rowFields.TryGetValue("m_" + property.Name, out storage) || rowFields.TryGetValue(property.Name, out storage)) { prm[5] = CreateFieldGetMethod(storage); prm[6] = CreateFieldSetMethod(storage); } field = (Field)Activator.CreateInstance(fieldInfo.FieldType, prm); fieldInfo.SetValue(this, field); } else { if (size != null) { throw new InvalidProgramException(String.Format( "Field size '{0}' in type {1} can't be overridden by Size attribute!", fieldInfo.Name, rowType.FullName)); } if (display != null) { field.Caption = new LocalText(display.DisplayName); } if ((int)addFlags != 0 || (int)removeFlags != 0) { field.Flags = (field.Flags ^ removeFlags) | addFlags; } if (column != null && String.Compare(column.Name, field.Name, StringComparison.OrdinalIgnoreCase) != 0) { throw new InvalidProgramException(String.Format( "Field name '{0}' in type {1} can't be overridden by Column name attribute!", fieldInfo.Name, rowType.FullName)); } } if (scale != null) { field.Scale = scale.Value; } if (defaultValue != null) { field.DefaultValue = defaultValue.Value; } if (selectLevel != null) { field.MinSelectLevel = selectLevel.Value; } if (expression != null) { field.Expression = expression.Value; } if (foreignKey != null) { field.ForeignTable = foreignKey.Table; field.ForeignField = foreignKey.Field; } if ((leftJoin != null || innerJoin != null) && field.ForeignTable.IsEmptyOrNull()) { throw new InvalidProgramException(String.Format("Property {0} of row type {1} has a [LeftJoin] or [InnerJoin] attribute " + "but its foreign table is undefined. Make sure it has a valid [ForeignKey] attribute!", fieldInfo.Name, rowType.FullName)); } if ((leftJoin != null || innerJoin != null) && field.ForeignField.IsEmptyOrNull()) { throw new InvalidProgramException(String.Format("Property {0} of row type {1} has a [LeftJoin] or [InnerJoin] attribute " + "but its foreign field is undefined. Make sure it has a valid [ForeignKey] attribute!", fieldInfo.Name, rowType.FullName)); } if (leftJoin != null) { field.ForeignJoinAlias = new LeftJoin(this.joins, field.ForeignTable, leftJoin.Alias, new Criteria(leftJoin.Alias, field.ForeignField) == new Criteria(field)); } if (innerJoin != null) { field.ForeignJoinAlias = new InnerJoin(this.joins, field.ForeignTable, innerJoin.Alias, new Criteria(innerJoin.Alias, field.ForeignField) == new Criteria(field)); } if (textualField != null) { field.textualField = textualField.Value; } if (dateTimeKind != null && field is DateTimeField) { ((DateTimeField)field).DateTimeKind = dateTimeKind.Value; } if (readPermission != null) { field.readPermission = readPermission.Permission ?? "?"; } if (insertPermission != null) { field.insertPermission = insertPermission.Permission ?? "?"; } if (updatePermission != null) { field.updatePermission = updatePermission.Permission ?? "?"; } if (property != null) { if (property.PropertyType != null && field is IEnumTypeField) { if (property.PropertyType.IsEnum) { (field as IEnumTypeField).EnumType = property.PropertyType; } else { var nullableType = Nullable.GetUnderlyingType(property.PropertyType); if (nullableType != null && nullableType.IsEnum) { (field as IEnumTypeField).EnumType = nullableType; } } } foreach (var attr in property.GetAttributes <LeftJoinAttribute>()) { if (attr.ToTable != null && attr.OnCriteria != null) { new LeftJoin(this.joins, attr.ToTable, attr.Alias, new Criteria(attr.Alias, attr.OnCriteria) == new Criteria(field)); } } foreach (var attr in property.GetAttributes <InnerJoinAttribute>()) { if (attr.ToTable != null && attr.OnCriteria != null) { new InnerJoin(this.joins, attr.ToTable, attr.Alias, new Criteria(attr.Alias, attr.OnCriteria) == new Criteria(field)); } } field.PropertyName = property.Name; this.byPropertyName[field.PropertyName] = field; field.customAttributes = property.GetAttributes <Attribute>().ToArray(); } } } foreach (var attr in rowCustomAttributes.OfType <LeftJoinAttribute>()) { new LeftJoin(this.joins, attr.ToTable, attr.Alias, new Criteria(attr.OnCriteria)); } foreach (var attr in rowCustomAttributes.OfType <InnerJoinAttribute>()) { new InnerJoin(this.joins, attr.ToTable, attr.Alias, new Criteria(attr.OnCriteria)); } foreach (var attr in rowCustomAttributes.OfType <OuterApplyAttribute>()) { new OuterApply(this.joins, attr.InnerQuery, attr.Alias); } #if !COREFX var propertyDescriptorArray = new PropertyDescriptor[this.Count]; for (int i = 0; i < this.Count; i++) { var field = this[i]; propertyDescriptorArray[i] = new FieldDescriptor(field); } this.propertyDescriptors = new PropertyDescriptorCollection(propertyDescriptorArray); #endif InferTextualFields(); AfterInitialize(); } isInitialized = true; }
internal string PrefixAliases(string expression, string alias, DialectExpressionSelector expressionSelector, List <Attribute> extraJoins) { if (string.IsNullOrWhiteSpace(expression)) { return(expression); } Check.NotNullOrWhiteSpace(alias, "alias"); var aliasPrefix = alias + "_"; var mappedJoins = new Dictionary <string, ISqlJoin>(); Func <string, string> mapAlias = null; Func <string, string> mapExpression = x => { if (x == null) { return(null); } return(JoinAliasLocator.ReplaceAliases(x, mapAlias)); }; mapAlias = x => { if (x == "t0" || x == "T0") { return(alias); } ISqlJoin sqlJoin; if (mappedJoins.TryGetValue(x, out sqlJoin)) { return(sqlJoin.Alias); } Tuple <string, ForeignKeyAttribute, ISqlJoin> propJoin; if (joinPropertyByAlias.TryGetValue(x, out propJoin)) { var propertyInfo = propertyByName[propJoin.Item1]; string leftExpression; var newAlias = aliasPrefix + x; var columnAttr = propertyInfo.GetCustomAttribute <ColumnAttribute>(); if (columnAttr != null) { leftExpression = alias + "." + SqlSyntax.AutoBracket(columnAttr.Name); } else { var expressionAttr = propertyInfo.GetCustomAttribute <ExpressionAttribute>(); if (expressionAttr != null) { leftExpression = mapExpression(expressionAttr.Value); } else { var origin = propertyInfo.GetCustomAttribute <OriginAttribute>(); if (origin != null) { leftExpression = OriginExpression(propertyInfo.Name, origin, expressionSelector, alias, extraJoins); } else { leftExpression = alias + "." + SqlSyntax.AutoBracket(propertyInfo.Name); } } } ISqlJoin srcJoin = propJoin.Item3; var criteriax = leftExpression + " = " + newAlias + "." + SqlSyntax.AutoBracket(propJoin.Item2.Field); if (srcJoin is LeftJoinAttribute) { srcJoin = new LeftJoinAttribute(newAlias, propJoin.Item2.Table, criteriax); } else if (srcJoin is InnerJoinAttribute) { srcJoin = new InnerJoinAttribute(newAlias, propJoin.Item2.Table, criteriax); } else { throw new ArgumentOutOfRangeException("joinType"); } srcJoin.RowType = propJoin.Item2.RowType ?? propJoin.Item3.RowType; mappedJoins[x] = srcJoin; extraJoins.Add((Attribute)srcJoin); return(newAlias); } if (rowJoinByAlias.TryGetValue(x, out sqlJoin)) { var mappedCriteria = mapExpression(sqlJoin.OnCriteria); var newAlias = aliasPrefix + x; var rowType = sqlJoin.RowType; var lja = sqlJoin as LeftJoinAttribute; if (lja != null) { sqlJoin = new LeftJoinAttribute(lja.Alias, lja.ToTable, mappedCriteria); } else { var ija = sqlJoin as InnerJoinAttribute; if (ija != null) { sqlJoin = new InnerJoinAttribute(ija.Alias, ija.ToTable, mappedCriteria); } else { var oaa = sqlJoin as OuterApplyAttribute; if (oaa != null) { sqlJoin = new OuterApplyAttribute(ija.Alias, mappedCriteria); } } } sqlJoin.RowType = rowType; mappedJoins[x] = sqlJoin; extraJoins.Add((Attribute)sqlJoin); return(newAlias); } return(x); }; return(mapExpression(expression)); }