检查是否启用了懒加载

3

I have the following model:

public partial class User
{
    // other properties

    /// <summary>
    /// Gets or sets user roles
    /// </summary>
    public virtual IList<UserRole> UserRoles
    {
        get => _userRoles ?? (_userRoles = UserUserRoleMappings.Select(mapping => mapping.UserRole).ToList());
    }

    /// <summary>
    /// Gets or sets user-user role mappings
    /// </summary>
    public virtual ICollection<UserUserRoleMapping> UserUserRoleMappings
    {
        get => _userUserRoleMappings ?? (_userUserRoleMappings = new List<UserUserRoleMapping>());
        protected set => _userUserRoleMappings = value;
    }
}

在另一个库中提供服务的方法:

    public virtual User GetUserByUsername(string username)
    {
        if (string.IsNullOrWhiteSpace(username))
            return null;

        var user = _dbContext.Users
            .Where(u => u.Username == username)
            .FirstOrDefault();

        return user;
    }

只有启用延迟加载时,它才能正常工作:

        services.AddDbContext<DataContext>(options => options
            .UseLazyLoadingProxies()
            .UseSqlServer(connString));

如果未启用延迟加载,则用户属性不会被填充。 如果有人在未启用延迟加载的情况下尝试使用我的服务,我想抛出一个异常。如何做到这一点?我尝试检查属性 _dbContext.ChangeTracker.LazyLoadingEnabled,但是这个属性总是为真,即使我没有启用延迟加载...
2个回答

2
我发现了解决方案(感谢Tore Aurstad的提示)。 我在我的DbContext中覆盖了OnConfiguring方法:
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseLazyLoadingProxies(true);
        base.OnConfiguring(optionsBuilder);
    }

那么我们就不需要在启动类中使用UseLazyLoadingProxies()方法来启用延迟加载。


1
很好,你发现如何使惰性加载的行为更具确定性。您可以考虑添加“sealed”关键字来阻止代码用户更改任何内容,而是添加另一个虚拟函数以让他们自定义。此外,请注意,.Net Core服务可能会注入DbContextOptions并更改一些内容,因此一个修改就是将OnConfiguring方法拆分为确定的、封闭的部分,然后跟随一个虚拟方法,客户端可以自定义内容,但这样可能会再次更改惰性加载。 - Tore Aurstad

1
您可能误解了懒加载的使用方式,因为您提到其他用户可以在未启用懒加载的情况下使用您的服务。客户端不会打开或关闭懒加载,这取决于您实现后端来确保检查 EF 的空导航属性是否存在。
懒加载是 EF Core 2.1 中的一项通用功能,允许您仅在访问时加载导航属性。这些属性必须是虚拟的,并且类不能被密封。
也许您将 "代理" 这个词与客户端-服务调用混淆了。无论如何,您实现后端的代码必须确保数据模型不会出现不一致。客户端无法打开或关闭懒加载。
如果您不是在谈论同事将从另一层(如数据层)调用 EF 代码的情况,那么您必须确保进行了适当的空值检查。懒加载通常是一件好事,但如果您想加载导航属性,则可以使用 .Include 等方法进行急切加载。

目前服务层只有在启用“UseLazyLoadingProxies()”时才能正常工作。如果其他人尝试在未启用它的情况下使用此服务层,我想抛出一个异常,如“请启用延迟加载”。这是否可能? - Oleg Sh
1
也许你可以在你的数据库上下文中重写OnConfiguring方法,并通过IsConfigured方法检查是否启用了延迟加载属性,然后抛出异常。实现数据层由你来决定,而不是客户端。但请注意,实现服务层的开发人员可能会进行重写。在这种情况下,考虑将DbContext类封装并将OnConfiguring方法标记为sealed。 - Tore Aurstad
我尝试查看属性 var c = optionsBuilder.IsConfigured;,但它始终为true,不受 .UseLazyLoadingProxies() 影响。 - Oleg Sh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接