首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DbSet<>和虚拟DbSet<>之间的区别是什么?

DbSet<>和虚拟DbSet<>之间的区别是什么?
EN

Stack Overflow用户
提问于 2014-06-06 18:00:08
回答 2查看 23.4K关注 0票数 50

首先在实体框架代码中,当我声明实体时,我必须使用DbSet<>类型的属性。例如:

代码语言:javascript
复制
public DbSet<Product> Products { get; set; }
public DbSet<Customer> Customers { get; set; }

最近,我遇到了被声明为虚拟的DbSet<>。

代码语言:javascript
复制
public virtual DbSet<Product> Products { get; set; }
public virtual DbSet<Customer> Customers { get; set; }

有什么关系?启用了哪些EF功能?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-09 13:39:49

代码语言:javascript
复制
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上下文仍然有效。

代码语言:javascript
复制
using (var context = new AppContext())
{
    var accountType = context.AccountTypes.FirstOrDefault();
    var accountCodes = accountType.AccountCodes;
}

虽然派生的DbContext类(虚拟DbSet<>)上的虚拟关键字用于测试目的(模拟DbSet属性),但本例中的虚拟关键字与延迟加载无关。

=====更新=====

通常我们针对服务/逻辑进行测试,例如,我们为帐户类型服务提供了另一个层,如下所示。并且服务通过构造器使用某种依赖注入来接受db上下文实例。

代码语言:javascript
复制
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来创建模拟类。

代码语言:javascript
复制
[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);
    }
}
票数 29
EN

Stack Overflow用户

发布于 2017-11-29 05:17:22

请注意,在EF核心(当前1.0和2.0)中仍然不支持LazyLoading方案,所以使用“虚拟”或不使用并不会产生不同的结果。

仅供参考。脚手架生成“虚拟”关键字可能会在EF核心的未来版本中支持LazyLoading技术!

在EF Core2.1中,开发团队添加了对LazyLoading的支持。有关更多信息,请访问here

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24079133

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档