2017-07-11 24 views
0

我有一个class它实现了一些interface异常,并提示“无柱映射”使用小巧玲珑的扩展

public interface IDb {} 
public class DbModel : IDb {} 

这个我用小巧玲珑的扩展插入对象到数据库后。此代码工作得很好:

var obj = new DbModel(); 
sqlConnection.Insert(obj); 

但是当我尝试插入此class的一个实例,铸造在相应interface,它给出了一个例外:

IDb obj = new DbModel(); 
sqlConnection.Insert(obj); // exception here 

System.ArgumentException:“没有列映射。'

回答

0

理由不工作:

一个事实,即,DapperExtensions.Insert方法是通用出发,DapperExstensions无法找到相应的地图为IDb

解决方案:

创建映射器类IDb并注册DbModel属性

public sealed class IDbMapper : ClassMapper<IDb> 
{ 
    public IDbMapper() 
    { 
     base.Table("TableName"); 
     Map(m => new DbModel().Title); 
     // and such mapping for other properties 
    } 
} 

在此之后它会工作:

IDb obj = new DbModel(); 
sqlConnection.Insert(obj); 

但这里是一个问题,当我们有IDb 接口的许多实现,在IDbMapper配置我们不能列映射到相应的 表格:

base.Table("TableName"); 
Map(m => new DbModel().Title); 

因为当我们做mapp时我们不知道对象实例的类型ING。

编辑:

一些调试运行我注意到,在每一个Insert方法调用,短小精悍做映射,并构建相应的ClassMapper<>下课。我们可以使用这个奇怪的东西。

为此,我们应该在调用Insert方法之前创建SharedState并将其存储在实例类型中。

public static class DapperExstensionsExstensions 
{ 
    public static Type SharedState_ModelInstanceType { get; set; } 
    ... 
} 

IDb obj = new DbModel(); 
DapperExstensionsExstensions.SharedState_ModelInstanceType = obj.GetType(); 
sqlConnection.Insert(obj); 

此之后,我们可以访问此属性时,小巧玲珑将做映射

public sealed class IDbMapper : ClassMapper<IDb> 
{ 
    public IDbMapper() 
    { 
     // here we can retrieve Type of model instance and do mapping using reflection 
     DapperExstensionsExstensions.SharedState_ModelInstanceType 
    } 
} 

整个代码片段:

public interface IDb { } 

[MapConfig("TableName", "Schema")] 
public class DbTemp : IDb 
{ 
    public string Title { get; set; } 
} 

public class MapConfigAttribute : Attribute 
{ 
    public MapConfigAttribute(string name, string schema) 
    { 
     Name = name; 
     Schema = schema; 
    } 
    public string Name { get; } 
    public string Schema { get; } 
} 

public sealed class DbMapper : ClassMapper<IDb> 
{ 
    public DbMapper() 
    { 
     DapperExstensionsExstensions.CorrespondingTypeMapper<IDb>((tableName, sechemaName, exprs) => 
     { 
      Table(tableName); 
      Schema(SchemaName); 
      return exprs.Select(Map); 
     }); 
    } 
} 

public static class DapperExstensionsExstensions 
{ 
    private static readonly object _LOCK = new object(); 
    public static Type SharedState_ModelInstanceType { get; set; } 
    public static List<PropertyMap> CorrespondingTypeMapper<T>(Func<string, string, IEnumerable<Expression<Func<T, object>>>, IEnumerable<PropertyMap>> callback) 
    { 
     var tableNameAttribute = (MapConfigAttribute)SharedState_ModelInstanceType.GetCustomAttribute(typeof(MapConfigAttribute)); 
     var tableName = tableNameAttribute.Name; 
     var schemaName = tableNameAttribute.Schema; 
     var result = callback(tableName, schemaName, new GetPropertyExpressions<T>(SharedState_ModelInstanceType)); 
     Monitor.Exit(_LOCK); 
     return result.ToList(); 
    } 
    public static object Insert<TInput>(this IDbConnection connection, TInput entity) where TInput : class 
    { 
     Monitor.Enter(_LOCK); 
     SharedState_ModelInstanceType = entity.GetType(); 
     return DapperExtensions.DapperExtensions.Insert(connection, entity); 
    } 
} 

public class GetPropertyExpressions<TInput> : IEnumerable<Expression<Func<TInput, object>>> 
{ 
    private readonly Type _instanceType; 

    public GetPropertyExpressions(Type instanceType) 
    { 
     _instanceType = instanceType; 
    } 
    public IEnumerator<Expression<Func<TInput, object>>> GetEnumerator() 
    { 
     return _instanceType 
      .GetProperties() 
      .Select(p => new GetPropertyExpression<TInput>(_instanceType, p.Name).Content()).GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

public class GetPropertyExpression<TInput> : IContent<Expression<Func<TInput, object>>> 
{ 
    private readonly Type _instanceType; 
    private readonly string _propertyName; 
    public GetPropertyExpression(Type instanceType, string propertyName) 
    { 
     _instanceType = instanceType; 
     _propertyName = propertyName; 
    } 
    public Expression<Func<TInput, object>> Content() 
    { 
     // Expression<Func<IDb, object>> :: model => (object)(new DbModel().Title) 

     var newInstance = Expression.New(_instanceType); 
     var parameter = Expression.Parameter(typeof(TInput), "model"); 

     var getPropertyExpression = Expression.Property(newInstance, _propertyName); 
     var convertedProperty = Expression.Convert(getPropertyExpression, typeof(object)); 
     var lambdaExpression = Expression.Lambda(convertedProperty, parameter); 

     return (Expression<Func<TInput, object>>)lambdaExpression; 
    } 
} 

它为我

IDb obj = new DbModel(); 
sqlConnection.Insert(obj);