需要协助建立一个实体框架4查询

问题描述:

我的上下文模型有几个相关的表:需要协助建立一个实体框架4查询

CREATE TABLE "CarSystem"."Reads" (
    "ReadId"     UUID   PRIMARY KEY, 
    . . . 
); 

CREATE TABLE "CarSystem"."Alarms" (
    "AlarmId"     UUID   PRIMARY KEY DEFAULT UUID_GENERATE_V4(), 
    "ReadId"     UUID   NOT NULL REFERENCES "CarSystem"."Reads"     ("ReadId"), 
    . . . 
); 

还有其他列,但他们并不重要。 Reads表和Alarms表之间存在零关系。对于Reads表中的每行,Alarms表中可以有任意数量的行,从零开始。

我有这个数据库结构的实体框架模型。我还为Reads表中的行获得了ViewModel对象。我希望ViewModel对象具有名为HasAlarms的布尔属性。如果Reads表中的行的Alarms表中至少有一行,则此属性将设置为true。

我在我的数据访问层中有一个函数,它应该返回一个Read ViewModel对象的数组,这些对象都符合一组条件。我不知道如何构建查询来设置HasAlarms属性。我只想进入数据库一次,并且我希望读数表中的每一行都有一个入口。

现在,我做两个数据库查询,一个检索所有的读取和另一检索所有的报警:

IQueryable<Read> query = from read in context.Reads 
         where SomeCondition 
         select read; 

Alarm[] alarms = (from read in query 
        join alarm in context.Alarms on read.Readid equals alarm.ReadId 
        select alarm).ToArray(); 

ReadViewModel[] result = (from read in query 
          select new ReadViewModel { 
           ReadId = read.ReadId, 
           . . . 
           HasAlarms = alarms.Where(a => a.ReadId == read.ReadId).Any(), 
           . . . 
          }).ToArray();  

这工作,而是因为我打的数据库是低效两次,一次检索Reads表中的行,一次获取Alarms。

有没有办法建立这个查询,所以它只碰到数据库一次?

托尼

@Craig斯顿茨:

我试图做的是加快在该数据被加载在我的应用程序响应报告请求的速率。这是一个WPF应用程序,我需要尽快加载数据以改善用户体验。尽可能少地访问数据库或应用程序似乎要抓取很重要。

ReadViewModel对象由映射到表中的列的属性以及存储为同一个表中的列或存储在几个相关表中的行中的几个嵌套对象组成。这是一个复杂的结构,如果我试图用一个IQueryable创建视图模型对象,实体框架会抱怨。也就是说,这样的:

ReadViewModel[] reads = (from read in context.Reads 
          join alarm in context.Alarms on read.ReadId equals alarm.ReadId 
          where SomeCondition 
          select new ReadViewModel { ... }).ToArray(); 

抛出,说实体框架不能创建嵌套类型的一个恒定的异常。

如果我将数据检索到实体对象数组中,然后使用Linq创建视图模型对象,那么一切正常。但是,我不得不多次访问数据库才能获得所有内容。但是,如果使用这些查询检索所有数据,它比让Entity Framework返回并查询每行的额外数据要快得多,当按照您的建议执行操作时会发生这种情况。还有一个复杂的情况是不得不使用Alarms表进行左外连接来搞砸。

我发现,如果我首先检索实体对象的数组,而不是为每行除了最初的旅程之外进行一次旅行,我总共可以进行2次或3次旅行。这比制作n + 1或n + 2旅行要快得多。我只是试图看看是否有一种方法可以让Entity Framework在一次数据库调用中完成所有工作,如果我自己编写SQL,那么我可以轻松完成。如果Read的Alarms表中至少有一行,我只需添加一个为HasAlarms返回0或1的列。

在模型中使用导航/关系。 It's usually wrong to spell out joins in L2E

ReadViewModel[] result = (from read in context.Reads 
          where SomeCondition 
          select new ReadViwModel 
          { 
           ReadId = read.ReadId, 
           // . . . 
           HasAlarms = read.Alarms.Any(), 
           // . . . 
          }).ToArray();  
+0

Plesase看到我编辑原来的问题。 – 2011-12-30 15:46:08

+0

我给你的查询在一次往返中获取整个结果集。 – 2011-12-30 17:25:42