Currently i have this (ugly) piece of code. It does a very simple thing. It takes a query as an input and translates it to SQL.
public class DqlSelectQueryTranslator : Translator<DqlSelectQuery>
{
protected override string Translate(DqlSelectQuery query)
{
var ops = query.Operators;
var sb = new StringBuilder();
sb.AppendLine(ops.AnyOfType<DqlSelectOperator>()
? $"SELECT {string.Join(",", ops.FirstOfType<DqlSelectOperator>().Fields)} FROM {query.TargetEntityType.Name}"
: $"SELECT * FROM {query.TargetEntityType.Name}");
if (ops.AnyOfType<DqlIncludeOperator>())
{
foreach (var dst in ops.OfType<DqlIncludeOperator>())
{
var src = query.TargetEntityType;
var type = src.GetRelationship<RelationshipAttribute>(dst.Type);
if (type == null)
throw new NotSupportedException($"Unknown relationship between {src.Name} and {dst.Type.Name}");
if (type is OneToManyAttribute)
sb.AppendLine($"JOIN {dst.Type.Name} {dst.Alias} ON {dst.Name}.{src.GetPrimaryKeys().First()} = {src.Name}.{src.GetPrimaryKeys().First()}");
if (type is ManyToOneAttribute)
sb.AppendLine($"JOIN {dst.Type.Name} {dst.Alias} ON {dst.Name}.{dst.Type.GetPrimaryKeys().First()} = {src.Name}.{dst.Type.GetPrimaryKeys().First()}");
if (type is ManyToManyAttribute)
{
string joinName = $"_{src.Name}{dst.Type.Name}";
sb.AppendLine($"JOIN {src.GetRelationship<ManyToManyAttribute>(dst.Type).Join} {joinName} ON {joinName}.{src.GetPrimaryKeys().First()} = {src.Name}.{src.GetPrimaryKeys().First()}");
sb.AppendLine($"JOIN {dst.Type.Name} {dst.Alias} ON {dst.Name}.{dst.Type.GetPrimaryKeys().First()} = {joinName}.{dst.Type.GetPrimaryKeys().First()}");
}
}
}
if (ops.AnyOfType<DqlWhereOperator>())
sb.AppendLine($"WHERE {ops.FirstOfType<DqlWhereOperator>().Condition}");
if (ops.AnyOfType<DqlOffsetOperator>())
sb.AppendLine($"OFFSET {ops.FirstOfType<DqlOffsetOperator>().Offset} ROWS");
if (ops.AnyOfType<DqlLimitOperator>())
sb.AppendLine($"FETCH NEXT {ops.FirstOfType<DqlLimitOperator>().Limit} ROWS ONLY");
return sb.ToString().Trim();
}
}
I'm looking for a way to improve that. My guess would be associate a "translator" to my operators/queries... It would be cleaner but then i would need to add classes with one line of code... Do you have good design patterns/ideas on how i can improve this bit?
Thx Seb
Aucun commentaire:
Enregistrer un commentaire