Reputation: 3757
I have a table with configurations and there are multiple types (stored in different columns) and i need to query with entity framework for the current type based on the generic type
I have 2 approaches 1 is just casting everything to (dynamic), basically saying i don't need type checking here
and it look like this
static TValue GetValueBasedOnType<TValue>(int configKey)
{
var query = dbcontext.Configurations.Where(c => c.configKey == configKey);
if(typeof(TValue) == typeof(bool))
return (dynamic)(query.Select(c => c.ValueBit).FirstOrDefault() ?? false);
if(typeof(TValue) == typeof(string))
return (dynamic)(query.Select(c => c.ValueText).FirstOrDefault());
if (typeof(TValue) == typeof(decimal))
return (dynamic)(query.Select(c => c.ValueDecimal).FirstOrDefault());
return default(TValue);
}
Or i can just cast the query to the current type, by first making it a general object and then change it back to the original type, like this
static TValue GetValueBasedOnType<TValue>(int configKey)
{
var query = dbcontext.Configurations.Where(c => c.configKey == configKey);
if (typeof(TValue) == typeof(bool))
return (TValue)(object)(query.Select(c => c.ValueBit).FirstOrDefault() ?? false);
if (typeof(TValue) == typeof(string))
return (TValue)(object)(query.Select(c => c.ValueText).FirstOrDefault());
if (typeof(TValue) == typeof(decimal))
return (TValue)(object)(query.Select(c => c.ValueDecimal).FirstOrDefault());
return default(TValue);
}
I just wonder what option is a better idea to use?
Upvotes: 3
Views: 270
Reputation: 21568
You can cast directly to TValue
using the Linq Cast
function:
static TValue GetValueBasedOnType<TValue>(int configKey)
{
var query = new List<Configuration>{ new Configuration { ValueDecimal = 1.2M, ValueBit = true, ValueText = "Text" }};
if (typeof(TValue) == typeof(bool))
return query.Select(c => c.ValueBit).Cast<TValue>().FirstOrDefault();
if (typeof(TValue) == typeof(string))
return query.Select(c => c.ValueText).Cast<TValue>().FirstOrDefault();
if (typeof(TValue) == typeof(decimal))
return query.Select(c => c.ValueDecimal).Cast<TValue>().FirstOrDefault();
return default(TValue);
}
As you can see, I used a List<Configuration>
to test your function. With the following additional code in LinqPad:
public class Configuration
{
public bool ValueBit { get; set; }
public string ValueText { get; set; }
public decimal ValueDecimal { get; set; }
}
void Main()
{
GetValueBasedOnType<bool>(0).Dump();
GetValueBasedOnType<string>(0).Dump();
GetValueBasedOnType<decimal>(0).Dump();
}
my output is, as expected:
True Text 1.2
Out of interest I ran a similar query against a database of my own in Linqpad and again I got the expected result and the SQL generated was satisfactory - a TOP(1)
query.
Upvotes: 1