List<Expression> w select

0

Witam,
Z racji że odwołania do bazy stały się coraz bardziej rozległe i mało czytelne chciałbym wyodrębnić jedną metodę do pobierania obiektów, a w argumentach przesyłać

  1. co ma pobrać (jakie kolumny - select)
  2. przy jakich ograniczeniach ( where)

Udało mi się napisać ograniczenia i obecnie to wygląda tak :

public IEnumerable<CarDto> GetCars(Func<Cars,bool> condition) 
{
   using(var db = new ModelContext()){
      var model = db.Cars.Where(condition).Select( i => new
    {
      Name = i.Name 
      Model = i.Model 
      FirstOwnerName = i.FirstOwner.Name
      .......
      .......
    } ).AsEnumerable().Select( x=> new CarDto(x))
   }
}

wywołanie:

.....
var cars = dao.GetCars(DBExpression.Where.NewCars); 
....

Tych kolumn oczywiście jest więcej, i je również chciałbym wyodrębnić do metody podobnie jak warunki.
Czy mógłby ktoś podrzucić jakiś przykład jak to zrobić sprytnie i poprawnie ?

zacząłem pisac coś takiego :

public static List<Expression> BaseInformationSelector(){
var result= List<Expression>();

Expression<Func<Car,String>> x = (p) => p.FirstOwner.Name
result.Add(x); 
Expression<Func<Car,Bool>> xx = (p) => p.isActive
result.Add(xx); 
return result; 
}

to niestety nie mogę takiej listy użyć w select :/

1

Jeśli mowa o obecnej funkcji to zamiast Func<Transfer,bool> powinieneś przekazywać Expression<Func<Transfer,bool>>, bo inaczej EF pobierze całą tabelę i będzie filtrować w pamięci.
Co do głównego pytania nie rozumiem do końca co masz na myśli. Jeśli chcesz pobierać różne kolumny, to raczej powinieneś utworzyć różne viewmodele i mapować do nich (ręcznie czy tam jakimś automapperem)

0

no tak mam różne viewModele, tylko że ViewModele powstają u mnie w warstwie wyżej (w service).

  1. Czy dobrą praktyką jest by mapowanie do ViewModeli odbywało się w Dao ?

Ogólnie na początku robiłem to tak:

public IEnumerable<Cars> GetCars(Func<Cars,bool> condition, IList<Expression<Func<Cars,Object>>> includes) 
{
   using(var db = new ModelContext()){
       var model = db.Cars.AsQueryable();
       foreach(var item in includes)
       {
         model = model.Include(item);
       }
        
        var result = model.Where(condition).ToList();
         return result;     
     
}

Było to bardzo wygodne bo przy mapowaniu w warstwie wyżej bo miałem całe duże obiekty. Niestety okazało się że jest to bardzo nadmiarowe i zapytanie jest dosyć długie (zaciąga wszystkie kolumny), długo się wykonuje po stronie bazy danych.
Dlatego teraz moim celem jest zaciąganie tych kolumn które są faktycznie potrzebne.
Chciałbym miec po stronie DAO jedną metodę GetCars która jako argumenty przyjmuje
a)kolumny które ma zwrócić
b)warunek jaki musi być spełniony
Czyli po stronie service wyglądałoby to tak:

public IEnumerable<NewCarViewModel> GetCar_New(){
var model = dao.GetCars(DBExpression.Where.NewCars(),DBExpression.Selector.Cars_BaseInformation()); 
return mapper.Map<NewCarViewModel>(model); 
}

public IEnumerable<NewCarDetailsViewModel> GetCar_New_Details(){
var model =  dao.GetCars(DBExpression.Where.NewCars(),DBExpression.Selector.Cars_ExtendedInformation()); 
return mapper.Map<NewCarDetailsViewModel>(model); 
}

public IEnumerable<OldCarViewModel> GetCar_New_Details(){
var model =  dao.GetCars(DBExpression.Where.OldCar,DBExpression.Selector.Cars_BaseInformation); 
return mapper.Map<OldCarViewModel>(model); 
}

public IEnumerable<OldCarDetailsViewModel> GetCar_New_Details(){
var model = dao.GetCars(DBExpression.Where.OldCar(),DBExpression.Selector.Cars_ExtendedInformation()); 
return mapper.Map<OldCarDetailsViewModel>(model); 
}
 
itd itd 

Czy ma ktoś pomysł jak to zrobić ? jak napisać tą metody i klasę Selector ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1