2016-08-08 21 views
6

Tôi đang cố chuyển đổi từ Entity Framework sang Dapper để cải thiện hiệu suất truy cập dữ liệu.Cách sử dụng Dapper với LINQ

Các truy vấn tôi sử dụng ở dạng các vị từ như "Biểu thức>".

Để đưa ra ví dụ:

Tôi có mã sau đây mà tôi cần chuyển đổi sang sử dụng Dapper.

Những gì tôi đang làm:

public async Task<List<TModel>> Get(Expression<Func<TModel, bool>> query) 
{ 
    // this.Context is of type DbContext 
    return await this.Context.Set<TModel>().Where(query).ToListAsync(); 
} 

Những gì tôi muốn làm:

public async Task<List<TModel>> Get(Expression<Func<TModel, bool>> query) 
{ 
    using (IDbConnection cn = this.GetConnection) 
    { 
     return await cn.QueryAsync<TModel>(query); 
    } 
} 

My google-fu là không cho tôi, ai đó có thể xin vui lòng giúp đỡ.

Edit:

Lưu ý rằng tôi đã tìm thấy: https://github.com/ryanwatson/Dapper.Extensions.Linq

nhưng tôi dường như không thể tìm ra cách để sử dụng nó.

+1

LINQ to EF xây dựng câu lệnh SQL từ mô hình thực thể và biến vị ngữ LINQ. Dapper thực hiện các câu lệnh SQL thực tế và "đơn giản" ánh xạ các kết quả. Bạn sẽ phải viết câu lệnh SQL được tham số hóa SQL đầy đủ. –

+0

Nói cách khác, bạn có chắc là bạn không giải quyết được vấn đề * sai? Bạn có thể chỉ cần thêm mệnh đề where-another-Where vào bất kỳ truy vấn nào bạn có, ví dụ 'var query = context.SomeEntity.Where() ....; query = query.Where (...); query = query.Select (...); '. Bạn không cần phải làm việc với các biểu thức nếu bạn chỉ muốn thêm bộ lọc vào một truy vấn hiện có. Di chuyển đến một vi-ORM sẽ không làm cho việc xây dựng thời gian chạy các truy vấn dễ dàng hơn –

+0

cho Dapper, cn.QueryAsync (truy vấn), truy vấn phải là chuỗi sql không Biểu thức >. Bạn phải thay đổi lớn trong việc chuyển đổi từ EF. để Dapper. –

Trả lời

13

Thứ nhất, một trong những tác giả của Dapper cho biết, khi ai đó hỏi

Có một kế hoạch để làm cho Dapper.net tương thích với giao diện IQueryable?

rằng

không có kế hoạch để làm điều này. Nó ở xa bên ngoài những gì người lập bản đồ cố gắng làm. Cho đến nay tôi sẽ nói nó là phản đối. Dapper core cố gắng làm bạn với những người yêu thích SQL của họ.

(xem https://stackoverflow.com/a/27588877/3813189).

Nói cách khác, điều đó gợi ý rằng các gói mở rộng khác nhau cho NuGet có thể giúp bạn, như bạn đã đề xuất.

Tôi đã thử DapperExtensions, giúp việc viết bộ lọc truy vấn theo cách có lập trình dễ dàng hơn một chút - ví dụ:

using System.Data.SqlClient; 
using DapperExtensions; 

namespace StackOverflowAnswer 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var cn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;")) 
      { 
       var list = cn.GetList<Products>(
        Predicates.Field<Products>(f => f.Discontinued, Operator.Eq, false) 
       ); 
      } 
     } 

     class Products 
     { 
      public int ProductId { get; set; } 
      public string ProductName { get; set; } 
      public bool Discontinued { get; set; } 
     } 
    } 
} 

Tôi cũng đã cố gắng Dapper.Extensions.Linq (gói bạn đề nghị), trong đó hứa hẹn sẽ

được xây dựng trên này cung cấp truy cập DB tiên tiến qua các truy vấn LINQ. Cấu hình chất lỏng giúp thiết lập đơn giản và nhanh chóng.

