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