gpt4 book ai didi

entity-framework - DbSet<> 和虚拟 DbSet<> 有什么区别?

转载 作者:行者123 更新时间:2023-12-03 07:41:48 31 4
gpt4 key购买 nike

在 Entity Framework Code First 中,当我声明实体时,我必须使用 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 功能?

最佳答案

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 属性。

AccountType::AccountCodes 导航属性上的虚拟关键字将在数据库上下文仍然存在的情况下以编程方式访问该属性时加载所有帐户代码。

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

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

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

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

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 来创建模拟类。

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

关于entity-framework - DbSet<> 和虚拟 DbSet<> 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24079133/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com