2014-06-06 44 views
19

Trong mã khung thực thể Trước tiên, khi tôi khai báo các thực thể, tôi phải sử dụng DbSet <> loại thuộc tính cho điều đó. Ví dụ:Sự khác biệt giữa DbSet <> và DbSet ảo <> là gì?

public DbSet<Product> Products { get; set; } 
public DbSet<Customer> Customers { get; set; } 

Gần đây tôi đã gặp DbSet <> được khai báo là ảo.

public virtual DbSet<Product> Products { get; set; } 
public virtual DbSet<Customer> Customers { get; set; } 

Sự khác biệt là gì? Chức năng EF nào được kích hoạt?

Trả lời

14
public class AppContext : DbContext 
{ 
    public AppContext() 
    { 
     Configuration.LazyLoadingEnabled = true; 
    } 

    public virtual DbSet<AccountType> AccountTypes { get; set; } 
} 

public class AccountType 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<AccountCode> AccountCodes { get; set; } 
} 

public class AccountCode 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public Guid AccountTypeId { get; set; } 
    public virtual AccountType AccountType { get; set; } 
} 

Từ khóa ảo trên thuộc tính điều hướng được sử dụng để bật cơ chế tải lười, nhưng phải bật thuộc tính LazyLoadingEnabled.

Từ khóa ảo trên AccountType :: Tài khoản điều hướng tài khoản sẽ tải tất cả các mã tài khoản vào thời điểm có quyền truy cập theo chương trình vào thuộc tính đó trong khi ngữ cảnh db vẫn còn hoạt động.

using (var context = new AppContext()) 
{ 
    var accountType = context.AccountTypes.FirstOrDefault(); 
    var accountCodes = accountType.AccountCodes; 
} 

Trong khi từ khóa ảo trên lớp DbContext nguồn gốc (ảo DbSet <>) được sử dụng cho mục đích thử nghiệm (chế giễu tài sản DbSet), từ khóa ảo trong trường hợp này không liên quan đến tải lười biếng.

cập nhật ===== =====

Thông thường chúng ta đang làm việc thử nghiệm chống lại các dịch vụ/logic, ví dụ chúng ta có một lớp cho dịch vụ loại tài khoản như sau. Và dịch vụ chấp nhận cá thể ngữ cảnh db bằng cách sử dụng một số loại tiêm phụ thuộc thông qua hàm tạo.

public class AccountTypeService 
{ 
    public AppContext _context; 

    public AccountTypeService(AppContext context) 
    { 
     _context = context; 
    } 

    public AccountType AddAccountType(string name) 
    { 
     var accountType = new AccountType { Id = Guid.NewGuid(), Name = name }; 
     _context.AccountTypes.Add(accountType); 
     _context.SaveChanges(); 
     return accountType; 
    } 
} 

Và bây giờ chúng ta cần phải kiểm tra dịch vụ loại tài khoản, trong trường hợp này tôi đã sử dụng MSTest và automoq để tạo ra các lớp học giả.

[TestClass] 
public class AccountTypeServiceTest 
{ 
    [TestMethod] 
    public void AddAccountType_NormalTest() 
    { 
     // Arranges. 
     var accountTypes = new List<AccountType>(); 
     var accountTypeSetMock = new Mock<DbSet<AccountType>>(); 
     accountTypeSetMock.Setup(m => m.Add(It.IsAny<AccountType>())).Callback<AccountType>(accountType => accountTypes.Add(accountType)); 

     var appContextMock = new Mock<AppContext>(); 
     appContextMock.Setup(m => m.AccountTypes).Returns(accountTypeSetMock.Object); 
     var target = new AccountTypeService(appContextMock.Object); 

     // Acts. 
     var newAccountType = target.AddAccountType("test"); 

     // Asserts. 
     accountTypeSetMock.Verify(m => m.Add(It.IsAny<AccountType>()), Times.Once()); 
     appContextMock.Verify(m => m.SaveChanges(), Times.Once()); 
     Assert.AreEqual(1, accountTypes.Count); 
     Assert.IsNotNull(newAccountType); 
     Assert.AreNotEqual(Guid.Empty, newAccountType.Id); 
     Assert.AreEqual("test", newAccountType.Name); 
    } 
} 
0

Lưu ý rằng trong EF Core (hiện 1.0 và 2.0) vẫn không hỗ trợ chương trình LazyLoading, vì vậy sử dụng với "ảo" hoặc không có không làm cho một khác nhau.

FYI. Giàn giáo tạo ra "ảo" từ khóa có thể hỗ trợ kỹ thuật LazyLoading trong phiên bản tương lai của EF Core!

(AFAIK trong EF2.1 nhóm nhà phát triển có thể thêm hỗ trợ cho LazyLoading)

+0

Ảo cơ bản có nghĩa là nó có thể bị ghi đè trong lớp học phát sinh. – Nikolaus

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