简体   繁体   中英

Using Entity Framework queries to get all entries on a table related to other 2 tables

Consider this model . Basically what I'm trying to do is obtaining every door in the table 'doors' such that there exists a corresponding entry in the table 'doors_to_devices' with a given device_id.

Here's what I've been trying

public async Task<ServiceResponse<AuthorizedDoorsDto>> Authenticate(string username, string password)
{
    // Irrelevant code
    var device = await dataContext.Devices
                           .Include(d => d.DoorsToDevices)
                           .FirstOrDefaultAsync(d => d.Username == username && d.Password == password);

    var doors = await dataContext.Doors
                         .Where(d => d.DoorsToDevices.ToList().ForEach(dtd => dtd.DeviceId.Equals(device.Id)));
    // More irrelevant code
}

But this obviously doesn't work...

I've actually got it to work some other way, in a previous version of the code (slightly different in purpose), but it seems so convoluted, I was hoping there was a simpler way. Here's how I got it to work:

private async Task<List<DoorDto>> GetDeviceDoors(Device device)
{
    var doorsToDevice = device.DoorsToDevices.ToList();

    List<Guid> doorsIds = new List<Guid>();

    doorsToDevice.ForEach(dtd => doorsIds.Add(dtd.DoorId));

    var doors = await _dataContext.Doors
                                  .Where(d => doorsIds.Contains(d.Id))
                                  .IgnoreAutoIncludes()
                                  .ToListAsync();
    var doorDtos = new List<DoorDto>();

    foreach (var door in doors)
    {
        doorDtos.Add(_mapper.Map<DoorDto>(door));
    }

    return doorDtos;
}

public async Task<ServiceResponse<AuthenticateDto>> Authenticate(string username, string password, Guid id)
{
    // Irrelevant code
    
    var device = await _dataContext.Devices
                            .Include(d => d.DoorsToDevices)
                            .FirstOrDefaultAsync(d => d.Id == id);
    var doors = GetDeviceDoors(device).Result;

    // More irrelevant code
}

Instead of collecting keys from one table, to include in the where clause of another table. Why not just join through directly in your query, via navigation properties;

var doors = await dataContext.Doors
    .Where(d => d.DoorsToDevices
        .Any(dtd => dtd.Device.UserName == username
            && dtd.Device.Password == password)
    )
    .ToListAsync();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM