2016-08-26 11 views
7

Tôi đang triển khai Mô hình bằng EF 6.1.3 và .NET Framework 4.6.1. Mô hình này được sử dụng bởi một ứng dụng ASPNET và bởi một ứng dụng ASPNET CORE, vì lý do đó nó sử dụng System.Data.Entity và nó nằm trong một mymodel.dll lắp ráp riêng biệt.Chỉ những nguồn triển khai IAsyncEnumerable mới có thể được sử dụng cho các hoạt động không đồng bộ của Entity Framework

Đây là mô hình

using System.Data.Entity; 
public partial class MyDbContext : DbContext 
{  
     public virtual DbSet<Athlete> Athletes{ get; set; } 
} 
public partial class Athlete 
{ 
    public Athlete() 
    { 
    } 
    //... 
    public string Country { get; set; } 
} 

Tôi đang phát triển ứng dụng MVC được thực hiện trong lõi aspnet với .NET Framework 4.6. Nó tham khảo EF 6.1.3 sao cho mô hình có thể được sử dụng.

public class MyViewModel 
{ 
    public IList<Athlete> ItalianAthletes{ get; set; } 
} 

using Microsoft.EntityFrameworkCore; 
//solution: comment the previous line and use instead System.Data.Entity; 
public class MyController : Controller 
{ 
    private readonly MyDbContext _context; 
    //... 
    public IActionResult Index() 
    { 
     MyViewModel myvm = new MyViewModel(); 
     var result = _context.Athletes.Where(a=>a.Country=="Italy").ToList(); 
     myvm.ItalianAthletes = result ; 
     return View(myvm); 
    } 
} 

... và nó hoạt động như mong đợi.

Bây giờ thay đổi phương pháp Chỉ số async

public async Task<IActionResult> Index() 
{ 
    MyViewModel myvm = new MyViewModel(); 
    var result = _context.Athletes.Where(a=>a.Country=="Italy").ToListAsync(); 
    await result; //at this point an exception is thrown 
    //... 
} 

InvalidOperationException: Nguồn IQueryable không thực hiện IAsyncEnumerable. Chỉ những nguồn thực hiện IAsyncEnumerable mới có thể được sử dụng cho các hoạt động không đồng bộ của Entity Framework.

Xóa mệnh đề Where() vẫn tồn tại, vì vậy vấn đề có vẻ liên quan đến ToListAsync();

var result = _context.Users.ToListAsync(); 

Cẩn thận đọc văn bản của ngoại lệ Tôi hiểu rằng "IQueryable tạo ra bởi ToList() doesnt thực hiện IAsyncEnumerable" nhưng điều này không có ý nghĩa với tôi bởi vì tất cả những gì hành vi là nội bộ để ToListAsync();

Ai đó có thể giúp tôi hiểu rõ hơn những gì đang xảy ra ở đây dưới mui xe? và tôi có thể làm gì để ToListAsync() hoạt động như mong đợi?

cảm ơn bạn trước vì bất kỳ nhận xét nào

+1

có thể được trợ giúp cho bạn: https://msdn.microsoft.com/en-us/data/dn313107 – Sampath

+0

chỉnh sửa mã bằng giải pháp –

Trả lời

10

Bạn sẽ muốn thực hiện một trong 2 điều sau.

Tham khảo gói nuget EF trong cả hai cụm. Điều này là do hoạt động ToListAsync() này thực sự được gọi đến EF DbContext của bạn và điều này không thể thực hiện được từ dự án không có tham chiếu đến EF NugetPackage. Nếu đây là trường hợp đã chắc chắn rằng bạn đang tham chiếu không gian tên System.Data.Entity trong những điều khoản sử dụng ở phía trên cùng của mã:

using System.Data.Entity; 

vì đây là vị trí của phương pháp khuyến nông ToListAsync bạn muốn gọi.


Bỏ mã lấy từ EF trong một dịch vụ trong dự án sử dụng EF, thực hiện cuộc gọi không đồng bộ và gọi từ dự án asp.net MVC của bạn. Đây sẽ là lựa chọn ưa thích của tôi vì nó thêm một lớp trừu tượng tốt đẹp và làm cho mã của bạn dễ dàng hơn để kiểm tra/duy trì.

Mã ví dụ cho lựa chọn thứ 2

public interface IAthleteService { 
    Task<List<Athlete>> GetAthletesByCountryAsync(string country, CancellationToken token); 
} 

public class AthleteService : IAthleteService { 
    private MyDbContext _context; 
    public async Task<List<Athlete>> GetAthletesByCountryAsync(string country, CancellationToken token) 
    { 
     return await _context.Athletes.Where(athlete => athlete.Country == country).ToListAsync(token).ConfigureAwait(false); 
    } 
} 

public class MyController : Controller 
{ 
    private readonly IAthleteService _service; 
    //... 
    public async Task<IActionResult> Index(CancellationToken token) 
    { 
     MyViewModel myvm = new MyViewModel(); 
     myvm.ItalianAthletes = await _service.GetAthletesByCountryAsync("Italy", token).ConfigureAwait(true); 
     // rest of code 
    } 
} 

Ghi chú:

  • tôi đã sử dụng một CancellationToken, nó cho phép hủy của một hoạt động async. Điều này là hoàn toàn tùy chọn.
  • Tôi đã sử dụng ConfigureAwait, điều này cho phép bạn chỉ định bất kỳ nơi nào trong cùng một bối cảnh chủ đề sẽ được lấy lại khi hoạt động tiếp tục. Nó tiết kiệm tài nguyên để không làm điều đó (vượt qua sai) nhưng bạn chỉ có thể làm điều đó khi có thể. Trong ví dụ trên được thực hiện trong thư viện. Cũng trong ví dụ trên, nó không được thực hiện từ Controller bởi vì bạn cần ngữ cảnh của Http được kết hợp với luồng (pass true).
  • Tôi không tính đến việc xóa tài nguyên (như làm cho AthleteService dùng một lần để dọn dẹp DbContext) hoặc bất kỳ sự tiêm phụ thuộc nào.
+0

cả hai hội đồng đã tham chiếu EF. 6.1.3 (đã chỉnh sửa câu hỏi của tôi) –

+1

@RobertoVanoli - bạn có chắc chắn rằng 'using System.Data.Entity;' được bao gồm trong tệp mã Bộ điều khiển của bạn ở trên cùng không? Không gian tên này chứa phương thức mở rộng bạn muốn gọi. – Igor

+0

Bạn đã đoán đúng là tôi đã tham chiếu sai EF. Hiệu quả tôi đã sử dụng Microsoft.EntityFrameworkCore trong bộ điều khiển của tôi, sử dụng thay vì System.Data.Entity chính xác ToListAsync() phương pháp được gọi là bây giờ (không rõ tại sao phiên bản ToList() đã làm việc trước). PS: Tôi sẽ thêm +1 cho các đề xuất bổ sung của bạn nhưng danh tiếng của tôi không cho phép tôi bỏ phiếu tại thời điểm này :-( Cảm ơn bạn và chúc mừng –

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