DbSet<>和有什么区别?和虚拟DbSet<&gt ;? [英] What is the difference between DbSet<> and virtual DbSet<>?

查看:96
本文介绍了DbSet<>和有什么区别?和虚拟DbSet<&gt ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In Entity Framework Code First, when I declare entities I have to use DbSet<> type of properties for that. For example:

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

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

Recently I've met DbSet<> declared as virtual.

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

有什么区别?

推荐答案

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

导航属性上的virtual关键字用于启用延迟加载机制,但是必须启用配置的LazyLoadingEnabled属性。

The virtual keyword on the navigation properties are used to enable lazy loading mechanism, but the LazyLoadingEnabled property of the configuration must be enabled.

AccountType :: AccountCodes导航属性上的虚拟关键字将以编程方式访问该帐户时加载所有帐户代码

The virtual keyword on AccountType::AccountCodes navigation property will load all account codes the moment there is a programmatically access to that property while the db context are still alive.

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

而派生的DbContext类(虚拟DbSet<>)上的虚拟关键字为用于测试目的(模拟DbSet属性),在这种情况下,虚拟关键字与延迟加载无关。

While the virtual keyword on the derived DbContext class (virtual DbSet<>) is used for testing purpose (mocking the DbSet property), virtual keyword in this case is not related to lazy loading.

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

===== update =====

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

Usually we are doing the testing against the service / logic, for example we have another layer for the account type service as follow. And the service accepts the db context instance using some kind of dependency injection through the constructor.

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

现在我们需要测试帐户类型服务,在这种情况下,我使用mstest和automoq创建了模拟类。

And now we need to test the account type service, in this case I used mstest and automoq to create the mock class.

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

这篇关于DbSet&lt;&gt;和有什么区别?和虚拟DbSet&lt;&gt ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