2017-08-10 11 views
-1

私はasp.net Web API RESTサービスを開発中です。私のデータはMySQLリレーショナルデータベースに保存されています。データアクセス層ではDapperマイクロORMを使用したいので、私は自分のORMラッパーメソッドを作成したいと思います。私が将来他のORMに変更することを決めたら、DALレイヤコード全体を書き直す必要はありません。カスタムC#Dapper ORMラッパー

私のアプローチについてどう思いますか?コードは次のとおりです。

public abstract class BaseORMCommandSettings //SQL command base class 
{ 
    public string CommandText { get; private set; } 
    public object Parameters { get; private set; } 
    public IDbTransaction Transaction { get; private set; } 
    public int? CommandTimeout { get; private set; } 
    public CommandType? CommandType { get; private set; } 
    public CancellationToken CancellationToken { get; private set; } 

    public BaseORMCommandSettings(string commandText, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null, 
          CommandType? commandType = null, CancellationToken cancellationToken = default(CancellationToken)) 
    { 
     this.CommandText = commandText; 
     this.Parameters = parameters; 
     this.Transaction = transaction; 
     this.CommandTimeout = commandTimeout; 
     this.CommandType = commandType; 
     this.CancellationToken = cancellationToken; 
    } 
} 

public class DapperCommandSettings : BaseORMCommandSettings//dapper cmd impl 
{ 
    public CommandFlags Flags { get; private set; } 

    public DapperCommandSettings(string commandText, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null, 
          CommandType? commandType = null, CancellationToken cancellationToken = default(CancellationToken), CommandFlags flags = CommandFlags.Buffered) 
     :base(commandText, parameters, transaction, commandTimeout, commandType, cancellationToken) 
    { 
     this.Flags = flags; 
    } 
} 

public interface ICustomORM //base interface, for now have only generic Read 
          list method 
{ 
    IEnumerable<T> Read<T>(BaseORMCommandSettings cmd); 
} 

public class DapperORM : ICustomORM //my own dapper ORM wrapper implentation 
{ 
    private readonly IDbConnection con; 

    public DapperORM(IDbConnection con) 
    { 
     this.con = con; 
    } 

    public IEnumerable<T> Read<T>(BaseORMCommandSettings cmd) 
    { 
     var cmdDapper = cmd as DapperCommandSettings; 
     var dapperCmd = new CommandDefinition(cmdDapper.CommandText, cmdDapper.Parameters, cmdDapper.Transaction, 
               cmdDapper.CommandTimeout, cmdDapper.CommandType, cmdDapper.Flags, 
               cmdDapper.CancellationToken); 

     return con.Query<T>(dapperCmd); 
    } 
} 

ご協力いただきありがとうございます。

+0

[SO]は、コードレビューに関するものではありません、おそらくあなたはhttps://codereview.stackexchange.com/ – Richard

+0

感謝のに尋ねるべきあなたの答えに...。実際には私が使っている技術をかなり簡単に素早く変更できるコードを書くために、自分のコード実装に関する誰かの意見を聞きたいのですが...これはコードレビューではなくデザインに関するものです。 – user2214626

答えて

2

である。しないでください。 Dapperは存在し、ADOを行うための簡潔で表情豊かな方法を提供するため、成功しています。 ORMではありません。あなたが大札を包むならば、簡潔な表現力のあるインターフェースを失い、あなたはその点を失います。 DBの移植性を提供するためにORM(一部のDApperはありません)が一部存在します。 ORMの移植性について話を始めると、民間人は絶望して壁に向かって頭を叩くのです! Dapperを使い、それを賞賛してください。

+0

Dapperチームがステップバイステップまたはベストプラクティスの完全なサンプル実装を提供できるのであれば、Dapperに来ることを望んでいる新しいユーザーのために多くの推測作業を取り除くことができます。 readme.mdは適切ではありません。 –

0

