Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

​Можно ли это сделать LINQом?

146  
Murr патриот24.08.17 11:54
Murr
24.08.17 11:54 

Можно ли это сделать LINQом?


Дано:

Две таблицы (плоские, типизированные ДатаТабле).


Одна содержит записи он чем-то. В моем случае - детализированные записи ордеров.

По одной записи на на каждую единицу. Единица полностью определяется сложным первичным (уникальным) ключом.

Единицы можно сгруппировать по части ключа (по номеру ордера).


Вторая таблица содержит группирующую часть ключа и количество интересующих элементов группе.

Единственная связь между таблицами - по части ключа (т.е. по номеру ордера).


Интересующая меня подвыборка - записи из первой таблицы, в количестве соответствующем указанному во второй.


Чтобы было понятно:

Ордера заносятся в базу планирования целиком. Потом отдаются в производство.

В Планировании своя нумерация, в Производстве - своя. Связи между ними нет - только номер ордера.

Первая таблица - ордера, вторая - отчеты по выполнению.

Интересующая меня часть - невыпоненные части ордеров.


Помнится в ЛИНКе было что-то вида ФирстОрДефаулт()

Мне же нужно что-то вида ФирстОф(н=>продукция.количество).


Есть что-то похожее?


#1 
dymanoid знакомое лицо24.08.17 18:47
dymanoid
NEW 24.08.17 18:47 
в ответ Murr 24.08.17 11:54

Зачем романы пишешь? Покажи схему данных и что надо получить. Ни фига не понятно из твоих живописных эссе.

#2 
Murr патриот25.08.17 10:31
Murr
NEW 25.08.17 10:31 
в ответ dymanoid 24.08.17 18:47

Проще, наверное, дать текущий код:


using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using log4net;
using ExceptionHandler;

using Olympic.Misk.Range;
using Olympic.Orders.DeliveryStatus;
using Olympic.Orders.QtyDelivered;

