域模型性能中的ICollection

时间:2016-06-02 11:57:24

标签: c# entity-framework domain-model

我有以下数据库上下文,我使用Entitry Framework

public class MainContext: DbContext
{
    public MainContext()
        : base("name=MainContext")
    { }

    public virtual DbSet<Device> Devices { get; set; }
    public virtual DbSet<Point> Points { get; set; }
}

使用以下域模型

public class Point
{
    [Key]
    public int Id { get; set; }

    public string Info { get; set; }
    public DateTime FixTime { get; set; }

    public int DeviceId { get; set; }
    public virtual Device Device { get; set; }
}

public class Device
{
    [Key]
    public int Id { get; set; }

    public int SomeValue { get; set; }

    public virtual ICollection<Point> Points { get; set; }

    public bool IsActive()
    {
        Point lastPoint = Points.LastOrDefault();
        if (lastPoint == null) 
        { 
            return false; 
        }
        else
        {
            var diff = DateTime.Now - lastPoint.FixTime;

            if (diff.TotalSeconds > 10 )
            {
                return false;
            } 
            else
            {
                return true;
            }
        }
    }
}

我在Device类中调用IsActive()方法时遇到了巨大的性能问题。据我所知,由于调用Points.LastOrDefault()会查询Device的所有可用数据库记录而不是唯一的数据库记录。我明白这是因为在我的班级中使用了ICollection,但那是Entity Framework的需求。有没有办法在这种情况下查询唯一的记录,或者只是我把方法放在错误的地方?

2 个答案:

答案 0 :(得分:1)

  

有没有办法在这种情况下查询唯一的记录,或者只是我把方法放在错误的地方?

如果你问我,后者。您比Entity Framework更了解您想要查询的内容:只要您访问延迟加载的导航集合属性Points,它就会加载该设备的整个集合。

此外,LastOrDefault()在数据库环境中没有任何意义,因为逆转排序相对便宜。

另外,since you specify no order, the order isn't guaranteed, so this code is guaranteed to break some day (LastOrDefault() returning a different record)

话虽这么说,我不喜欢执行查询的实体模型,至少在ORM的情况下,尤其是实体框架,所以我将这个逻辑移到一个单独的类中。称之为PointGetter或给它起个名字。

在那里,你可以进行查询:

public class PointGetter
{
    public Point GetLastPoint(DbContext dbContext, Device device)
    {
        var lastPointForDevice = dbContext.Points
                                          .Where(p => p.Device == device)
                                          .OrderByDescending(p => p.FixTime)
                                          .FirstOrDefault();
        return lastPointForDevice;
    }
}

答案 1 :(得分:0)

为什么不尝试.OrderByOrderByDescending然后FirstOrDefault。如果你的数据库中有适当的索引,这应该足够快,只能带回一条记录。