使用LINQ

时间:2018-11-13 17:31:14

标签: c# linq datatable

我有一个应用程序,用户在其中输入用于查询数据库并返回匹配行的搜索词。我想找到重复的行,如下所示:

File  Tool  Product  Time1          MeasureTime      Row
319   S32   AX       11/13 1:12AM   11/13 5:02am     5
318   S32   AX       11/13 1:12AM   11/13 4:41am     5

在这些情况下,具有较高文件ID的条目可能是错误的重新测量,因此我希望能够向用户突出显示。

我有这段代码可以计数是否存在重复的行:

                    var duplicates = db2.AsEnumerable()
                    .GroupBy(r => new
                    {
                        Tool = r.Field<string>("Tool"),
                        Product = r.Field<string>("Product"),
                        Time1 = r.Field<DateTime>("Time1"),
                        Row = r.Field<Int32>("Row")
                    }).Select(g => new {
                        Tool = g.Key.Tool,
                        Product = g.Key.Product,
                        Time1 = g.Key.Time1,
                        Row = g.Key.Row,
                        Count = g.Count() }).ToList();

这将返回一个通用列表,我希望能够从中获取计数并将其添加回初始数据表db2中。然后,当用户选择计数大于1的行时,我可以提醒用户。我只想在用户选择较高的文件号时发出警报,因此我可能需要对排名进行排序,但是无论哪种方式,我如何才能将自己拥有的文件重新添加到原始表中?

2 个答案:

答案 0 :(得分:0)

如上所述,您将需要创建一个新列表,因为您丢失了对原始数据的引用:

import random
import logging
import threading
from PyQt5 import QtCore, QtGui, QtWidgets

WHITE, BLACK, YELLOW, ORANGE, RED = QtGui.QColor("white"), QtGui.QColor("black"), QtGui.QColor("yellow"), QtGui.QColor("orange"), QtGui.QColor("red")
DEFAULT_FONT = QtGui.QFont()

class QHandler(logging.Handler, QtWidgets.QTextEdit):
    def __init__(self, parent=None):
        QtWidgets.QTextEdit.__init__(self, parent)
        logging.Handler.__init__(self)

        self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
        self.setReadOnly(True)

        self.emit_lock = threading.Lock()

    def emit(self, record):
        with self.emit_lock:
            QtCore.QMetaObject.invokeMethod(self, 
                "append",  
                QtCore.Qt.QueuedConnection,
                QtCore.Q_ARG(str, self.format(record)))
            QtCore.QMetaObject.invokeMethod(self, 
                "autoScroll",
                QtCore.Qt.QueuedConnection)

    def format(self, record):
        if record.levelno == logging.INFO:
            bgcolor = WHITE
            fgcolor = BLACK
        elif record.levelno == logging.WARNING:
            bgcolor = YELLOW
            fgcolor = BLACK
        elif record.levelno == logging.ERROR:
            bgcolor = ORANGE
            fgcolor = BLACK
        elif record.levelno == logging.CRITICAL:
            bgcolor = RED
            fgcolor = BLACK
        else:
            bgcolor = BLACK
            fgcolor = WHITE

        self.setTextBackgroundColor(bgcolor)
        self.setTextColor(fgcolor)
        self.setFont(DEFAULT_FONT)
        record = logging.Handler.format(self, record)
        return record

    @QtCore.pyqtSlot()
    def autoScroll(self):
        self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.status_handler = QHandler()
        self.setCentralWidget(self.status_handler)

        logging.getLogger().addHandler(self.status_handler)
        self.status_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
        logging.getLogger().setLevel(logging.DEBUG)
        timer = QtCore.QTimer(self, interval=1000, timeout=self.on_timeout)
        timer.start()

    def on_timeout(self):
        logging.info('From Gui Thread {}'.format(QtCore.QDateTime.currentDateTime().toString()))


class Subprocess_Thread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.logger = logging.getLogger(self.__class__.__name__)
        self.logger.info('Subprocess Thread Created')

    def run(self):
        while True:
            t = random.choice(["info", "warning", "error", "critical"])
            msg = "Type: {}, thread: {}".format(t, threading.currentThread())
            getattr(self.logger, t)(msg)
            QtCore.QThread.sleep(1)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
        app.setStyle('Fusion')
    w = MainWindow()
    w.show()
    th = Subprocess_Thread()
    th.daemon = True
    th.start()
    sys.exit(app.exec_())

或者,如果您从代码中删除var updateList = db2.Where(r=> Tool = r.Field<string>("Tool") && Product = r.Field<string>("Product") && Time1 = r.Field<DateTime>("Time1") && Row = r.Field<Int32>("Row")); foreach (var ul in updateList) ul.Count = updateList.Count(); ,则可以保留对原始数据的引用:

Select

答案 1 :(得分:0)

显然,您设计的是可以通过ToolProduct等值来标识度量:如果您有两项具有相同的Tool,{{1 }}等,它们属于同一度量标准组,甚至可能是同一度量标准。

为防止我不得不一遍又一遍地说“相同的工具,产品等”,我将这些属性的集合称为Product。因此,每当我说MeasurementId时,我的意思是属性Tool / Product / Timel / Row

问题描述

如果您使用相同的MeasurementId进行了两次测量,则可能是重新测量。因此,每当操作员选择其他MeasurementId具有相同测量值的测量时,您都想警告操作员,如果操作员选择了最早的测量值,可能就不会发出警告。

您的问题似乎类似于在数据库中保留某事物的多个版本。如果有人向您的数据库中添加了具有相同“ MeasurementId MeasurementId文件. but with a different版本”的新项。

如果操作员未选择最早的版本,则要对其进行警告。

您选择了以下解决方案:

  

我希望能够从中获取计数并将其添加回初始数据表db2

不要在表中添加计数,而是考虑添加“先前版本”的ID,如果没有先前版本,则添加0。

, it is as if you add a new

在添加度量之前,请检查是否已经存在类似度量:

class Measurement
{
     public int Id {get; set;}
     public int File {get; set;}

     // measurement identification
     public string Tool {get; set;}
     public string Product {get; set;}
     ...

     // you wanted to add a Count, instead add a previous version
     public int PreviousMeasurementId {get; set;}   // 0 if no previous measurement
}

现在,如果已经有相似的度量,则lastMeasurementVersionId是最后一个相似的度量的ID。如果没有,则该值等于0。

在将lastMeasurementVersionId分配给void AddMeasurement(Measurement measurementToAdd) { var lastMeasurementVersionId = dbContext.Measurements .Where( measurement => // select with same measurementId: measurement.Tool == measurementToAdd.Tool && measurement.Product == measurementToAdd.Product && ...) // from the remaining versions, keep the one with the highest File: .OrderByDescending(measurement => measurement.File) // I'm only interested in the Id of this measurement .Select(measurement => measurement.Id) .FirstOrDefault(); 后添加新的测量值:

PreviouseMeasurementId

这将如何帮助我解决问题?

如果操作员选择了 measurementToAdd.PreviousMeasurementId = lastMeasurementVersionId; dbContext.Measurements.Add(measurementToAdd); dbContext.SaveChanges(); } ,那么您唯一要做的就是检查Measurement的值。如果为零,则操作员选择了第一个测量;如果不为零,则可以警告操作员此测量有多个版本。所选的可能是重新测量。

可能的改进:

  • 考虑为复合PreviousMeasurementId添加一个额外的索引。 MeasurementId的值不会经常更改,但是使用此MeasurementId获取所有度量的查询要快得多
  • 如果您对所有版本都不感兴趣,但实际上仅对第一个版本感兴趣,请不要记住MeasurementId,而要记住PreviousMeasurementId