Probably you won't use it anymore, but maybe there are more guys up there trying to figure it out.
I've been checking out how dapper works when running GetAll<>
and Insert<>
.
What it does:
var type = typeof(T);
var cacheType = typeof(List<T>);
if (!GetQueries.TryGetValue(cacheType.TypeHandle, out string sql))
{
GetSingleKey<T>(nameof(GetAll));
var name = GetTableName(type); <--- key thing
sql = "select * from " + name;
GetQueries[cacheType.TypeHandle] = sql;
}
So I've checked what GetTableName
was doing:
private static string GetTableName(Type type)
{
if (TypeTableName.TryGetValue(type.TypeHandle, out string name)) return name;
if (TableNameMapper != null)
{
name = TableNameMapper(type); <-- key thing
}
else
{
//NOTE: This as dynamic trick should be able to handle both our own Table-attribute as well as the one in EntityFramework
var tableAttr = type
#if NETSTANDARD1_3
.GetTypeInfo()
#endif
.GetCustomAttributes(false).SingleOrDefault(attr => attr.GetType().Name == "TableAttribute") as dynamic;
if (tableAttr != null)
{
name = tableAttr.Name;
}
else
{
name = type.Name + "s";
if (type.IsInterface() && name.StartsWith("I"))
name = name.Substring(1);
}
}
TypeTableName[type.TypeHandle] = name;
return name;
}
Solution:
So I thought I can implement my own table name mapper with code like this:
SqlMapperExtensions.TableNameMapper = DapperMapper.TableNameMapper();
And
public static SqlMapperExtensions.TableNameMapperDelegate TableNameMapper()
{
return (type) =>
{
var has = Attribute.GetCustomAttribute(type, typeof(CastleTableAttribute));
if (has != null)
{
return $"{ConfigurationProvider.Schema}.{type.Name}";
}
else
{
return type.Name;
}
};
}
With that name mapper you just need to mark your table with that.
[CastleTable]
class CubeTimestamps
{
[ExplicitKey]
public int cube_id { get; set; }
public DateTime cube_timestamp { get; set; }
}
you can implement your name mapper to use [TableName] attribute also. Because my simple implementation hides this feature.
Enjoy :)