Как использовать Linq в C# для выбора определенной строки c из нескольких вложенных столбцов? - PullRequest
1 голос
/ 03 апреля 2020

У меня здесь небольшая проблема. У меня есть следующие таблицы с их отношениями:

Building
  Batteries
    Columns
      Elevators

В здании может быть много батарей, в батареях может быть много столбцов, в столбцах может быть много лифтов.

У батареи есть одно здание, В столбце есть одна батарея, в лифте - одна колонка.

Если бы я сделал это var myintervention = _context.buildings.Where(b => b.batteries.Any(ba => ba.status == "Intervention")).ToList();, в моем запросе было бы прекрасно работать, чтобы вывести список зданий, в которых есть батареи со статусом вмешательства (статус это столбец).

Проблема в том, что я не могу сделать что-то вроде _context.buildings.Where(c => c.columns.Any...), потому что модель здания не имеет доступа к классу столбцов, но батарея делает ... То же самое касается лифтов, здания не имеют доступ к лифтам, столбцы делают.

Вот как я определил свой modelBuilder:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Battery>()
            .HasOne(p => p.buildings)
            .WithMany(b => b.batteries)
            .HasForeignKey(p => p.building_id);

        modelBuilder.Entity<Column>()
            .HasOne(p => p.batteries)
            .WithMany(b => b.columns)
            .HasForeignKey(p => p.battery_id);

        modelBuilder.Entity<Elevator>()
            .HasOne(p => p.columns)
            .WithMany(b => b.elevators)
            .HasForeignKey(p => p.column_id);
    }

Вот как мои отношения выглядят в моих моделях:

building.cs
  public List<Battery> batteries { get; set; }

battery.cs
  public long building_id { get; set; }
  public Building buildings { get; set; }
  public List<Column> columns { get; set; }

column.cs
  public long battery_id { get; set; }
  public Battery batteries { get; set; }
  public List<Elevator> elevators { get; set; }

elevator.cs
  public long column_id { get; set; }
  public Column columns { get; set; }

tl; dr ; Я хочу сделать запрос linq, чтобы получить список всех зданий, в которых есть батарея, столбец или лифт, чей столбец состояния имеет значение «Вмешательство».

ОБНОВЛЕНИЕ: очевидно, это работает, но не эффективно:

var myintervention = _context.buildings.Where(a => a.batteries.SelectMany(b => b.columns.SelectMany(c => c.elevators)).Any(c => c.status == "Intervention")).ToList();

Кажется, что это не так? Иногда вмешиваются батареи, и здание, связанное с этими батареями, не отображается в списке зданий. То же самое касается лифтов или колонн ... Я немного растерялся!

ОБНОВЛЕНИЕ 2: вот мой запрос:

[HttpGet("intervention")]
        public List<Building> Getintervention(string status)
        {
            var myintervention = _context.buildings.Where(c => c.batteries.SelectMany(z => z.columns).Any(z => z.status == "Intervention")).ToList();
            return myintervention;
        }

Ответы [ 2 ]

1 голос
/ 03 апреля 2020
var vara = _context.maintable.Where(a => a.tablerelatedtomain.SelectMany(b => b.tablerelatedtoprevious).SelectMany(c => c.tablerelatedtoprevious).Any(c => c.status == "mystring")).ToList();
var varb = _context.maintable.Where(a => a.tablerelatedtomain.SelectMany(b => b.tablerelatedtoprevious).Any(b => b.status == "mystring")).ToList();
var varc = _context.maintable.Where(a => a.tablerelatedtomain.Any(a => a.status == "mystring")).ToList();
var result = vara.Union(varb).Union(varc).OrderBy(z => z.id).ToList();

return result;
1 голос
/ 03 апреля 2020

Прежде всего, исправьте модель, чтобы в коллекциях были множественные имена, а в объектах - одиночные, иначе ваш код будет сильно запутан:

building.cs
  public List<Battery> Batteries { get; set; }

battery.cs
  public long BuildingId { get; set; }
  public Building Building { get; set; }
  public List<Column> Columns { get; set; }

column.cs
  public long BatteryId { get; set; }
  public Battery Battery { get; set; }
  public List<Elevator> Elevators { get; set; }

elevator.cs
  public long ColumnId { get; set; }
  public Column Columns { get; set; }

Теперь давайте добавим еще несколько свойств в модель, чтобы она могла сказать нам о вмешательствах:

building.cs
  public List<Battery> Batteries { get; set; }

  [NotMapped]
  public bool IsInIntervention => this.Status == "Intervention" || Batteries.Any(b => b.IsInIntervention);

battery.cs
  public long BuildingId { get; set; }
  public Building Building { get; set; }
  public List<Column> Columns { get; set; }

  [NotMapped]
  public bool IsInIntervention => this.Status == "Intervention" || Columns.Any(c => c.IsInIntervention);


column.cs
  public long BatteryId { get; set; }
  public Battery Battery { get; set; }
  public List<Elevator> Elevators { get; set; }

  [NotMapped]
  public bool IsInIntervention => this.Status == "Intervention" || Elevators.Any(e => e.IsInIntervention);


elevator.cs
  public long ColumnId { get; set; }
  public Column Column { get; set; }

  [NotMapped]
  public bool IsInIntervention => this.Status == "Intervention";


Теперь вы можете просто спросить здание, является ли оно IsInIntervention, и оно скажет «да», если оно принадлежит, или если оно принадлежит

Примечание: если модель не имеет Если вы загружены сущностями, то вам может понадобиться такой прием: EF Core linq и условное включение, а затем включение задачи для их условной загрузки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...