首先在实体框架代码中,当我声明实体时,我必须使用DbSet<>类型的属性。例如:
public DbSet<Product> Products { get; set; }
public DbSet<Customer> Customers { get; set; }最近,我遇到了被声明为虚拟的DbSet<>。
public virtual DbSet<Product> Products { get; set; }
public virtual DbSet<Customer> Customers { get; set; }有什么关系?启用了哪些EF功能?
发布于 2014-06-09 13:39:49
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; }
}导航属性上的LazyLoadingEnabled关键字用于启用延迟加载机制,但必须启用配置的virtual属性。
AccountType::AccountCodes导航属性上的virtual关键字将在以编程方式访问AccountType::AccountCodes导航属性时加载所有帐户代码,同时db上下文仍然有效。
using (var context = new AppContext())
{
var accountType = context.AccountTypes.FirstOrDefault();
var accountCodes = accountType.AccountCodes;
}虽然派生的DbContext类(虚拟DbSet<>)上的虚拟关键字用于测试目的(模拟DbSet属性),但本例中的虚拟关键字与延迟加载无关。
=====更新=====
通常我们针对服务/逻辑进行测试,例如,我们为帐户类型服务提供了另一个层,如下所示。并且服务通过构造器使用某种依赖注入来接受db上下文实例。
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;
}
}现在我们需要测试account类型的服务,在本例中,我使用mstest和automoq来创建模拟类。
[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);
}
}发布于 2017-11-29 05:17:22
请注意,在EF核心(当前1.0和2.0)中仍然不支持LazyLoading方案,所以使用“虚拟”或不使用并不会产生不同的结果。
仅供参考。脚手架生成“虚拟”关键字可能会在EF核心的未来版本中支持LazyLoading技术!
在EF Core2.1中,开发团队添加了对LazyLoading的支持。有关更多信息,请访问here。
https://stackoverflow.com/questions/24079133
复制相似问题