namespace Olympic.Orders.UnfinishedOrders
{
public static partial class TUnfinishedOrders
{
public partial class Table : Olympic.Shared.UnfinishedOrders.TUnfinishedOrders.Table
{
#region Logging

private static readonly ILog logger = LogManager.GetLogger(typeof(Table).Name);

#endregion Logging

#region Local Data

static protected DataTable empty;

#endregion

#region Constructor

public Table() : base() { }
protected internal Table(DataTable pDt) : base(pDt) { }

#endregion

#region Methods

protected override CareyGlass.AbstractBO.Row GetNewRow() { return new Row(); }
protected override CareyGlass.AbstractBO.Subset GetEmptySubset() { return new Subset(); }

// here passed a Batch ranges
public void Load(TRangeCollection pRanges)
{
//batchRanges = pRanges;
Olympic.Sql.TGetCurrentOrders sqlt = new Olympic.Sql.TGetCurrentOrders();
sqlt.Ranges = pRanges;
//sqlt.Stations = new TKnownStations();

try
{
DataTable rawdata = DbExec.TExecFactory.LiProd.FillDataTable(sqlt);

if (empty == null) empty = rawdata.Clone();
rawdata.TableName = "DTBcdsToDo";

int rowsCount = rawdata.Rows.Count;

Table currentOrders = new Table(rawdata);
dt = GetUnfinishedOrders(currentOrders);
}
catch (Exception ex)
{
TExceptionHandler.Error(ex);
}
} // check config!!!

private DataTable GetUnfinishedOrders(Table pCurrentOrders)
{
Table unfinishedOrders = new Table(empty.Clone());

TRange range = new TRange(pCurrentOrders.MinOrderNo, pCurrentOrders.MaxOrderNo);
OrderRange = new TRangeCollection("DummyFieldName");
OrderRange.Add(range);

TDistinctOrders.Distinct distinctOrders = new TDistinctOrders.Distinct(pCurrentOrders);
string orderList = distinctOrders.GetOrdersList();

TDeliveryStatus.Table deliveryStatus = new TDeliveryStatus.Table();
deliveryStatus.Load(OrderRange, orderList);

TQtyDelivered.Table qtyDelivered = new TQtyDelivered.Table();
qtyDelivered.Load(orderList);

System.Diagnostics.Stopwatch stopwatch1 = System.Diagnostics.Stopwatch.StartNew();

//var query1 = from current in pCurrent.Rows.Cast<DataRow>().Select(r => (Row)r)
// join delivery in deliveryStatus.Cast<TDeliveryStatus.Row>() on current.OrderNo equals delivery.OrderNo
// where delivery.DeliveryStatusS == TDeliveryStatus.NotDelivered
// // || delivery.DeliveryStatusS == TDeliveryStatus.PartiallyDelivered
// select current;

var undeliveredAll = from current in pCurrentOrders.Cast<Row>().Select(r => r)
join delivery in deliveryStatus.Cast<TDeliveryStatus.Row>() on current.OrderNo equals delivery.OrderNo
where delivery.DeliveryStatusS == TDeliveryStatus.NotDelivered
// || delivery.DeliveryStatusS == TDeliveryStatus.PartiallyDelivered
orderby current.OrderNo, current.ItemNo
select current;

var partlyAll = from current in pCurrentOrders.Cast<Row>().Select(r => r)
join delivery in deliveryStatus.Cast<TDeliveryStatus.Row>() on current.OrderNo equals delivery.OrderNo
where delivery.DeliveryStatusS == TDeliveryStatus.PartiallyDelivered
orderby current.OrderNo, current.ItemNo
select current;

var query3 = from undeliverd in partlyAll
join quantity in qtyDelivered.Cast<TQtyDelivered.Row>()
on new { undeliverd.OrderNo, undeliverd.ItemNo }
equals new { quantity.OrderNo, quantity.ItemNo }
orderby undeliverd.OrderNo, undeliverd.ItemNo
select new { undeliverd, quantity };

int quantityCount = -1;
int currentOrderNo = -1;
int currentItemNo = -1;
foreach (var pair in query3)
{
if (pair.undeliverd.OrderNo != currentOrderNo
|| pair.undeliverd.ItemNo != currentItemNo)
{
currentOrderNo = pair.undeliverd.OrderNo;
currentItemNo = pair.undeliverd.ItemNo;
quantityCount = 0;
//logger.InfoFormat("Order/item {0}/{1} required {2} not deliverd {3}, Restart counter", pair.undeliverd.OrderNo, pair.undeliverd.ItemNo, pair.quantity.QtyItem, pair.quantity.QtyCompNotDelivered);
}
if (++quantityCount <= pair.quantity.QtyCompNotDelivered)
{
pair.undeliverd.DeliveryStatus = TDeliveryStatus.PartiallyDelivered;
unfinishedOrders.ImportRow(pair.undeliverd);
//logger.InfoFormat("Order/item {0}/{1} required {2} not deliverd {3}, added", pair.undeliverd.OrderNo, pair.undeliverd.ItemNo, pair.quantity.QtyItem, pair.quantity.QtyCompNotDelivered);
}
else
{
//skip this pair
//logger.InfoFormat("Order/item {0}/{1} required {2} not deliverd {3}, skiped", pair.undeliverd.OrderNo, pair.undeliverd.ItemNo, pair.quantity.QtyItem, pair.quantity.QtyCompNotDelivered);
}
}

foreach (Row urow in undeliveredAll)
{
urow.DeliveryStatus = TDeliveryStatus.NotDelivered;
unfinishedOrders.ImportRow(urow);
}

stopwatch1.Stop();

System.Diagnostics.Debug.WriteLine("Selection for undelivered/partlidelivered took " + stopwatch1.Elapsed + "");
System.Diagnostics.Debug.WriteLine("Rows selected: " + unfinishedOrders.dt.Rows.Count);

//return unfinishedOrders.dt;
return unfinishedOrders.dt.Select("", "orderNo,itemNo").CopyToDataTable();
}


#endregion

#region Properties

//public new Row FirstRow { get { return (Row)base.FirstRow; } }
public TRangeCollection OrderRange { get; internal set; }

#endregion

#region Propeties Calculation

public Decimal MinOrderNo { get { return Convert.ToDecimal(dt.Compute("MIN(orderNo)", "")); } }
public Decimal MaxOrderNo { get { return Convert.ToDecimal(dt.Compute("MAX(orderNo)", "")); } }

#endregion
}
}
}


Меня интересует выполнение фильтрации в цикле foreach (var pair in query3) ЛИНКом.

Чтобы упростилось до уровня foreach (Row urow in undeliveredAll)

Mожно и так оставить - оно достаточно быстрое - 0.5 сек на 20К записей, но все же интересно - можно ли слепить такой фильтр v LINQ.


#3