1

I have an entity user with roles and I need to load the user with our roles (but not proxy object).

class User{
  public int Id{get; set;}
  public string Name{get; set;}
  public ICollection<Role> Roles{get; set;}
}
class Role{
  public int Id{get; set;}
  public string Name{get; set;}
  public virtual User User{get; set;}
}

When I use this: DbContext.Users.Where(x => x.Id == id).Include(x => x.Roles).FirstOrDefault() I get User object with Role Proxy object.

I need User object with Role object. How to do it? Thanks

2
  • I'm just curious, but why can't it be the proxy object? It's a descendant of Role anyway. Commented Jun 30, 2017 at 11:17
  • I need send User as JSON and Ok(user) dont add proxy objects to json (it must be) Commented Jun 30, 2017 at 11:22

1 Answer 1

1

Answering your specific answer, just disable proxy creation just for a specific code block, but you will have to eager load your entities like so:

try
{
    DbContext.Configuration.ProxyCreationEnabled = false;
    var userWithRoles = DbContext.Users.Include(x => x.Roles).Where(x => x.Id == id).FirstOrDefault();
}
finally
{
    DbContext.Configuration.ProxyCreationEnabled = true;
}

...which will affect only that instance. I wrapped this in a try finally block, because if any exception occur while loading entities, you can make sure that option will be reversed.

You could also set this globally inside your DbContext constructor, but I don't recommend this:

public class YourDbContext : DbContext
{

    public YourDbContext() : base("name=ConnectionString")
    {
        this.Configuration.ProxyCreationEnabled = true;
    }
}

My recommendation is to avoid exposing you database entities to an API. You can create DTO classes and expose them, instead:

// original entities
public class User {
    public int Id{get; set;}
    public string Name{get; set;}
    public ICollection<Role> Roles{get; set;}
    // other fields like birthdate, status, password, etc...
}
public class Role {
    public int Id{get; set;}
    public string Name{get; set;}
    public virtual User User{get; set;}
}

// DTO classes, keeping only the fields you want

// original entities
public class UserDTO {
    public int Id{get; set;}
    public string Name{get; set;}
    public ICollection<RoleDTO> Roles{get; set;}
}
public class RoleDTO {
    public int Id{get; set;}
    public string Name{get; set;}
}

// project them like this:
var userDTO = DbContext.Users.Where(x => x.Id == id)
    .Select(u => new UserDTO
    {
        Id = u.Id,
        Name = u.Name,
        Roles = u.Roles.Select(r => new RoleDTO
        {
            Id = r.Id,
            Name = r.Name
        }),
    })
    .FirstOrDefault();

Then you could return just the DTO. There are tools like AutoMapper which makes easier and cleaner to project DTO classes, this is just an example.

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

4 Comments

Ok its good, but i use Dependency injection and i can not use ProxyCreationEnabled in globally.
Yes! its good. When I set proxyCreationEnabled=false, it works. It is best solution? I thought to use Join method maybe or other linq method...
Although I just answered your specific answer, I don't think this is the best solution, because I would avoid exposing my database entities to an API, for example. I would project them to DTO classes and expose that as JSON.
I edited with a suggestion, then you don't need to disable proxy creation. I already experienced some problems when trying to return my DbContext objects directly to APIs, that's why I prefer using DTOs for these scenarios.

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.