2017-02-17 91 views
1

Я хотел бы получить список элементов как составную часть составного ключа группы. Но до сих пор я не мог написать запрос, чтобы сделать это.Как добавить список к ключу в группе Linq to Sql В

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

var list = this.Stocks.Where(x => x.StockType == StockTypeEnum.RawMaterialEntered) 
.GroupBy(i => new { RawMaterialId = i.RawMaterial.Id, RawMaterial = i.RawMaterial.Name, 
        Suppliers = i.RawMaterial.Suppliers.Select(j=> new { Id= j.Supplier.Id, Name = j.Supplier.Name}) }) 
.Select(g => new StockSummary 
{ 
    TotalAmount = g.Sum(i => i.Amount), 
    ComponentId = g.Key.RawMaterialId,     
    Component = g.Key.RawMaterial, 
    Suppliers = g.Key.Suppliers.Select(h=> new StockItemModel(){ Id = h.Id, Name = h.Name}).ToList() 
}) 
.OrderByDescending(g => g.Component).ToList(); 

Он строит, но когда я пытаюсь запустить его, я получаю это исключение:

первого шанса исключение типа «System.NotImplementedException» произошло в NHibernate. dll

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

У меня есть эта модель:

public class Stock 
{ 
    public RawMaterial RawMaterial{ get; set; } 
    public int Amount { get; set; } 
} 

public class RawMaterial 
{ 
    public int Id{ get;set; } 
    public string Name { get;set; } 
    public IList<SupplierInfo> SupplierInfos{ get;set; } 
} 

public class SupplierInfo 
{ 
    public int Id{ get;set; } 
    public Supplier Supplier { get;set; } 
} 

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

Первоначально мы имели сетку, где мы показываем каждый общий запас доступных для сырья. Мы получаем эту информацию с этим запросом:

var list = this.Stocks.Where(x => x.StockType == StockTypeEnum.RawMaterialEntered) 
    .GroupBy(i => new { RawMaterialId = i.RawMaterial.Id, RawMaterial = i.RawMaterial.Name }) 
    .Select(g => new StockSummary 
       { 
        TotalAmount = g.Sum(i => i.Amount), 
        ComponentId = g.Key.RawMaterialId,     
        Component = g.Key.RawMaterial,     
       }) 
       .OrderByDescending(g => g.Component).ToList(); 

Эти данные отображаются в виде таблицы примерно так:

Current Stocks Total

И теперь, как уже упоминалось выше, мы хотели бы показать список поставщиков, которые предоставили указанные компоненты. Можно ли все это сделать в одном запросе?

Desired table

+0

Вы ищете решение для спящего режима или SQL Server решение? Я не мог помочь вам спящий режим, но в sql-сервере вы можете легко использовать материал и для xml. Взгляните сюда. http://stackoverflow.com/questions/451415/simulating-group-concat-mysql-function-in-microsoft-sql-server-2005 –

+0

Вы группируете данные по списку в вызове GroupBy? Насколько я знаю, ни NHibernate, ни EF не поддерживают такую ​​операцию. –

+0

Я бы сказал, нет, вы не можете сделать это в одном запросе. Получите все результаты по первому запросу, загрузите их все из базы данных и сгруппируйте их в своем приложении. Я не уверен, что вы хотите сделать, даже в SQL. – Sidewinder94

ответ

0

Итак, прежде всего, ваш код является неполным или вы не вставить все здесь. Например, отсутствуют StockType и StockEnumType, и я удалил их из своего ответа для простоты, а не пытался воспроизвести то, что вы не показывали. В любом случае, она отлично работает для меня, если я использую string.Join(",", ...) хотя он показывает идентификатор и имя, но я думаю, что вы не должны иметь никаких проблем регулировочных вывод, изменив ваше заявление LINQ:

 var list = stocks 
      .GroupBy(i => new { RawMaterialId = i.RawMaterial.Id, RawMaterial = i.RawMaterial.Name, 
       Suppliers = i.RawMaterial.SupplierInfos.Select(j => new { Id = j.Supplier.Id, Name = j.Supplier.Name }) 
      }) 
      .Select(g => new 
      { 
       TotalAmount = g.Sum(i => i.Amount), 
       ComponentId = g.Key.RawMaterialId, 
       Component = g.Key.RawMaterial, 
       Suppliers = string.Join(",", g.Key.Suppliers.Select(h => new { Id = h.Id, Name = h.Name }).ToList()) 
      }) 
      .OrderByDescending(g => g.Component).ToList(); 

И выход с моим тестовые данные:

1 NAME3 30.00 (Id = 1, Name = ПОД1), (Id = 3, Имя = Sup3)

2 Имя2 20.00 (Id = 1, Name = ПОД1) .. .

+0

Да, я забыл добавить StockType, но это действительно не относится к вопросу. Также вы используете Nhibernate? Или это полностью тест памяти? – Dzyann

+0

Это в памяти, но не имеет значения, правильна ли ваша модель данных. LINQ - это абстракция над вашим источником данных, которая позволяет вам манипулировать данными независимо от того, находится ли она в памяти, SQL, no-SQL и т. Д. – bc004346

+0

Это имеет значение, потому что Linq To SQL переведен на SQL, и я получаю Nhibernate Исключение. Я хочу написать Linq, чтобы он генерировал наименьшее количество запросов в SQL. – Dzyann

1

Вы можете попробовать:

var list = this.Stocks 
    .Where(x => x.StockType == StockTypeEnum.RawMaterialEntered) 
    .GroupBy(i => 
     new 
     { 
      RawMaterialId = i.RawMaterial.Id, 
      RawMaterial = i.RawMaterial.Name 
     }) 
    .Select(g => new StockSummary 
    { 
     TotalAmount = g.Sum(i => i.Amount), 
     ComponentId = g.Key.RawMaterialId,     
     Component = g.Key.RawMaterial, 
     Suppliers = g 
      .SelectMany(s => 
       s.RawMaterial.SupplierInfos.Select(j => 
        new { Id = j.Supplier.Id, Name = j.Supplier.Name })) 
      .Distinct() 
      .Select(h => new StockItemModel() { Id = h.Id, Name = h.Name }) 
      .ToList() 
    }) 
    .OrderByDescending(g => g.Component).ToList(); 

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

Возможно, вам это проще, избегая группы: почему бы не использовать RawMaterial в качестве корня вашего запроса?Для этого необходимо добавить коллекцию Stocks на номер RawMaterial (или использовать подзапросы).

Гадание this.RawMaterials существует и является IQueryable<RawMaterial>, это было бы что-то вроде:

var list = this.RawMaterials 
    .Where(rm => 
     rm.Stocks.Any(s => s.StockType == StockTypeEnum.RawMaterialEntered)) 
    .Select(rm => new StockSummary 
    { 
     TotalAmount = rm.Stocks 
      .Where(s => s.StockType == StockTypeEnum.RawMaterialEntered) 
      .Sum(s => s.Amount), 
     ComponentId = rm.Id,     
     Component = rm.Name, 
     Suppliers = rm.SupplierInfos 
      .Select(si => 
       new StockItemModel() 
       { 
        Id = si.Supplier.Id, 
        Name = si.Supplier.Name 
       }) 
      .ToList() 
    }) 
    .OrderByDescending(ss => ss.Component).ToList(); 

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