2017-08-10 68 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(); 
    } 
}