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

Muh*_*bal 1 .net c# linq entity-framework lazy-loading

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

\n

这是我的第一个案例:我有User,User rolesRoles类。用户与角色具有多对多的关系。所以我创建了用户角色类来处理这种关系。User 不包含所有情况的角色(不要介意IdUserRole)。

\n

用户

\n
public class User : IUser\n{\n    public bool IsActive { get; set; }\n    public int Id { get; private set; }\n    public string Email { get; set; }\n    public byte[] PasswordHash { get; set; }\n    public byte[] PasswordSalt { get; set; }\n    public string? Phone { get; set; }\n\n    public List<UserRole> UserRoles { get; set; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

用户角色

\n
public class UserRole : IEntity\n{\n    public int Id { get; private set; }\n\n    [ForeignKey(nameof(User))]\n    public int UserId { get; set; }\n    public User User { get; set; }\n\n    [ForeignKey(nameof(Role))]\n    public int RoleId { get; set; }\n    public Role Role { get; set; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

角色

\n
public class Role : IEntity\n{\n    public int Id { get; private set; }\n    public string Name { get; set; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是我的第二个案例:我有一个ArticleUser. 在这种情况下,在任何情况下都Article使用Creator.Email( User) 或创建者名称,这意味着包括User使用 的任何查询Article

\n

文章

\n
public class Article : IEntity\n{\n    public Article() => CreatedAt = DateTime.Now;\n\n    public bool IsDeleted { get; set; }\n    public int Id { get; private set; }\n    public string Title { get; set; } = "Ba\xc5\x9fl\xc4\xb1k";\n    public string Content { get; set; } = "\xc4\xb0\xc3\xa7erik";\n    public DateTime CreatedAt { get; set; }\n    public DateTime? UpdatedAt { get; set; }\n    [ForeignKey(nameof(User))] public int CreatorId { get; set; }\n    [ForeignKey(nameof(User))] public int? DeletedBy { get; set; }\n\n    public User? Creator { get; set; }\n    public List<ArticleCategory> ArticleCategories { get; set; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

如果是 - 我应该做什么?如果不是 - 这如何与 EF Core 配合使用?

\n

例如User,它是从数据库返回数据并将其保存在内存中直到被请求,还是在被请求之前不会进入 UserRoles 和 Roles 表?

\n

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

\n

以下是如何以非常简单的方式从数据库中获取所有数据的示例:

\n
 var users = context.Users\n                    .Include(u => u.UserRoles)\n                    .ThenInclude(ur => ur.Role);\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

Gur*_*ron 5

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

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

public class Blog
{
    // ...

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

public class Post
{
    // ...

    public virtual Blog Blog { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

// ...
var postBlog = post.Blog; // here the lazy loading will happen.
Run Code Online (Sandbox Code Playgroud)

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

聚苯乙烯

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

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