使用Dapper映射Uri字段

3

如何使用Dapper将字符串列映射到Uri属性的最清晰的方法是什么?

到目前为止,这是我能想到的最简洁的方法(使用ITypeMap功能):

查询:

SELECT * FROM TableWithAStringAddressColumn

POCO:

public class MyPoco
{   
    [ColumnSetter("DapperAddress")]
    public Uri Address { get; set; }
    private string DapperAddress { set { this.Address = new Uri(value); } }
}

扩展:

partial class SqlMapper
{
    public static void InitializeTypeMaps()
    {
        SqlMapper.SetTypeMap(
            typeof(MyPoco),
            new CustomPropertyTypeMap(typeof(MyPoco), SqlMapper.CustomSetterMapper));

        // call out every other class that needs this kind of mapping
    }

    public static Func<Type, string, PropertyInfo> CustomSetterMapper =
        (type, columnName) =>
        {
            PropertyInfo prop = type
                .GetProperties()
                .FirstOrDefault(p => string.Equals(columnName, p.Name, StringComparison.OrdinalIgnoreCase));

            if (prop != null)
            {
                // find out if we need to use a different setter
                ColumnSetterAttribute setterAttribute = prop.GetCustomAttributes(false).OfType<ColumnSetterAttribute>().LastOrDefault();
                if (setterAttribute != null)
                {
                    PropertyInfo setterProp = type
                        .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                        .FirstOrDefault(p => string.Equals(setterAttribute.Setter, p.Name, StringComparison.OrdinalIgnoreCase));
                    if (setterProp == null)
                    {
                        throw new InvalidOperationException(string.Format("Setter property misconfigured (Property={0}, Setter={1})", prop.Name, setterAttribute.Setter));
                    }
                    else
                    {
                        prop = setterProp;
                    }
                }
            }
            return prop;
        };
}

自定义属性:
public class ColumnSetterAttribute : Attribute
{
    public string Setter { get; set; }

    public ColumnSetterAttribute(string setter)
    {
        this.Setter = setter;
    }
}

[编辑] 我正在寻找一种解决方案,可以在不需要在所有查询中调用所有列的情况下使用(我希望找到一种可以使用 SELECT * 的解决方案)。

1个回答

2

看起来需要做很多工作...

这样行吗?

public class MyPoco
{
    private string _uriMapper;

    public Uri SomeUri
    {
        get { return new Uri(_uriMapper); }
    }

    public string Mapper { set { _uriMapper = value; } }
}

编辑:

public class UriContainer
{
    private string _uriMapper;

    public string UriMapper { set { _uriMapper = value; } }

    public int Id { get; set; }

    public Uri SomeUri { get {return new Uri(_uriMapper);} }
}



public class DbTests
{
    [Test]
    public void Can_Get_A_Uri()
    {
        using (var c = new SqlConnection("hello"))
        {
            c.Open();

            var uri = c.Query<UriContainer>("select *, someuri as urimapper from uris where id = 3").Single();

            Console.WriteLine(uri.SomeUri);
        }
    }
}

你说得对。如果我在查询中调用所有列并为特殊的列设置别名,那么这个方法是可行的。例如:SELECT Column1, Column2, SomeUri AS Mapper FROM TableName。但是,我正在寻找一种不必在所有查询中都调用所有列的解决方案。 - Clay
好的,直接将映射属性命名为列名称是不可接受的吗?此外,您不需要调用所有列,只需调用想要别名的列-这个语句可以工作:“select *,someUri as mapper from table”。 - Greg Smith
正确,我想在我的属性(类型为Uri)中使用与表中相同的名称。不得不重新命名其中一方,只是为了满足Dapper,似乎有些牵强。不幸的是,如果您将Uri属性的名称与SQL列相同,则无法使用“SELECT *,SomeUri AS Mapper”技巧。 - Clay
实际上,如果Uri属性只是一个getter Uri SomeUri { get { ... } },那么SELECT *,SomeUri AS Mapper技巧确实有效。如果您将SomeUri设置为自动属性public Uri SomeUri { get; set; },则无法使用该技巧。 - Clay
我很确定我们在同一页面上 - 我更新了我的答案,并附上了我用来测试的确切代码 - 对我来说完全符合预期。 - Greg Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接