2014-06-06 22 views
19

Im Entity Framework Code Zuerst, wenn ich Entitäten deklariere, muss ich DbSet <> Art der Eigenschaften dafür verwenden. Zum Beispiel:Was ist der Unterschied zwischen DbSet <> und virtuellem DbSet <>?

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

Vor kurzem habe ich traf DbSet <> deklariert als virtuell.

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

Was ist der Unterschied? Welche EF-Funktionalitäten sind aktiviert?

Antwort

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

Das Schlüsselwort virtual auf die Navigationseigenschaften werden verwendet, faul Lademechanismus zu aktivieren, aber die LazyLoadingEnabled Eigenschaft der Konfiguration aktiviert werden muss.

Das virtuelle Schlüsselwort in der Navigationseigenschaft AccountType :: AccountCodes lädt alle Kontocodes in dem Moment, in dem programmgesteuert auf diese Eigenschaft zugegriffen wird, während der Datenbankkontext noch aktiv ist.

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

Während das virtuelle Schlüsselwort auf der abgeleiteten Klasse DbContext (virtual DbSet <>) für Testzwecke verwendet wird (die spöttischen DbSet Eigenschaft), virtuelles Schlüsselwort in diesem Fall ist nicht auf träges Laden verwendet.

===== ===== Update

Normalerweise machen wir die Tests gegen den Dienst/Logik, zum Beispiel haben wir eine weitere Schicht für den Kontotyp Dienst wie folgen. Und der Dienst akzeptiert die DB-Kontextinstanz mit einer Art der Abhängigkeitsinjektion über den Konstruktor.

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

Und jetzt müssen wir den Kontotyp-Service, in diesem Fall testen ich mstest und automoq verwendet, um die Mock-Klasse zu erstellen.

[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

Beachten Sie, dass in EF Core (derzeit 1.0 und 2.0) noch nicht Lazy Loading Schema unterstützt, so mit „virtuell“ mit oder ohne kein anderes machen.

FYI. Das Gerüst erzeugt "virtuell" Schlüsselwort kann LazyLoading-Technik in der zukünftigen Version von EF Core unterstützen!

(AFAIK in EF2.1 das Entwicklerteam Unterstützung für Lazy Loading hinzufügen könnte)

+0

Elementar virtuellen Mittel es in einer derriving Klasse außer Kraft gesetzt werden kann. – Nikolaus

Verwandte Themen