2017-08-10 23 views
-1

我正在開發asp.net web API REST服務。我的數據存儲在MySQL關係數據庫中。在數據訪問層,我想使用Dapper微型ORM,所以我想創建一些我自己的ORM包裝方法。如果我決定在將來更改爲其他ORM,我不需要重寫我的整個DAL層代碼。Custom C#Dapper ORM wrapper

您如何看待我的方法?這裏是代碼:

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。如果你包裝精靈,你會失去簡潔的表達界面,並且你失去了重點。 ORM的(不是短小精悍)部分地存在以提供DB便攜性。開始談論ORM的便攜性會讓人們在絕望中撞牆!只需使用Dapper並欣賞它。

+0

也許如果Dapper團隊可以提供完整的示例實施方案,並且可以逐步執行或者甚至是最佳實踐,那麼對於希望進入Dapper的新用戶來說,這會帶走很多猜測工作。 readme.md遠遠不夠。 –

0

我建議你去一個面向對象設計,並創建一個對象,只有一個方法返回一些對象類型的序列。通過這種方式,您可以創建一個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(); 
    } 
}