C# 使用EF LazyLoading初始化属性?
更新:我知道我不应该使用C# 使用EF LazyLoading初始化属性?,c#,entity-framework,lazy-loading,lazy-evaluation,C#,Entity Framework,Lazy Loading,Lazy Evaluation,更新:我知道我不应该使用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 ICollec
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; }
}
由于属性用户未初始化,此测试将在NullReferenceException
上失败
我应该如何更改可以依赖EF提供的LazyLoading的代码?var-tenant=new-tenant
var tenant = new Tenant
{
Name = "localhost",
Guid = Guid.NewGuid().ToString(),
Users = new List<User> { user }
};
{
Name=“localhost”,
Guid=Guid.NewGuid().ToString(),
用户=新列表{user}
};
var-tenant=新租户
{
Name=“localhost”,
Guid=Guid.NewGuid().ToString(),
用户=新列表{user}
};
我想您期待的是这样的东西(不是线程安全的):
[表(“租户”)]
公营房屋租户
{
专用数据库集用户;
公共int Id{get;set;}
公共字符串名称{get;set;}
[关键]
公共字符串Guid{get;set;}
公共虚拟ICollection用户
{
得到
{
如果(_users==null)
_用户=新列表();
返回用户;
}
设置{u users=value;}
}
}
我确信
Lazy
类也可以以某种方式使用,但我对该类不太熟悉。我想您希望看到类似的东西(不是线程安全的):
[表(“租户”)]
公营房屋租户
{
专用数据库集用户;
公共int Id{get;set;}
公共字符串名称{get;set;}
[关键]
公共字符串Guid{get;set;}
公共虚拟ICollection用户
{
得到
{
如果(_users==null)
_用户=新列表();
返回用户;
}
设置{u users=value;}
}
}
我确信
惰性类也可以以某种方式使用,但我不熟悉该类。我在这里看到了两个问题
正如@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();
}
[表(“租户”)]
公营房屋租户
{
公共int Id{get;set;}
公共字符串名称{get;set;}
[关键]
公共字符串Guid{get;set;}
公共虚拟ICollection用户{get;set;}
}
[表格(“用户”)]
公共类用户:IEntity
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串电子邮件地址{get;set;}
公共字符串密码{get;set;}
}
[测试]
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=新列表{user};
_租户存放。添加(租户);
_applicationContext.SaveChanges();
}
我在这里看到了两个问题
正如@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();
}
[表(“租户”)]
公营房屋租户
{
公共int Id{get;set;}
公共字符串名称{get;set;}
[关键]
公共字符串Guid{get;set;}
公共虚拟ICollection用户{get;set;}
}
[表格(“用户”)]
公共类用户:IEntity
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串电子邮件地址{get;set;}
公共字符串密码{get;set;}
}
[测试]
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=新列表{user};
_租户存放。添加(租户);
_applicationContext.SaveChanges();
}
是的,我可以想出各种方法来消除我的NullReferenceException,但是为什么惰性加载的概念不能解决这个问题呢?我做错什么了吗?是的,我可以想出各种方法来摆脱我的NullReferenceException,但是为什么懒惰加载的概念不能为我解决这个问题呢?我做错什么了吗?所以您希望逻辑在第一次访问时初始化用户
?这些类是如何生成的?这里没有延迟加载。。EF此时未触及Users属性。你的测试只实例化了对象。好吧,我现在可能属于白痴一类,但你能帮我一个大忙,并添加一个我应该如何初始化DbSet属性的示例吗?@Daniel,我不敢回答你的问题,但是的,我有点回答了。它们不是生成的。你这里有一个答案可以告诉你。要么这样做,要么在构造函数中初始化它。任何引用类型属性都将初始化为null,除非您显式地这样做。因此,您希望逻辑在第一次访问时初始化用户
?这些类是如何生成的?这里没有延迟加载。。EF此时未触及Users属性。你的测试只是实例化对象。好吧,我现在可能属于白痴一类,但是你能帮我一个大忙并添加一个吗
[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();
}