2
\$\begingroup\$

I have a Company Class, and separate normalized Address Class. I did this because the Address table will hold more than just Company Addresses, so I don't want "CompanyAddress", "EmployeeAddress", "MiscAddress" tables. The Address table will also hold historical addresses, which would only need to be seen on the Edit and Detail Views.

I am able to return my Company Address along with the Company View by calling "ToList()" on the _context.Address table, but that will load all addresses, most of which are not necessary for this View.

This code works, and will display correctly in the View - however note that it is calling "ToList" on the entire Address table.

//This returns the address 
public async Task<IActionResult> Index()
{
    var x = await _context.Address.ToListAsync();
    return View(await _context.CompanyViewModel.ToListAsync());
}

The below examples do not work. The Address returns null.

public async Task<IActionResult> Index()
{
    return View(await _context.CompanyViewModel.ToListAsync());
}

and

var y = from c in _context.CompanyViewModel
        join a in _context.Address on c.CurrentAddress.ID equals a.ID
        select c;

The classes are fairly standard. I have left out a lot of the "meat" to make the code review as simple as possible - the other properties do not impact the review, as this issue is only with the Address property.

Classes:

public class CompanyViewModel
{
    public int ID { get; set; }
    public string CompanyName { get; set; }        
    public Address CurrentAddress { get; set; }
}

public class Address
{
    public int ID { get; set; }
    public string Address1 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

Calling ToList on the entire Address table does work, but is very inefficient. The View displays properly, but every time the page is loaded, it will materialize the entire Address table, which is much more work than is required for the Index View.

What is the right way with EF/MVC to only materialize the addresses that exist for the current context?

This is the best solution I can come up with right now. I have no idea if this is a best practice, but this seems to do the trick. Again though, I'm throwing darts blindfolded here. If someone knows a better way, my eyes and ears are open.

var companies = await _context.CompanyViewModel.ToListAsync();
var ret = from c in companies
          join a in _context.Address on c.CurrentAddress.ID equals a.ID
          select c;
return View(ret);
\$\endgroup\$
  • 1
    \$\begingroup\$ You can feel free to post other snippets of (non-functional) code to display what you were trying to accomplish, and why you wanted to accomplish it that way, but please make it as explicit as possible that this code is only an example, and is not the main focus of review. \$\endgroup\$ – Dannnno May 9 '18 at 18:27
  • 1
    \$\begingroup\$ It seems you simply overlooked the Include method. \$\endgroup\$ – Gert Arnold May 9 '18 at 21:08
  • \$\begingroup\$ @GertArnold it works perfectly. return View(await _context.CompanyViewModel.Include(x=>x.CurrentAddress).ToListAsync()); ... If you want to turn that into an answer, I'll mark as solution for you. Thank you. \$\endgroup\$ – Aaron May 10 '18 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.