簡體   English   中英

LINQ / Entity Framework復雜查詢:占據所有行

[英]LINQ /Entity Framework complex query: take all rows

首先,請原諒我的頭銜,因為我找不到我要解決的問題的有意義的頭銜。

我有3個表,“公司”,“設備”和“度量值”,一個公司可以有很多設備,而“度量”表每5分鍾具有每個設備的溫度數據。

我用這個畫了一張桌子: 在此處輸入圖片說明

問題是:

我需要執行一個使我返回的LINQ / EF查詢:1.每個公司每個設備的最新溫度。

因此,如果您看到圖片中的表格,它將返回以下內容:

在此處輸入圖片說明

我在C#中的模型是這樣的:

public class Medida
    {
        [Key]
        [DisplayName("Medida")]
        public int MedidaID { get; set; }

        public decimal Temperatura { get; set; }
        public int Humedad { get; set; }

        public DateTime FechaHora { get; set; }

        [DisplayName("Dispositivo")]        
        public int DispositivoID { get; set; }
        public virtual Dispositivo Dispositivo { get; set; }



    }

設備:

    [Table("Dispositivo")]
    public class Dispositivo  // 
    {
        [Key]
        [Column(Order = 0)]

        public int DispositivoID { get; set; }

        [StringLength(100)]
        [Required(ErrorMessage = "El nombre  es requerido")]
        public string Nombre { get; set; }

        public string ClaveDispositivo { get; set; }

        public bool Activo { get; set; }
        [Required(ErrorMessage = "El nombre Empresa es requerido")]
        [Display(Name = "Empresa")]
        public int EmpresaID { get; set; }

        public virtual Empresa Empresa { get; set; }

        public virtual ICollection<Medida> Medidas { get; set; }
    }
}

和公司表

  public partial class Empresa
    {
        [Key] //clave primaria en la tabla
        [Display(Name = "Empresa")]
        public int EmpresaID { get; set; }//metodos de acceso de lectura y escritura a la propiedad

        [StringLength(100)] // no debe pasarse de 100 caracteres
        [Required(ErrorMessage = "El nombre empresa es requerido")]
        [DisplayName("Nombre Empresa")]
        public string Nombre { get; set; }

        [StringLength(100)]
        //[Required(ErrorMessage = "El código es requerido")]
        [DisplayName("Código")]
        public string Codigo { get; set; } 

        [Display(Name = "Correo")]
        [Required(ErrorMessage = "El correo es requerido")]
        [EmailAddress(ErrorMessage = "dirección de correo invalido")]

        public string Correo { get; set; }
        public bool Activo { get; set; }
        public bool Notificar_Correo { get; set; }
        public bool Notificar_SMS { get; set; }

        public virtual ICollection<Dispositivo> Dispositivos { get; set; }
        public virtual ICollection<Usuario> Usuarios { get; set; }
    }

最后,這是我試圖在需要限制返回的行的地方實現的代碼:

 public void TakeLastTemp()
            {

                using (ZigBeeContext db = new ZigBeeContext())
                {
                    var lista = db.Medidas
                                 .Include(e => e.Dispositivo);

您可以通過其FechaHora datetime屬性以降序對測量進行排序,並采用第一個。

from e in db.Empresas
from d in e.Dispositivos 
let lastMeasurement = d.Medidas.OrderByDescending(m => m.FechaHora)
                               .FirstOrDefault()
select new
{
    Empresa = c.Nombre,
    Dispositivo = d.Nombre,
    lastMeasurement.FechaHora,
    lastMeasurement. ... // etc.
}

請記住,整個LINQ語句已轉換為SQL,因此您不必擔心lastMeasurement.FechaHora等中的空引用。唯一的問題是,如果存在沒有測量值的設備,則必須將非空類型轉換為可空:

(DateTime?)lastMeasurement.FechaHora

我建議更改一下數據庫表結構,在設備表中添加其他字段LastTemperature,並更改更新表中溫度的代碼,在此表中添加新行並更新Device表中歸檔的LastTemperature的測量值,然后即可輕松查詢它與Linq。 它將簡化您的查詢。 有這個主意嗎?

如果首先在sql中決定查詢,然后考慮使用LINQ或EF實施,則總是很容易的。

可以從下面的SQL查詢中檢索圖像中表的結果。

SELECT m.* FROM dbo.Measures m
JOIN 
(SELECT IdDevice,MAX(datetime) AS sdatetime FROM dbo.Measures
GROUP BY IdDevice) s
ON s.IdDevice = m.IdDevice AND m.[datetime] = s.sdatetime

在EF中,不能以這種方式完成include measure.include(device),因為它是根據表設計包含許多度量的設備。

由於所需數據來自度量表,因此可以按如下方式使用LINQ查詢。 我已經根據圖像使用了表名和列名。

var subquery = db1.Measures.GroupBy(row => new { id = row.IdDevice }).Select(Finalrow => new
            {
                IdDevice = Finalrow.Key.id,
                datetime = Finalrow.Max(d => d.datetime)
            });
var mainquery = db1.Measures.Join(subquery, m => m.IdDevice, s => s.IdDevice, (m, s) => new { m, s }).Where(deviceid => deviceid.m.datetime == deviceid.s.datetime).Select(Finalrow => new
            {
                id = Finalrow.m.IdMeasure,
                temp = Finalrow.m.temp,
                deviceid = Finalrow.m.IdDevice,
                date = Finalrow.m.datetime
            });

希望這可以幫助。 如有問題,請通知我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM