1

我正在使用 Dapper Extensions 并定义了我自己的自定义映射器来处理具有复合键的实体。

     public class MyClassMapper<T> : ClassMapper<T> where T : class
{
    public MyClassMapper()
    {
        // Manage unmappable attributes

        IList<PropertyInfo> toIgnore = typeof(T).GetProperties().Where(x => !x.CanWrite).ToList();

        foreach (PropertyInfo propertyInfo in toIgnore.ToList())
        {
            Map(propertyInfo).Ignore();
        }

        // Manage keys

        IList<PropertyInfo> propsWithId = typeof(T).GetProperties().Where(x => x.Name.EndsWith("Id") || x.Name.EndsWith("ID")).ToList();
        PropertyInfo primaryKey = propsWithId.FirstOrDefault(x => string.Equals(x.Name, $"{nameof(T)}Id", StringComparison.CurrentCultureIgnoreCase));

        if (primaryKey != null && primaryKey.PropertyType == typeof(int))
        {
            Map(primaryKey).Key(KeyType.Identity);
        }
        else if (propsWithId.Any())
        {
            foreach (PropertyInfo prop in propsWithId)
            {
                Map(prop).Key(KeyType.Assigned);
            }
        }

        AutoMap();
    }
}

我也有这个测试用例来测试我的映射器:

    [Test]
    public void TestMyAutoMapper()
    {
        DapperExtensions.DapperExtensions.DefaultMapper = typeof(MyClassMapper<>);

        MySubscribtionEntityWithCompositeKey entity = new MySubscribtionEntityWithCompositeKey
        {
            SubscriptionID = 145,
            CustomerPackageID = 32
        };

        using (var connection = new SqlConnection(CONNECTION_STRING))
        {
            connection.Open();
            var result = connection.Insert(entity);
            var key1 = result.SubscriptionID;
            var key2 = result.CustomerPackageID;
        }
    }

请注意,我在测试用例中设置了默认映射器。

插入失败,我注意到我的客户映射器从未被调用。我在 github 页面上没有关于该主题的文档,所以我不确定是否需要做任何其他事情来使 dapper 扩展使用我的映射器。

提前致谢!

4

1 回答 1

1

Looking at your question, you are attempting to write your own defalut class mapper derived from the existing one. I never used this approach; so I do not know why it is not working or whether it should work.

I explicitly map the classes as below:

public class Customer
{
    public int CustomerID { get; set; }
    public string Name { get; set; }
}

public sealed class CustomerMapper : ClassMapper<Customer>
{
    public CustomerMapper()
    {
        Schema("dbo");
        Table("Customer");
        Map(x => x.CustomerID).Key(KeyType.Identity);
        AutoMap();
    }
}

The AutoMap() will map rest of the properties based on conventions. Please refer to these two resources for more information about mapping.

Then I call SetMappingAssemblies at the startup of the project as below:

DapperExtensions.DapperExtensions.SetMappingAssemblies(new[] { Assembly.GetExecutingAssembly() });

The GetExecutingAssembly() is used in above code because mapping classes (CustomerMapper and other) are in same assembly which is executing. If those classes are placed in other assembly, provide that assembly instead.

And that's it, it works.

To set the dialect, I call following line just below the SetMappingAssemblies:

DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqlServerDialect();

Use your preferred dialect instead of SqlServerDialect.

Apparently, the solution mentioned here may help you achieve what you are actually trying to. But, I cannot be sure, as I said above, I never used it.

于 2019-11-04T10:01:48.847 回答