我试图将我的Id字段与列属性进行映射,但出于某种原因,这似乎不起作用,我无法弄清楚为什么。 我设置了一个测试项目来演示我的尝试。
首先,我有两个实体:
实体 Table1
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; }
}
}
在我的数据库中,有两个表,也称为Table1和Table2。这两个表的列名称与实体相同,但Table1除外,它有一个名为Table2Id的列,并且Table1.Table2Id和Table2.Id之间还有一个外键关系。
此外,每个表中都有一个记录,它们都具有Id 2。
接下来我尝试使用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,但我更喜欢使用Id,因为它能让代码更加合乎逻辑,例如Table1.Id而不是Table1.Table1Id。所以我想知道,我想要的是否可能实现,如果可能,应该如何操作呢?
编辑:
我找到了这个主题: 手动将列名称映射到类属性
通过Kaleb Pederson的第一篇帖子中的代码,可以使用FallBackTypeMapper类和ColumnAttributeTypeMapper类在需要时使用属性。所有需要的就是将所需的类添加到typemapping中:
SqlMapper.SetTypeMap(typeof(Table1), new ColumnAttributeTypeMapper<Table1>());
SqlMapper.SetTypeMap(typeof(Table2), new ColumnAttributeTypeMapper<Table2>());
但是对于许多实体,这个列表会变得很长。而且你需要手动将每个类添加到列表中,我在想是否可以使用反射自动更加通用地完成这项工作。我找到了一个能够获取所有类型的代码片段:
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</*???*/>()));
编辑:
经过更多搜索,我找到了解决上一个问题的方法:
typeList.ToList().ForEach(type =>
{
var mapper = (SqlMapper.ITypeMap)Activator.CreateInstance(
typeof(ColumnAttributeTypeMapper<>)
.MakeGenericType(type));
SqlMapper.SetTypeMap(type, mapper);
});