2011-08-21 33 views
6

tôi vấp phải vấn đề tiếp theo ... Tôi có bối cảnh cơ sở dữ liệu:Sử dụng IQueryable <TEntity> thay DbSet <TEntity> vấn đề

// For support unit testing... 
public interface IDbContext : IDisposable 
{ 
    IQueryable<Hardware> Hardwares { get; } 
    IQueryable<ProviderHardware> ProviderHardwares { get; } 
} 

// Real DbContext (EF 4.0, Code First) 
public class PrimaryDbContext : DbContext, IDbContext 
{ 
    public DbSet<Hardware> Hardwares { get; set; } 
    public DbSet<ProviderHardware> ProviderHardwares { get; set; } 

    IQueryable<Hardware> IDbContext.Hardwares 
    { get { return Hardwares; } } 
    IQueryable<ProviderHardware> IDbContext.ProviderHardwares 
    { get { return ProviderHardwares; } } 
    ... 
} 

Và tôi cố gắng nhận được tất cả phần cứng, mà doesnt tồn tại trong bảng ProviderHardwares:

var hardwaresRemoved = db.Hardwares.Where(i => (i.IsAvailable == true) && 
    (db.ProviderHardwares.Count(j => j.Article == i.Article) == 0)).ToList(); 

Nếu tôi sử dụng PrimaryDbContext đúng như "PrimaryDbContext db = new PrimaryDbContext();" tất cả đều ổn. Nhưng nếu tôi sử dụng nó ngầm "IDbContext db = new PrimaryDbContext();" tôi có ngoại lệ:

Không thể tạo giá trị không đổi loại 'ConfiguratorMvcApplication.DomainModels.ProviderHardware'. Chỉ có loại nguyên thủy ('chẳng hạn như Int32, Chuỗi và Hướng dẫn') được hỗ trợ trong ngữ cảnh này.

Tóm tắt, tôi không thể thay thế DbSet trên IQueryable. Và làm thế nào tôi có thể sử dụng thử nghiệm đơn vị trong trường hợp này? Tôi hy vọng một người nào đó đã giải quyết vấn đề này ... Cảm ơn trước rất nhiều!

+0

Bạn có khai báo hằng số ở bất kỳ đâu trong 'PrimaryDbContext' không? –

+0

Không, chỉ có tôi chứng minh trước đây ... Và ghi đè lên phương pháp OnModelCreating nhiều hơn nữa ... – xtmq

+0

Tôi có thể tạo lại điều này. Tôi cũng thấy (với SQL Profiler) rằng trong trường hợp 'IDbContext'' db.ProviderHardwares' bên trong biểu thức được thực hiện như một truy vấn tải * tất cả * 'ProviderHardware' hàng từ cơ sở dữ liệu (* như thể *' IDbContext.ProviderHardwares 'là một 'IEnumerable' và không phải' IQueryable'). Sau đó, 'Đếm' và truy vấn bên ngoài không thể được thực thi vì danh sách bộ nhớ của các đối tượng (danh sách các đối tượng" hằng số ") không thể được sử dụng trong SQL. Điều này gây ra ngoại lệ. Tại sao EF xử lý 'IDbContext.ProviderHardwares' như một' IEnumerable' nhưng không phải là 'PrimaryDbContext.ProviderHardwares'? Không có đầu mối ... – Slauma

Trả lời

-2

tôi đề nghị bạn giữ tốt hơn DbSets và làm HỘI NHẬP KIỂM TRAbao gồm cơ sở dữ liệu.

Bởi vì, mặc dù vượt qua bài kiểm tra đơn vị với mô hình DB có thể hữu ích, bạn sẽ được kiểm tra tốt hơn với cơ sở dữ liệu thực (nhưng không phải kiểm tra đơn vị).

Khi ClassInitialize xóa cơ sở dữ liệu và/hoặc tạo dữ liệu ban đầu để thử nghiệm.

Nếu bạn tạo tệp App.config bằng chuỗi kết nối, bạn có thể có cơ sở dữ liệu thử nghiệm riêng biệt và nếu bạn đang sử dụng mã EF đầu tiên, bạn sẽ nhận được miễn phí.

Trân trọng.

+0

Có, tôi nghĩ rằng bạn đang phải .. Nhưng làm thế nào tôi có thể tạo và điền vào cơ sở dữ liệu trong mã? Tôi có thể tạo các đối tượng miền trong PrimaryDbContext. Tôi có thể tạo cơ sở dữ liệu có chứa các đối tượng này trên máy chủ sql cục bộ thông qua các công cụ đầu tiên của mã EF tự động không? và sử dụng nó trong các bài kiểm tra của tôi? – xtmq

+0

Có, sử dụng mã số EF Đầu tiên, cơ sở dữ liệu có thể được tạo và điền vào lần đầu tiên ứng dụng của bạn chạy, hãy xem hướng dẫn này: (http://www.asp.net/entity-framework/tutorials/creating-an-entity-framework -data-model-for-an-asp-net-mvc-ứng dụng). Một điểm cộng nữa là nếu bạn tạo một tệp App.config trong dự án thử nghiệm, bạn sẽ có cơ sở dữ liệu thử nghiệm miễn phí, độc lập với cơ sở dữ liệu phát triển của bạn. Tôi đề nghị bạn sử dụng SQL Server Compact 4.0. –

+0

Cảm ơn, tôi đang chạy để đọc hướng dẫn này =) – xtmq

1

Tôi đã kết thúc có hai thuộc tính cho mỗi DbSet: một loại IQueryable và một loại DbSet. Thuộc tính IQueryable được định nghĩa trong giao diện, và nó chuyển tiếp các cuộc gọi đến việc thực hiện bê tông (loại tài sản của DbSet), như sau:

// Exists in the interface 
public IQueryable<AccountContact> AccountContacts 
{ 
    get 
    { 
     return DbAccountContacts; 
    } 
    set 
    { 
     DbAccountContacts = (DbSet<AccountContact>)value; 
    } 
} 

// Exists only in the implementation 
public DbSet<AccountContact> DbAccountContacts { get; set; } 

Có thiết lập này, tôi đã có thể để có được chế giễu để làm việc một cách chính xác và đơn vị có thể kiểm tra mã.

Điều này chắc chắn là quá muộn cho OP, nhưng có lẽ điều này sẽ giúp một người đang đấu tranh với cùng một câu hỏi, như tôi đã làm.

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