2017-02-12 7 views
0

Основной идеи в psuedocodeSelect * из двух таблиц в два отдельных списках

Select(a, b) => new Tuple<List<Item1>, List<Item2>>(a, b)

Я пытаюсь сделать это в:

  • Один запроса к БД
  • , очевидно, используя linq (запрос или синтаксис метода)

Здесь приведены t горе классов участвуют

public class Bundle 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public HashSet<Inventory> Inventories { get; set; } 
} 

public class Inventory 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public int Stock { get; set; } 
} 

Прямо сейчас все, что я могу думать о

using (var context = new MyEntities()) 
{ 
    return new Tuple<IEnumerable<Inventory>, IEnumerable<Bundle>>(context.Inventories.OrderBy(a => a.Stock).ToList() 
     , context.Bundles.Include(b => b.Inventories).OrderBy(c => c.Name).ToList()); 
} 

Однако это ударит по базе данных дважды.

Я знаю, что UNION используется для комбинирования наборов результатов из 2 разных запросов, но два запроса должны иметь одинаковые столбцы, поэтому я предполагаю, что он наилучшим образом используется при выборе тех же данных.

Как я могу выбрать данные из двух разных таблиц в два отдельных списка только с одним ударом по db?

+2

Любая конкретная причина для желающих попасть только один раз, когда база данных? – Sam

+0

Просто чтобы свести к минимуму количество выполненных запросов – Adrian

ответ

1

Если вы беспокоитесь о производительности, я не думаю, что сокращение количества запросов - это путь. На самом деле, если вы хотите оптимизировать мелкие зерна, LINQ также не является наиболее подходящим инструментом.

Это означает, что вы можете сделать два разных объекта совпадающими с одним и тем же интерфейсом/столбцами, заполняя фиктивные свойства для тех, которые отсутствуют в другом типе. Это теоретически должно быть переведено на SQL union, содержащий все столбцы.

var union = context.Inventories 
    .Select(i => new { i.Id, i.Name, i.Stock, Inventories=null }) 
    .Concat(context.Bundles.Select(b => new { b.Id, b.Name, Stock=0, b.Inventories)); 

Обратите внимание, что в этом случае Concat предпочтительнее из Union, так как она не изменяет порядок ваших строк и позволяет повторяющиеся строки.

0

То, о чем вы просите, не представляется возможным. Если вы пытаетесь получить два отличных результата, вам нужно дважды нажать DB, один раз за набор результатов. Вы можете выполнить внешнее соединение, но это приведет к тому, что ваш результат будет больше, чем нужно, и, судя по тому, что вы хотите ударить по БД один раз, вы заботитесь о производительности. Кроме того, если производительность была проблемой, я бы не использовал Linq в первую очередь.

+0

Я согласен с вами в точке linq. Этот проект является всего лишь приемом из интервью, поэтому я пытаюсь предвидеть любые «ошибки», с которыми я могу столкнуться. Странно, однако, я бы подумал, что будет способ сделать это за один раз. – Adrian

+1

Вопросы для интервью Ahhh обычно не имеют смысла :) – albattran

2

Если вы хотите получить два набора результатов, вы можете сделать это, бросив два запроса. Это может быть сделано в одном вызове базы данных без проблем, но оно не будет магически разделено на два набора объектов, которые вас интересуют.

На самом деле, задавая несколько вопросов и получая более одного набора результатов, очень часто, когда затраты на установление соединения (стоимость создания экземпляра или стоимость задержки и т. д.) достаточно велики, чтобы гарантировать это. Я сделал это сам в хранимой процедуре, прося все, что нужно страницам в одном запросе.

Но, если производительность является ключевой проблемой, кеширование также очень распространено. И если это выпадающие списки или что-то еще, где запрошенный список невелик, а список не меняется часто, вы можете даже вытащить его в память при запуске приложения и позволить ему установить на веб-сервере, чтобы вы не что делает поездку в базу данных.

Я не люблю LINQ к SQL, так как он создает беспорядок для АБД, но вы можете сделать это что-то вроде этого (только один пример, любой метод, где вы можете команды цепи будет работать):

var connString = "{conn string here}"; 
var commandString = "select * from tableA; select * from tableB"; 
var conn = new SqlConnection(connString); 
var command = new SqlCommand(commandString, conn); 
try { 
    conn.Open(); 
    var result = command.Execute(); 
    // work with results here 
} 
finally { 
    conn.Dispose(); 
} 

Я не заполнял все детали, но вы можете сделать это с любым количеством команд. Еще раз, если информация не изменяется, рассмотрите одно нажатие и удерживание в памяти (кэширование через программирование) или использование какого-либо другого механизма кэширования.

+0

Грегори, я ценю ваш хорошо продуманный ответ, но я должен был отметить ответ Сэма так же правильно, как он показал возможное решение, используя linq. Тем не менее, я поддержал ваш ответ. – Adrian

+0

@Adrian - проблем нет. Проблема, с которой я сталкиваюсь с LINQ to SQL, - это кошмар - это причины для администраторов баз данных. Неплохо для небольшого проекта, но не очень хорошего в корпоративных ситуациях. Я не против LINQ, поскольку я считаю, что это очень хороший способ расчесывать объекты. Смешно, что LINQ to SQL был написан в основном из-за задержки в SQL Server 2005 (Entity Framework 1.0) и демонстрации того, как создать сайт за 15 минут при запуске Visual Studio 2005. –

0

Я думаю, что вы можете сделать это, запросив несколько наборов результатов (как отметил Григорий), я не уверен, хотя для этого был бы «лучшим» способом. Почему бы вам не взглянуть на эту статью msdn? How to: Use Stored Procedures Mapped for Multiple Result Shape

Или это, по-LINQ к SQL-подхода: LINQ to SQL: returning multiple result sets

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

  • Нет связанных вопросов^_^