私はオブジェクト指向のために行くことをお勧めし、いくつかのオブジェクト型のシーケンスを返すメソッドが1つしかないオブジェクトを作成します。このようにして、PAgeオブジェクトを作成し、そのコンストラクタを介してパラメータを渡すことで、異なる種類のページ(SqlPages、DapperPages、TestablePagesなど)を作成できます。このように柔軟な作業方法があり、コードを作成し、インフラストラクチャ/データベースの詳細を最後に実装することができます。私は、オブジェクトの内部dtabasesの詳細をカプセル化の詳細は、あなたのコードを介して広がるせていけないでしょう:

/// <summary> 
/// DTO 
/// </summary> 
public class MyDto 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Value { get; set; } 
} 

/// <summary> 
/// Define a contract that get a sequence of something 
/// </summary> 
/// <typeparam name="T"></typeparam> 
public interface IFetch<T> 
{ 
    IEnumerable<T> Fetch(); 
} 

/// <summary> 
/// Define a pageTemplate 
/// </summary> 
/// <typeparam name="T"></typeparam> 
public abstract class PageTemplate<T> : IFetch<T> 
{ 
    protected readonly int pageSize; 
    protected readonly int page; 

    public PageTemplate(int page, int pageSize) 
    { 
     this.page = page; 
     this.pageSize = pageSize; 
    } 
    public abstract IEnumerable<T> Fetch(); 
} 

/// <summary> 
/// Design a MyDto Page object, Here you are using the Template method 
/// </summary> 
public abstract class MyDtoPageTemplate : PageTemplate<MyDto> 
{ 
    public MyDtoPageTemplate(int page, int pageSize) : base(page, pageSize) { } 
} 

/// <summary> 
/// You can use ado.net for full performance or create a derivated class of MyDtoPageTemplate to use Dapper 
/// </summary> 
public sealed class SqlPage : MyDtoPageTemplate 
{ 
    private readonly string _connectionString; 
    public SqlPage(int page, int pageSize, string connectionString) : base(page, pageSize) 
    { 
     _connectionString = connectionString; 
    } 

    public override IEnumerable<MyDto> Fetch() 
    { 
     using (var connection = new SqlConnection(_connectionString)) 
     { 
      //This can be injected from contructor or encapsulated here, use a Stored procedure, is fine 
      string commandText = "Select Something"; 
      using (var command = new SqlCommand(commandText, connection)) 
      { 
       connection.Open(); 
       using (var reader = command.ExecuteReader()) 
       { 
        if (reader.HasRows) yield break; 
        while (reader.Read()) 
        { 
         yield return new MyDto() 
         { 
          Id = reader.GetInt32(0), 
          Name = reader.GetString(1), 
          Value = reader.GetString(2) 
         }; 
        } 
       } 
      } 
     } 
    } 
} 

/// <summary> 
/// You can test and mock the fetcher 
/// </summary> 
public sealed class TestPage : IFetch<MyDto> 
{ 
    public IEnumerable<MyDto> Fetch() 
    { 
     yield return new MyDto() { Id = 0, Name = string.Empty, Value = string.Empty }; 
     yield return new MyDto() { Id = 1, Name = string.Empty, Value = string.Empty }; 
    } 
} 

public class AppCode 
{ 
    private readonly IFetch<MyDto> fetcher; 
    /// <summary> 
    /// From IoC, inject a fetcher object 
    /// </summary> 
    /// <param name="fetcher"></param> 
    public AppCode(IFetch<MyDto> fetcher) 
    { 
     this.fetcher = fetcher; 
    } 
    public IEnumerable<MyDto> FetchDtos() 
    { 
     return fetcher.Fetch(); 
    } 
} 

public class CustomController 
{ 
    private readonly string connectionString; 

    public void RunSql() 
    { 
     var fetcher = new SqlPage(1, 10, connectionString); 
     var appCode = new AppCode(fetcher); 
     var dtos = appCode.FetchDtos(); 
    } 

    public void RunTest() 
    { 
     var fetcher = new TestPage(); 
     var appCode = new AppCode(fetcher); 
     var dtos = appCode.FetchDtos(); 
    } 
}