2017-07-11 9 views
0

を用い「NO列がマッピングされなかった」私はいくつかinterfaceを実装classを有します。例外がDapperの拡張

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

をしかし、私は、対応するinterfaceにキャストし、このclassのインスタンスを挿入しようとすると、それが例外を与える:このコードはうまく機能

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メソッド呼び出しでは、Dapperのマッピングを行う、ことがわかり、そしてClassMapper<>クラスに対応する構築。私たちはこの奇妙さを使うことができます。

このため、Insertメソッドを呼び出す前に、SharedStateを作成してインスタンス型を格納する必要があります。Dapperのマッピングを行いますときに我々は、このプロパティにアクセスすることができ、この後

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); 
のために働きます
関連する問題