private void AppendJoin( TypePropertyMap map, int index, TypePropertyMapEntry entry, string aliasForCurrentTable, StringBuilder fromAndJoinsBuff, DtoMetadata metadata, string [] aliases) { var target = map.GetEntryWithMatchingPropertyPreceding(index, entry.Type); if (target == null) { throw new InvalidOperationException( string.Format( "Unable to find any property " + "that fits type '{0}'. Please ensure you have included all the necessary " + "types in your query, and that any type to which '{0}' should be added " + "precedes it in the list of types otherwise, like soldiers killed in " + "Stanley Kubrick's Full Metal Jacket, you will be in a world of s***.", entry.Type)); } fromAndJoinsBuff.Append("LEFT OUTER JOIN "); var targetProperty = target.GetPropertyMetadataFor(entry.Type); if (targetProperty.HasAttribute<ManyToManyAttribute>()) { var manyToMany = targetProperty.GetAttribute<ManyToManyAttribute>(); var linkAlias = AppendTableNameAndAlias(fromAndJoinsBuff, manyToMany.SchemaQualifiedLinkTableName); fromAndJoinsBuff.Append(" ON "); AppendJoinConditionArgument(target, fromAndJoinsBuff, target.Metadata.PrimaryKey, aliases); fromAndJoinsBuff.Append(" = "); AppendJoinConditionArgument(fromAndJoinsBuff, target.Metadata.PrimaryKey, linkAlias); fromAndJoinsBuff.Append(Environment.NewLine); fromAndJoinsBuff.Append("LEFT OUTER JOIN "); var table = metadata.GetAttribute<TableAttribute>(); AppendTableNameAndAlias(fromAndJoinsBuff, table, aliasForCurrentTable); fromAndJoinsBuff.Append(" ON "); AppendJoinConditionArgument(entry, fromAndJoinsBuff, metadata.PrimaryKey, aliases); fromAndJoinsBuff.Append(" = "); AppendJoinConditionArgument(fromAndJoinsBuff, metadata.PrimaryKey, linkAlias); fromAndJoinsBuff.Append(Environment.NewLine); } else { var table = metadata.GetAttribute<TableAttribute>(); AppendTableNameAndAlias(fromAndJoinsBuff, table, aliasForCurrentTable); fromAndJoinsBuff.Append(" ON "); if (targetProperty.HasAttribute<OneToOneAttribute>() && string.IsNullOrEmpty(targetProperty.GetAttribute<OneToOneAttribute>().ChildForeignKeyColumn)) { // Covers situation where foreign key column is on the target table AppendJoinConditionArgument(entry, fromAndJoinsBuff, metadata.PrimaryKey, aliases); fromAndJoinsBuff.Append(" = "); AppendJoinConditionArgument(target, fromAndJoinsBuff, targetProperty, aliases); } else if (targetProperty.HasAttribute<ManyToOneAttribute>()) { var manyToOne = targetProperty.GetAttribute<ManyToOneAttribute>(); var targetColumn = manyToOne.ForeignKeyTargetColumnName; if (string.IsNullOrEmpty(targetColumn)) { AppendJoinConditionArgument(entry, fromAndJoinsBuff, metadata.PrimaryKey, aliases); } else { AppendJoinConditionArgument(entry, fromAndJoinsBuff, targetColumn, aliases); } fromAndJoinsBuff.Append(" = "); AppendJoinConditionArgument(target, fromAndJoinsBuff, targetProperty, aliases); } else if (targetProperty.HasAttribute<OneToOneAttribute>() || targetProperty.HasAttribute<OneToManyAttribute>()) { // Covers situation where foreign key column is on the source table AppendJoinConditionArgument(entry, fromAndJoinsBuff, entry.GetPropertyMetadataFor(target.Type), aliases); fromAndJoinsBuff.Append(" = "); AppendJoinConditionArgument(target, fromAndJoinsBuff, target.Metadata.PrimaryKey, aliases); } else { throw new InvalidOperationException( string.Format( "Unable to generate JOIN condition between types '{0}' and '{1}' because the property '{2}' on '{1}' " + "is not decorated with an attribute indicating its cardinality. Please add a [OneToOne], [OneToMany] " + "[ManyToOne], or [ManyToMany] decoration, as appropriate.", metadata.DtoType, target.Type, targetProperty.Prop.Name)); } fromAndJoinsBuff.Append(Environment.NewLine); } }
private static void AppendConditionForParameter( StringBuilder whereConditionBuff, TypePropertyMapEntry entry, string parameterName, object parameterValue, string [] aliases) { if (whereConditionBuff.Length == 0) { whereConditionBuff.Append("WHERE "); } else { whereConditionBuff.Append(" AND "); } var alias = aliases == null ? entry.Alias : aliases[entry.Index]; whereConditionBuff.Append(alias); whereConditionBuff.Append(".["); whereConditionBuff.Append(parameterName); whereConditionBuff.Append("] "); if (parameterValue == null) { whereConditionBuff.Append("IS NULL"); } else { whereConditionBuff.Append("= @"); whereConditionBuff.Append(parameterName); } whereConditionBuff.Append(Environment.NewLine); }
private static void AppendJoinConditionArgument( TypePropertyMapEntry entry, StringBuilder fromAndJoinsBuff, string columnName, string [] aliases) { var alias = aliases == null ? entry.Alias : aliases[entry.Index]; AppendJoinConditionArgument(fromAndJoinsBuff, columnName, alias); }
private static void BuildWhereCondition(object parameters, StringBuilder whereConditionBuff, TypePropertyMapEntry entry, string [] aliases) { if (parameters != null) { if (parameters is IEnumerable<KeyValuePair<string, object>>) { foreach (var kvp in (IEnumerable<KeyValuePair<string, object>>) parameters) { AppendConditionForParameter( whereConditionBuff, entry, kvp.Key, kvp.Value, aliases); } } else { foreach ( var property in parameters.GetType() .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)) { AppendConditionForParameter( whereConditionBuff, entry, property.Name, property.GetMethod.Invoke(parameters, new object[0]), aliases); } } } }
private static void AppendJoinConditionArgument( TypePropertyMapEntry entry, StringBuilder fromAndJoinsBuff, PropertyMetadata property, string [] aliases) { if (property == null) { throw new InvalidOperationException( string.Format( "Unable to generate JOIN condition because no suitable join property could " + "be found on '{0}'. This might be because you haven't marked a property with " + "the [PrimaryKey] attribute from Dapper.SimpleSave, or because no matching " + "target property can be found on the target object, although this seems a bit " + "unlikely. Also bear in mind that commparison with property names here is " + "case-sensitive so this failure may be caused by a difference in casing between, " + "say, the property name, and any column name specified in a [Column] attribute.", entry.Type)); } var alias = aliases == null ? entry.Alias : aliases[entry.Index]; AppendJoinConditionArgument(fromAndJoinsBuff, property, alias); }