【问题标题】:ICollection in domain model performance领域模型性能中的 ICollection
【发布时间】:2016-06-02 11:57:23
【问题描述】:

我有以下与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() 查询设备的所有可用数据库记录,而不是唯一一个。我知道这是因为在我的课堂上使用了 ICollection,但这是实体框架的需求。在这种情况下有什么方法可以查询唯一的记录还是只是我把方法放在了错误的地方?

【问题讨论】:

    标签: c# entity-framework domain-model


    【解决方案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;
        }
    }
    

    【讨论】:

    • 好吧解决我的问题,最后我做了这样的东西,但我觉得这不是最好的方法。
    【解决方案2】:

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

    【讨论】:

    • 这是我做的第一件事,使用了 OrderByDescending 和 FirstOrDefault。此外,我在调用 FirstOrDefault 之前尝试使用 Take(1)。查询 EF 为所有记录生成无论如何调用/
    猜你喜欢
    • 2010-12-20
    • 1970-01-01
    • 2012-12-11
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多