我有以下数据库上下文,我使用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的需求。有没有办法在这种情况下查询唯一的记录,或者只是我把方法放在错误的地方?
答案 0 :(得分:1)
有没有办法在这种情况下查询唯一的记录,或者只是我把方法放在错误的地方?
如果你问我,后者。您比Entity Framework更了解您想要查询的内容:只要您访问延迟加载的导航集合属性Points
,它就会加载该设备的整个集合。
此外,LastOrDefault()
在数据库环境中没有任何意义,因为逆转排序相对便宜。
话虽这么说,我不喜欢执行查询的实体模型,至少在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)
为什么不尝试.OrderBy
或OrderByDescending
然后FirstOrDefault
。如果你的数据库中有适当的索引,这应该足够快,只能带回一条记录。