C# 我应该对每个相关属性使用延迟加载吗

问题描述 投票:0回答:1

我正在研究延迟加载。我不明白延迟加载是如何工作的,我应该做些什么来改变它吗?


这是我的第一个案例:

我有用户、用户角色和角色类。用户与角色具有多对多的关系。所以我创建用户角色类来处理关系。用户不包括所有情况的角色。 (不要介意 UserRole 中的 Id )

用户

public class User : IUser
{
    public bool IsActive { get; set; }
    public int Id { get; private set; }
    public string Email { get; set; }
    public byte[] PasswordHash { get; set; }
    public byte[] PasswordSalt { get; set; }
    public string? Phone { get; set; }

    public List<UserRole> UserRoles { get; set; }
}

用户角色

public class UserRole : IEntity
{
    public int Id { get; private set; }

    [ForeignKey(nameof(User))]
    public int UserId { get; set; }
    public User User { get; set; }

    [ForeignKey(nameof(Role))]
    public int RoleId { get; set; }
    public Role Role { get; set; }
}

角色

public class Role : IEntity
{
    public int Id { get; private set; }
    public string Name { get; set; }
}

这是我的第二个案例:

我有与用户相关的文章类。在这种情况下,文章使用 Creator.Email ( User ) 或创建者名称,这意味着使用文章的任何查询都包含用户。

文章

public class Article : IEntity
{
    public Article() => CreatedAt = DateTime.Now;

    public bool IsDeleted { get; set; }
    public int Id { get; private set; }
    public string Title { get; set; } = "Başlık";
    public string Content { get; set; } = "İçerik";
    public DateTime CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
    [ForeignKey(nameof(User))] public int CreatorId { get; set; }
    [ForeignKey(nameof(User))] public int? DeletedBy { get; set; }

    public User? Creator { get; set; }
    public List<ArticleCategory> ArticleCategories { get; set; }
}

所以我的问题是我应该为延迟加载这些相关属性做些什么吗?

如果是,我应该做什么,如果不是,它如何与 efcore 一起使用?

对于用户示例,它是从数据库获取数据并保留在内存中直到被请求,还是不会进入 UserRoles 和 Roles 表直到被请求?

如果两者都不是,它实际上是如何工作的?


这里是我如何以简单的方式从数据库获取所有数据的示例。

 var users = context.Users
                .Include(u => u.UserRoles)
                .ThenInclude(ur => ur.Role);

在某些情况下,即使我不请求用户的角色,它们是否会从数据库中获取,如果是,它们是否会保留在内存中?

c# .net linq many-to-many lazy-loading
1个回答
2
投票

Lazy<T>
是一个框架提供的类,用于支持任何自定义开发人员定义的逻辑/函数的延迟初始化(通常用于多线程环境,但不限于此)。与 EF Core 无关。

另一方面,EF Core 中数据的延迟加载是在不使用

Lazy
的情况下完成的(至少在面向用户的 API/约定中)。 EF 中有两种主要的延迟加载“风格” - with proxywithout。第一种方法依赖于使用特殊的包,并且需要相应的属性是虚拟的:

public class Blog
{
    // ...

    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    // ...

    public virtual Blog Blog { get; set; }
}

这会生成特殊的代理类,除非需要(即以某种方式访问),否则它将推迟相关数据的加载。例如:

var post = _context.Posts.First(); // the Blog will not be loaded

// ...
var postBlog = post.Blog; // here the lazy loading will happen.

这两个概念相关,但仍然有些不同。

附注

  • 需要注意的一件事 - EF DbContext 不是线程安全的(即一次只能由一个线程使用,并且不支持通过同一实例对数据库进行并行查询),这消除了一部分问题,通过以下方式解决

    Lazy

  • 我个人建议谨慎使用延迟加载,因为它可能导致臭名昭著的 N+1 问题 - 请检查文档的注意延迟加载部分。

© www.soinside.com 2019 - 2024. All rights reserved.