Thật không may, tôi cũng không thể đi xa lắm. Không có nhiều tài liệu và các bài kiểm tra dường như không bao gồm QueryBuilder, đó là những gì dường như là lớp để sử dụng để dịch Biểu thức LINQ thành các biến vị ngữ Dapper Extensions (như đề xuất bởi số Parsing boolean expressions with the QueryBuilder). Tôi đã thử những điều sau, yêu cầu thêm giao diện IEntity vào DTO của tôi -

using System; 
using System.Data.SqlClient; 
using System.Linq.Expressions; 
using Dapper.Extensions.Linq.Builder; 
using Dapper.Extensions.Linq.Core; 
using DapperExtensions; 

namespace StackOverflowAnswer 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var cn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;")) 
      { 
       Expression<Func<Products, bool>> filter = p => !p.Discontinued; 
       var queryFilter = QueryBuilder<Products>.FromExpression(filter); 

       var list = cn.GetList<Products>(
        queryFilter 
       ); 
      } 
     } 

     class Products : IEntity 
     { 
      public int ProductId { get; set; } 
      public string ProductName { get; set; } 
      public bool Discontinued { get; set; } 
     } 
    } 
} 

..nhưng nó đã thất bại khi chạy với lỗi

điều hành đã không được tìm thấy cho StackOverflowAnswer.Program + Sản phẩm

Tôi không chắc chắn lý do tại sao tạo ra Predicate bằng tay (ví dụ đầu tiên) hoạt động nhưng QueryBuilder doesn 't ..

Tôi có thể nói rằng ngày càng giống các nhận xét còn lại trên câu hỏi của bạn là chính xác, bạn sẽ cần phải làm việc lại mã của bạn khỏi các biểu thức bạn đã sử dụng với Khung thực thể. Do rất khó tìm thấy bất kỳ thông tin nào về lớp QueryBuilder này, tôi sẽ lo ngại rằng (ngay cả khi bạn đã làm việc đó), bất kỳ vấn đề nào bạn gặp phải sẽ rất khó khăn để nhận được sự trợ giúp (và các lỗi có thể bị lỗi).

+1

Cảm ơn bạn đã dành thời gian để xem xét câu hỏi của tôi. Tôi hạnh phúc (và buồn) rằng ai đó đã đi đến cùng một kết luận mà tôi có. Cảm ơn nhiều. –

5

Tôi đã viết một tiện ích để làm việc EF với Dapper bằng cách sử dụng các thuộc tính. Tôi phân tích cú pháp vị ngữ và dịch sang SQL.

"Người dùng" poco:

[Table("Users")] 
public class User 
{ 
    [Key] 
    [Identity] 
    public int Id { get; set; } 

    public string Login { get; set;} 

    [Column("FName")] 
    public string FirstName { get; set; } 

    [Column("LName")] 
    public string LastName { get; set; } 

    public string Email { get; set; } 

    [NotMapped] 
    public string FullName 
    { 
     get 
     { 
      return string.Format("{0} {1}", FirstName, LastName); 
     } 
    } 
} 

Và truy vấn đơn giản:

using (var cn = new SqlConnection("...")) 
{ 
    var usersRepository = new DapperRepository<User>(cn) 
    var allUsers = await userRepository.FindAllAsync(x => x.AccountId == 3 && x.Status != UserStatus.Deleted); 
} 

Có lẽ nó sẽ hữu ích đối với bạn?

MicroOrm.Dapper.Repositories

+3

Tôi hiểu rằng câu trả lời của bạn không phải là câu trả lời cho câu hỏi ban đầu, bởi vì bạn không sử dụng LINQ. Tuy nhiên, giải pháp của bạn là bất kỳ ai gần nhất sẽ nhận được các biểu thức truy vấn an toàn loại, không cần sử dụng Khuôn khổ thực thể. Kinh ngạc! Làm tốt lắm! –

Các vấn đề liên quan