2014-06-06 14 views
19

W Entity Framework Code Najpierw, kiedy deklaruję podmioty, muszę użyć DbSet <> Typ właściwości dla tego. Na przykład:Jaka jest różnica między DbSet <> a wirtualnym DbSet <>?

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

Ostatnio poznałem DbSet <> zadeklarowane jako wirtualny.

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

Jaka jest różnica? Jakie funkcjonalności EF są włączone?

Odpowiedz

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; } 
} 

Słowo kluczowe virtual na właściwości nawigacyjnych są wykorzystywane w celu umożliwienia leniwy mechanizm ładowania, ale LazyLoadingEnabled własność konfiguracji musi być włączona.

Wirtualne słowo kluczowe w AccountType :: Właściwość nawigacji AccountCodes załaduje wszystkie kody kont w momencie, gdy programowo uzyska dostęp do tej właściwości, gdy kontekst db będzie nadal istnieć.

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

Choć słowo kluczowe virtual na pochodnej klasy DbContext (wirtualny DbSet <>) jest używany do celów testowania (kpiącym właściwość DbSet), wirtualnego słowo kluczowe w tym przypadku nie jest związane z leniwe załadunku.

===== aktualizacja =====

Zazwyczaj robimy badania pod kątem usług/logiczne, na przykład mamy kolejną warstwę dla usługi typu konto następująco. Usługa akceptuje instancję kontekstu db za pomocą pewnego rodzaju iniekcji zależności za pośrednictwem konstruktora.

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; 
    } 
} 

A teraz musimy przetestować usługę typu konto, w tym przypadku użyłem mstest i automoq do stworzenia klasy próbnej.

[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

Należy zauważyć, że nie jest EF rdzeń (obecnie 1,0 a 2,0) nadal wspiera system LazyLoading, więc przy użyciu z „wirtualny” lub bez nie wykorzysta różne.

FYI. Rusztowanie generuje "wirtualne" słowo kluczowe może wspierać technikę LazyLoading w przyszłej wersji EF Core!

(AFAIK w EF2.1 zespół programista może dodać wsparcie dla LazyLoading)

+0

elementarne środki wirtualne mogą być nadpisane w klasie derriving. – Nikolaus

Powiązane problemy