My stored procedure is returning dynamic pivot columns as available. I am using the SQLMapper and COlumnTypeAttribute, But in the results I can only see the first column and its value, but the dynamic pivot column(s) and their values(s) are empty.
the sample data could look like
The first column is fixed, Rest of the columns are pivot columns.
TSBNumber SystemXY SystemBB SystemTT
asdas 1/1/2013
1231 1/1/2014
12312 1/1/2013
ASAWS 1/1/2013
awsdS 1/1/2013
Store Procedure
DECLARE @PivotColumnHeaders NVARCHAR(MAX)
SELECT @PivotColumnHeaders =
COALESCE(
@PivotColumnHeaders + ',[' + cast(SystemFullName as Nvarchar) + ']',
'[' + cast(SystemFullName as varchar)+ ']'
)
FROM System
WHERE (@SelectedSystemIDs IS NULL OR System.ID IN(select * from dbo.SplitInts_RBAR_1(@SelectedSystemIDs, ',')))
AND ((@PlatformID IS NULL) OR (System.PlatformID = @PlatformID) OR (@PlatformID = 12 AND System.PlatformID <= 2))
DECLARE @PivotTableSQL NVARCHAR(MAX)
SET @PivotTableSQL = N'
SELECT *
FROM (
SELECT
TSBNumber [TSBNumber],
SystemFullName,
ClosedDate
FROM ServiceEntry
INNER JOIN System
ON ServiceEntry.SystemID = System.ID
where
(ServiceEntry.TSBNumber IS NOT NULL)
AND
(ServiceEntry.ClosedDate IS NOT NULL)
AND
(
(''' + @SelectedTsbIDs + ''' = '''+ '0' + ''') OR
(ServiceEntry.TSBNumber in (select * from dbo.SplitStrings_Moden(''' + @SelectedTsbIDs + ''', ''' + ',' + ''')))
)
) AS PivotData
PIVOT (
MAX(ClosedDate)
FOR SystemFullName IN (
' + @PivotColumnHeaders + '
)
) AS PivotTable
'
EXECUTE (@PivotTableSQL)
ColumnAttributeTypeManager
namespace RunLog.Domain.Exports
{
/// <summary>
/// Uses the Name value of the ColumnAttribute specified, otherwise maps as usual.
/// </summary>
/// <typeparam name="T">The type of the object that this mapper applies to.</typeparam>
public class ColumnAttributeTypeMapper<T> : FallbackTypeMapper
{
public static readonly string ColumnAttributeName = "ColumnAttribute";
public ColumnAttributeTypeMapper()
: base(new SqlMapper.ITypeMap[]
{
new CustomPropertyTypeMap(
typeof(T),
(type, columnName) =>
type.GetProperties().FirstOrDefault(prop =>
prop.GetCustomAttributes(false)
.OfType<ColumnAttribute>()
.Any(attr => attr.Name == columnName)
)
),
new DefaultTypeMap(typeof(T))
})
{
}
//public ColumnAttributeTypeMapper()
// : base(new SqlMapper.ITypeMap[]
// {
// new CustomPropertyTypeMap(typeof (T), SelectProperty),
// new DefaultTypeMap(typeof (T))
// })
//{
//}
//private static PropertyInfo SelectProperty(Type type, string columnName)
//{
// return
// type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).
// FirstOrDefault(
// prop =>
// prop.GetCustomAttributes(false)
// // Search properties to find the one ColumnAttribute applied with Name property set as columnName to be Mapped
// .Any(attr => attr.GetType().Name == ColumnAttributeName
// &&
// attr.GetType().GetProperties(BindingFlags.Public |
// BindingFlags.NonPublic |
// BindingFlags.Instance)
// .Any(
// f =>
// f.Name == "Name" &&
// f.GetValue(attr).ToString().ToLower() == columnName.ToLower()))
// && // Also ensure the property is not read-only
// (prop.DeclaringType == type
// ? prop.GetSetMethod(true)
// : prop.DeclaringType.GetProperty(prop.Name,
// BindingFlags.Public | BindingFlags.NonPublic |
// BindingFlags.Instance).GetSetMethod(true)) != null
// );
//}
}
public class MyModel
{
[Column("TSBNumber")]
public string TSBNumber { get; set; }
[Column(Name = "FileKey")]
public string MyProperty2 { get; set; }
//public string MyProperty2 { get; set; } // Uses Default Mapping
// ...
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ColumnAttribute : Attribute
{
public string Name { get; set; }
public ColumnAttribute() { }
public ColumnAttribute(string Name) { this.Name = Name; }
}
public class FallbackTypeMapper : SqlMapper.ITypeMap
{
private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;
public FallbackTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)
{
_mappers = mappers;
}
public ConstructorInfo FindConstructor(string[] names, Type[] types)
{
foreach (var mapper in _mappers)
{
try
{
ConstructorInfo result = mapper.FindConstructor(names, types);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetConstructorParameter(constructor, columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetMember(string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetMember(columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
}
}
Executing Stored Procedure
public static string ServiceTsbExport(DateTime StartDate, DateTime EndDate, int UserRoleID,
string SelectedSystemIDs,
string SelectedTsbIDs)
{
EFDbContext db = new EFDbContext();
Dapper.SqlMapper.SetTypeMap(typeof(MyModel), new ColumnAttributeTypeMapper<MyModel>());
return db.Database.SqlQuery<MyModel>("[dbo].[spExportServiceTSB] @parm1, @parm2, @parm3, @parm4, @parm5",
new SqlParameter("parm1", StartDate),
new SqlParameter("parm2", EndDate),
new SqlParameter("parm3", SelectedSystemIDs),
new SqlParameter("parm4", SelectedTsbIDs),
new SqlParameter("parm5", UserRoleID)
).ToList().ToHTMLTable();
}