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

and method of service in another library:

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

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

        return user;
    }

it works correctly only if lazy loading is enabled:

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

if lazy loading is not enabled then Users property is not filled. I want to throw an exception, if somebody try to use my service without enabled lazy loading. How to do it? I tried to check property _dbContext.ChangeTracker.LazyLoadingEnabled, but this property is always true, even I did not enable lazy loading...

2 Answers 2

2

I found the solution (thank you Tore Aurstad for hint). I override OnConfiguring method in my DbContext :

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseLazyLoadingProxies(true);
        base.OnConfiguring(optionsBuilder);
    }

Then we not need to use UseLazyLoadingProxies() method in startup class for enabling Lazy Loading

Sign up to request clarification or add additional context in comments.

1 Comment

Nice that you found out how to make the behavior of lazy loading more deterministic. You may consider to add the "sealed" keyword to hinder users of your code to alter anything and instead add another virtual to let them customize. Also note that .net core services might inject DbContextOptions and alter stuff, so one alteration will then be to split up the OnConfiguring method into a determined, sealed part and followed up by a virtual method that the clients can customize stuff, but then they might alter lazy loading again.
1

You are perhaps misinterpreting the usage of lazy loading, by mentioning that other users can use your service without lazy loading is enabled. The clients will not turn on or off lazy loading, it is up to you that implement the backend to make sure that you check for null navigation properties of EF to be existing or not.

Lazy loading is a general feature in EF Core 2.1 that allows you to load in navigation properties only when they are accessed. These properties must be virtual and the class must not be sealed.

Maybe you are misinterpreting the word "proxies" with a client-service call. Anyways, it is you that implement the backend that must see through that your data model is not inconsistent. Clients cannot turn lazy loading on or off.

If you are not talking about your peers at work that will call the EF code from another layer, such as the data layer. Then you must see through that null checking is done properly. Lazy loading is usually a good thing, but you can do eager loading such as .Include in case you want to load up navigation properties.

3 Comments

Right now service layer works correctly only when Lazy Loading is enabled by UseLazyLoadingProxies(). If somebody else will try to use this service layer without it, I want to throw him an exception like "enable Lazy Loading, please". Is it possible?
Maybe you could override OnConfiguring in your db context and check if the property for using lazy loading is enabled through the IsConfigured method and then throw an exception. It is up to you that implement the data layer, not the client. But do note that the developer(s) implementing the service layer could override. In that case, consider sealing the DbContext class and mark the OnConfiguring method as sealed perhaps.
I try to look at property var c = optionsBuilder.IsConfigured;, but it's always true, not depending on .UseLazyLoadingProxies()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.