Я пытаюсь сопоставить свои поля Id с атрибутами столбца, но по какой-то причине это не работает, и я не могу понять, почему. Я создал тестовый проект, чтобы продемонстрировать, что я пытаюсь.
Во-первых, я получил 2 объекта:
Таблица сущностей1
using System.Data.Linq.Mapping;
namespace DapperTestProj
{
public class Table1
{
[Column(Name = "Table1Id")]
public int Id { get; set; }
public string Column1 { get; set; }
public string Column2 { get; set; }
public Table2 Table2 { get; set; }
public Table1()
{
Table2 = new Table2();
}
}
}
и сущность Table2
using System.Data.Linq.Mapping;
namespace DapperTestProj
{
public class Table2
{
[Column(Name = "Table2Id")]
public int Id { get; set; }
public string Column3 { get; set; }
public string Column4 { get; set; }
}
}
В моей базе данных я получил 2 таблицы, также называемые Table1 и Table2. Обе таблицы получили свои столбцы с именем, равным сущности, за исключением того, что Table1 имеет столбец с именем Table2Id, а также есть внешний ключ между Table1.Table2Id и Table2.Id.
Кроме того, в обеих таблицах есть по 1 записи, и у них есть оба идентификатора.
Что я пытаюсь сделать, так это выполнить запрос с dapper и он должен вернуть объект типа Table1. Это работает, но и свойство Table1.Id и Table1.Table2.Id остается 0 (по умолчанию целое число). Я ожидаю, что атрибуты столбца будут отображать поля Id, но это явно не так.
Это запрос и сопоставление, выполняемые в коде:
private Table1 TestMethod(IDbConnection connection)
{
var result = connection.Query<Table1, Table2, Table1>(
@"SELECT
T1.Id as Table1Id,
T1.Column1 as Column1,
T1.Column2 as Column2,
T2.Id as Table2Id,
T2.Column3 as Column3,
T2.Column4 as Column4
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.Table2Id = T2.Id",
(table1, table2) =>
{
table1.Table2 = table2;
return table1;
},
splitOn: "Table2Id"
).SingleOrDefault();
return result;
}
Теперь я мог переименовать оба свойства свойства Id в сущности в Table1Id и Table2Id, но вместо этого я предпочитаю идентификатор вместо более логического кода, например Table1.Id вместо Table1.Table1Id. Поэтому мне было интересно, возможно ли, что я хочу здесь, и если да, то как?
Изменить:
Я нашел эту тему: Вручную сопоставить имена столбцов с свойствами класса
И с кодом в первом посте Kaleb Pederson можно использовать атрибуты, когда это необходимо, с классом FallBackTypeMapper и классом ColumnAttributeTypeMapper. Все, что необходимо, - это добавить необходимые классы в typemapping с помощью:
SqlMapper.SetTypeMap(typeof(Table1), new ColumnAttributeTypeMapper<Table1>());
SqlMapper.SetTypeMap(typeof(Table2), new ColumnAttributeTypeMapper<Table2>());
Но со многими сущностями этот список будет расти долго. Также вам нужно добавить каждый класс вручную в список, и мне было интересно, можно ли это сделать автоматически с более общим с Reflection. Я нашел фрагмент кода, способный получить все типы:
const string @namespace = "DapperTestProj.Entities";
var types = from type in Assembly.GetExecutingAssembly().GetTypes()
where type.IsClass && type.Namespace == @namespace
select type;
И зациклившись на всех типах, я могу это сделать, только проблема, которую я имею сейчас, - это какой фрагмент кода, который мне нужен, или должен быть помещен туда, где вопросительные знаки сейчас?
typeList.ToList().ForEach(type => SqlMapper.SetTypeMap(type,
new ColumnAttributeTypeMapper</*???*/>()));
Edit:
После большего поиска я нашел решение для моей последней проблемы:
typeList.ToList().ForEach(type =>
{
var mapper = (SqlMapper.ITypeMap)Activator.CreateInstance(
typeof(ColumnAttributeTypeMapper<>)
.MakeGenericType(type));
SqlMapper.SetTypeMap(type, mapper);
});