在我的 webapi dotnet7 应用程序中,我使用 Dapper 进行数据库操作。此外,我采用了 StackOverflow 上找到的解决方案,使用
Column
属性将数据库列映射到类属性,如以下示例所示:
public class Customer
{
public int CustomerID { get; set; }
[Column(Name = "Customer_Name")]
public string Name{ get; set; }
}
ColumnAttributeTypeMapper.cs
文件,其中包含自定义类型映射器逻辑。摘录如下:
namespace YourNamespace
{
/// <summary>
/// Uses the Name value of the <see cref="ColumnAttribute"/> specified to determine
/// the association between the name of the column in the query results and the member to
/// which it will be extracted. If no column mapping is present all members are mapped as
/// usual.
/// </summary>
/// <typeparam name="T">The type of the object that this association between the mapper applies to.</typeparam>
public class ColumnAttributeTypeMapper<T> : FallbackTypeMapper
{
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))
})
{
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ColumnAttribute : Attribute
{
public string Name { get; set; }
}
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;
}
public ConstructorInfo FindExplicitConstructor()
{
return _mappers
.Select(mapper => mapper.FindExplicitConstructor())
.FirstOrDefault(result => result != null);
}
}
}
为了确保 Dapper 识别这些映射,我目前为
SetTypeMap
文件中的每个模型添加了 Program.cs
调用,这可能会导致合并冲突。例如:
Dapper.SqlManager.SetTypeMap(typeof(Customer), new ColumnAttributeTypeMapper<Customer>);
有没有办法自动为项目中的所有模型注册这些映射?也许通过使用属性(例如
[DapperMapper]
)将每个模型与 Dapper 相关联?
请提供有关注册 Dapper 映射的更自动化方法的建议。
目前简短的回答是“不”; Dapper 已经进行了大量的反射,并且不太需要添加更多反射。
但是;在即将到来的(不完整,至少依赖于 net9 构建工具支持)DapperAOT 时代,我do希望纳入这样的东西;特别是:
已经有一个 [DbValue(...)]
Name
添加对众所周知的
[System.ComponentModel.DataAnnotations.Schema.ColumnAttribute]
[UseColumnAttribute]
标记,以避免意外 - 如果您有
[Column(...)]
但不',甚至可能会出现构建警告) t 有明确的 [UseColumnAttribute]
/[UseColumnAttribute(false)]
)
但是:这至少需要几个月的时间(至少要到 11 月才能发布,并且:我什至还没有实施
[Column]
我已登录
https://github.com/DapperLib/DapperAOT/issues/36进行跟踪