In my webapi dotnet7 application, I utilize Dapper for database operations. Additionally, I employ a solution found on StackOverflow for mapping database columns to class properties using the Column
attribute, as shown in the following example:
在我的webapi dotnet7应用程序中,我使用Dapper进行数据库操作。此外,我还使用了在StackOverflow上找到的解决方案,使用Column属性将数据库列映射到类属性,如下面的示例所示:
public class Customer
{
public int CustomerID { get; set; }
[Column(Name = "Customer_Name")]
public string Name{ get; set; }
}
This Column attribute is sourced from the ColumnAttributeTypeMapper.cs
file, which contains the custom type mapper logic. Here's an excerpt:
该列属性来自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);
}
}
}
To ensure Dapper recognizes these mappings, I currently add a SetTypeMap
call for each model in the Program.cs
file, which can lead to merge conflicts. For example:
为了确保Dapper能够识别这些映射,我目前为Program.cs文件中的每个模型添加了一个SetTypeMap调用,这可能会导致合并冲突。例如:
Dapper.SqlManager.SetTypeMap(typeof(Customer), new ColumnAttributeTypeMapper<Customer>);
Is there a way to automate the registration of these mappings for all models in the project? Perhaps by using an attribute, such as [DapperMapper]
, to associate each model with Dapper?
有没有办法为项目中的所有模型自动注册这些映射?也许可以使用一个属性,如[DapperMapper],将每个模型与Dapper关联起来?
Please advise on a more automated approach for registering Dapper mappings.
请提供更自动化的方法来注册Dapper映射。
更多回答
优秀答案推荐
The short answer currently is "no"; Dapper already does a ton of reflection, and it isn't hugely desirable to add more.
目前的简短答案是“不”;Dapper已经做了大量的反思,添加更多内容并不是很理想。
However; in the upcoming (incomplete, depends at least on net9 for build tool support) DapperAOT era, I do hope to incorporate something like this; in particular:
然而,在即将到来的DapperAOT时代(不完整,至少依赖于net9的构建工具支持),我确实希望加入这样的东西;特别是:
- there is already a
[DbValue(...)]
that allows a Name
to be specified (works both both column and parameter names)
- I intend to add support for the well-known
[System.ComponentModel.DataAnnotations.Schema.ColumnAttribute]
attribute, (perhaps via a global [UseColumnAttribute]
marker, to avoid surprises - perhaps even with a build warning if you have [Column(...)]
but don't have an explicit [UseColumnAttribute]
/[UseColumnAttribute(false)]
)
but: that's at least a few months out (can't release until at least November, and: I haven't even implemented [Column]
yet)
但是:这至少还需要几个月的时间(至少要到11月才能发布,而且:我甚至还没有实现[专栏])
I've logged https://github.com/DapperLib/DapperAOT/issues/36 for tracking
我已登录https://github.com/DapperLib/DapperAOT/issues/36进行跟踪
更多回答
我是一名优秀的程序员,十分优秀!