public static bool Delete(ProductionBatch batch)
        {
            if (batch == null)
            {
                throw new ArgumentNullException("batch");
            }

            using (var context = ApplicationDbContext.Create())
            {
                var existing =
                    context.ProductionBatches.Include(b => b.Meters.Select(m => m.Parameters))
                        .FirstOrDefault(b => b.ProductionBatchId == batch.ProductionBatchId);
                if (existing == null)
                {
                    return false;
                }

                context.ProductionBatches.Remove(existing);
                context.SaveChanges();

                return true;
            }
        }
        public static ProductionBatch CreateNextForOrder(string orderUniqueId)
        {
            if (string.IsNullOrEmpty(orderUniqueId))
            {
                throw new ArgumentNullException("orderUniqueId");
            }

            var order = OrderRepository.GetOneByUniqueId(orderUniqueId, true);

            // Reset stations
            StationRepository.RemoveMetersFromStations(order.UniqueId);

            var batch = new ProductionBatch() { ProductionOrderId = order.ProductionOrderId, SequenceNumber = 1, StartedAt = new DateTime(1900, 1, 1), Meters = new List<DvseMeter>() };

            // find last parameters 
            using (var context = ApplicationDbContext.Create())
            using (var trans = context.Database.BeginTransaction())
            {
                try
                {
                    order = OrderRepository.SetProducedSoFar(orderUniqueId);
                    if (order.IsCompleted)
                    {
                        // we are done
                        return null;
                    }
                    
                    // prepare list of calculated parameters (Eigentumsnummer)
                    var formulaParams = new List<Parameter>();
                    CreateNewParametersFromInfoSet(order, formulaParams);
                    formulaParams = formulaParams.Where(p => p.TargetValue.Contains("[")).ToList();

                    // get the last batch to decide if we should begin incrementing numbers from definition or from last batch
                    var lastBatch = GetLastByOrderUniqueId(orderUniqueId);
                    List<Parameter> lastParameters;
                    if (lastBatch == null)
                    {
                        // create new parameters from definition
                        lastParameters = new List<Parameter>();
                        CreateNewParametersFromInfoSet(order, lastParameters);
                    }
                    else
                    {
                        // create new parameters from last batch
                        // increment sequence number
                        batch.SequenceNumber = lastBatch.SequenceNumber + 1;

                        // take parameters from last produced meter
                        var lastMeter = lastBatch.Meters.Where(m => m.IsCompleted).OrderBy(m => m.ComPort).LastOrDefault();
                        if (lastMeter == null)
                        {
                            // last batch is not completed
                            throw new InvalidOperationException("Last batch was not completed");
                        }

                        lastParameters = lastMeter.Parameters.ToList();
                    }

                    // add meters to batch until no free station is available
                    while ((order.ProducedMeterCount + batch.Meters.Count) < order.MeterCount)
                    {
                        var freeStation = StationRepository.GetNextWithoutMeter(order.UniqueId);
                        if (freeStation == null)
                        {
                            // batch is full - no more free stations
                            break;
                        }

                        // create meter with parameters
                        var meter = new DvseMeter()
                        {
                            ComPort = StationRepository.GetNextWithoutMeter(order.UniqueId).ComPort,
                            ProductionBatch = batch,
                            ProducedAt = new DateTime(1900, 1, 1),
                            Parameters = new List<Parameter>(),
                        };

                        // create incremented or random parameters based on last
                        var isFirstOfOrder = order.ProducedMeterCount + batch.Meters.Count == 0;
                        lastParameters.ForEach(p => meter.Parameters.Add(p.GetNextAsClone(isFirstOfOrder)));
                        lastParameters = meter.Parameters.ToList();

                        // create calculated parameters based on formula
                        formulaParams.ForEach(p =>
                        {
                            var param = lastParameters.First(lp => lp.TagId == p.TagId);
                            param.TargetValue = p.GetCalculatedTargetValue(meter.Parameters.ToList());
                        });

                        // use meter's serialno from parameter
                        meter.SerialNo = meter.GetParameter(ParameterTagId.ManufacturerSerialNumber).TargetValue;
                        StationRepository.ReserveStationForMeter(freeStation.ComPort, meter.SerialNo);
                        
                        // check serial no against server id
                        var serverId = meter.GetParameter(ParameterTagId.ServerId).TargetValue;
                        CheckServerIdAndMeterSerialNo(serverId, meter.SerialNo);

                        batch.Meters.Add(meter);
                    }

                    context.ProductionBatches.Add(batch);
                    context.SaveChanges();
                    trans.Commit();

                    return batch;
                }
                catch (Exception ex)
                {
                    var msg = "Create next batch for order failed: " + ex.GetaAllMessagesInHierarchy();
                    Logger.Error(msg);
                    trans.Rollback();
                    throw new ApplicationException(msg);
                }
            }
        }