Lets say I have one method, which extracts property name and value:
public TModel Get (Expression<Func<object>> param)
{
using (OracleConnection connection = new OracleConnection(GetConnectionString()))
{
connection.Open();
var propertyName= ((MemberExpression)param.Body).Member.Name;
var value = param.Compile()();
// GetTableName() returns table name of TModel
var query = $"SELECT * FROM {GetTableName()} WHERE {propertyName}='{value}'";
var output = connection.Query<TModel>(query);
connection.Dispose();
return output.FirstOrDefault();
}
}
and using it as:
var model = Get(() => foo.FirstProperty);
However, if I want to get name and value from the unknown number of properties, I do this:
public TModel Get(params Expression<Func<object>>[] param)
using (OracleConnection connection = new OracleConnection(GetConnectionString()))
{
connection.Open();
var query = new StringBuilder();
query.Append($"SELECT * FROM {GetTableName()} WHERE ");
for (int i = 0; i < param.Length; i++)
{
var propertyName = ((MemberExpression)param[i].Body).Member.Name;
var value = param[i].Compile()();
query.Append($"{propertyName} = '{value}'");
if (i + 1 < param.Length) query.Append(" AND ");
}
var output = connection.Query<TModel>(query.ToString());
connection.Dispose();
return output.FirstOrDefault();
}
}
But, implementation looks a bit 'ugly' and verbose:
var model = Get(() => foo.FirstProperty, () => foo.SecondProperty); // and so on
I could send manualy name of the property + value, however, I would like to keep the implementation as simple as possible and less verbose.
Is there any way to simplify this?
1 Answer 1
If you want to iterate through all of the properties then reflection will help you to do that. You can find more at MS docs Something like this:
public TModel Get<TParam>(TParam param)
{
var allParams = typeof(TParam).GetProperties().Select(p => $"{p.Name} ='{p.GetValue(param)}'");
var condition = string.Join(" AND ", allParams);
using (OracleConnection connection = new OracleConnection(GetConnectionString()))
{
connection.Open();
// GetTableName() returns table name of TModel
var query = $"SELECT * FROM {GetTableName()} WHERE {condition}";
var output = connection.Query<TModel>(query);
return output.FirstOrDefault();
}
}
But you have to think how to escape SQL injections. Because the value of query variable in current implementation could have potential vulnerabilities.
object[]which would be something likeGet(() => new {foo.FirstProperty, foo.SecondProperty})then just loop over the object array. \$\endgroup\$