使用 EF 延迟加载初始化属性
本文关键字:属性 初始化 延迟加载 EF 使用 | 更新日期: 2023-09-27 17:56:25
>UPDATE:我知道我不应该使用DbSet
所以我按照Erenga的建议将实现更改为ICollection
请考虑以下课程:
[Table("Tenant")]
public class Tenant : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
[Key]
public string Guid { get; set; }
public virtual ICollection<User> Users { get; set; }
}
[Table("User")]
public class User : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public string Password { get; set; }
}
第一个测试创建一个新租户和一个新用户,并将它们存储在相应的表中。
[Test]
public void CreateNewUserForNewTenant()
{
var user = _applicationContext.Users.Create();
user.Name = "barney";
user.EmailAddress = "barney@flinstone.com";
var tenant = _applicationContext.Tenants.Create();
tenant.Name = "localhost";
tenant.Guid = Guid.NewGuid().ToString();
tenant.Users.Add(user); // NullReferenceException, I expected the EF would LazyLoad the reference to Users?!
_tenantRepository.Add(tenant);
_applicationContext.SaveChanges();
}
此测试将在NullReferenceException
失败,因为属性 Users 未初始化。
我应该如何更改我可以依赖 EF 提供的 LazyLoading 的代码?
我在这里看到 2 个问题。
-
如@SimonWhitehead所述,默认情况下,引用类型初始化为 null。延迟加载仅适用于 EF 创建的实体。这些实际上是类的子类,其中包含延迟加载的附加逻辑。
-
DbSet
不是实体支持的集合类型。您需要将类型更改为ICollection
、ISet
或IList
。
这是一个工作示例
[Table("Tenant")]
public class Tenant : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
[Key]
public string Guid { get; set; }
public virtual ICollection<User> Users { get; set; }
}
[Table("User")]
public class User : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public string Password { get; set; }
}
[Test]
public void CreateNewUserForNewTenant()
{
var user = _applicationContext.Users.Create();
user.Name = "barney";
user.EmailAddress = "barney@flinstone.com";
var tenant = _applicationContext.Tenents.Create();
tenant.Name = "localhost";
tenant.Guid = Guid.NewGuid().ToString();
tenant.Users = new List<User> { user };
_tenantRepository.Add(tenant);
_applicationContext.SaveChanges();
}
var tenant = new Tenant
{
Name = "localhost",
Guid = Guid.NewGuid().ToString(),
Users = new List<User> { user }
};
我想你期待这样的东西(不是线程安全的):
[Table("Tenant")]
public class Tenant : IEntity
{
private DbSet<User> _users;
public int Id { get; set; }
public string Name { get; set; }
[Key]
public string Guid { get; set; }
public virtual ICollection<User> Users
{
get
{
if (_users == null)
_users = new List<Users>();
return _users;
}
set { _users = value; }
}
}
我相信Lazy<T>
类也可以以某种方式使用,但我不熟悉该类。