2016-11-18 1 views
2

У меня есть несколько вопросов относительно опорных возможностей POCO ServiceStack.OrmLite.Загрузить * Ссылки на POCO с использованием OrmLite и SQL

  1. При использовании Load*() API для извлечения ПОКО со ссылками, делает его внутренне генерировать & запустить один запрос SQL (с соответствующей JOIN и), чтобы вернуть ПОКО и ссылки на него, или же запустить его отдельные запросы (один для POCO, затем по одной для каждой ссылки)?

  2. Есть ли способ сделать Load*() API принимать пользовательскую SQL запрос (вместо с SqlExpression), и по-прежнему иметь возможность автоматически загружать ссылки, а не должно вызывать LoadReferences() для каждого объекта?

Я пытаюсь указать пользовательские SQL заявление и возвращает список POCO со ссылками предварительно загружены, мы надеемся запустить один запрос под капотом.

Надеюсь, что кто-то перезвонит с некоторым пониманием.

ответ

2

Нагрузка Ссылки грузы 1 запрос загрузить основную таблицу и 1 запрос загрузить дочерние ссылки независимо от того, сколько строк ребенок ссылки есть.

Вы можете увидеть SQL, сгенерированный с помощью SQL Generated, который регистрируется на выходе Console при использовании ConsoleLogFactory. Например вот LoadSelectexample you can run on Gistlyn с его консоли вывода:

public class Artist 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    [Reference] 
    public List<Track> Tracks { get; set; } 
    public override string ToString() => Name; 
} 

public class Track 
{ 
    [AutoIncrement] 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int ArtistId { get; set; } 
    public string Album { get; set; } 
    public int Year { get; set; } 
    public override string ToString() => Name; 
} 

var oldestTracks = db.Select(db.From<Track>() 
    .Where(x => Sql.In(x.Year, db.From<Track>().Select(y => Sql.Min(y.Year))))); 
"Oldest Tracks: {0}".Print(oldestTracks.Dump()); 

var oldestTrackIds = oldestTracks.Map(x => x.Id); 
var earliestArtistsWithRefs = db.LoadSelect(db.From<Artist>() 
    .Where(a => oldestTracks.Map(t => t.ArtistId).Contains(a.Id))); 
"Earliest Artists: {0}".Print(earliestArtistsWithRefs.Dump()); 

консоли Выход:

DEBUG: SQL: SELECT "Id", "Name" 
FROM "Artist" 
WHERE "Id" In (@0,@1) 
PARAMS: @0=3, @1=4 
DEBUG: SQL: SELECT "Id", "Name", "ArtistId", "Album", "Year" FROM "Track" WHERE "ArtistId" IN (SELECT "Artist"."Id" 
FROM "Artist" 
WHERE "Id" In (@0,@1)) 
PARAMS: @0=3, @1=4 
Earliest Artists: [ 
    { 
     Id: 3, 
     Name: Nirvana, 
     Tracks: 
     [ 
      { 
       Id: 5, 
       Name: Smells Like Teen Spirit, 
       ArtistId: 3, 
       Album: Nevermind, 
       Year: 1991 
      }, 
      { 
       Id: 6, 
       Name: Heart-Shaped Box, 
       ArtistId: 3, 
       Album: In Utero, 
       Year: 1993 
      } 
     ] 
    }, 
    { 
     Id: 4, 
     Name: Pearl Jam, 
     Tracks: 
     [ 
      { 
       Id: 7, 
       Name: Alive, 
       ArtistId: 4, 
       Album: Ten, 
       Year: 1991 
      }, 
      { 
       Id: 8, 
       Name: Daughter, 
       ArtistId: 4, 
       Album: Vs, 
       Year: 1993 
      } 
     ] 
    } 
] 

Где вы можете увидеть 2 запросов, 1 запрос на загрузку основной таблицы и 1 запрос для загрузки треков ребенка Рекомендации.

+1

Thanks @mythz. Основной запрос таблицы сложный и ресурсоемкий, поэтому я закончил его с помощью 'Select' API, а затем выполнил отдельный запрос в справочной таблице для уникальных идентификаторов из основного запроса и, наконец, слияние обоих наборов результатов. Это быстрее и оптимальнее в моем случае, чем «LoadSelect», который повторно запускает основной запрос в качестве справочного запроса. Я полагаю, что один из подходов к этому подходу состоит в том, что количество уникальных идентификаторов из основного запроса должно быть разумным, чтобы не пройти предел параметра для предложения 'IN'. – Nick

Смежные вопросы