I am using Dapper Extensions but I have multiple schema names in My DB.
I found the an answer in below link but it assumes that I have only one schema name and this is not my case. Dapper Extensions Change Schema
What is the right way to change the schema name at the runtime?
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 :)