是否可以使用常见查询扩展实体模型?

时间:2012-05-11 13:50:29

标签: c# asp.net-mvc-3 linq entity-framework-4

假设我有一组Sites,其集合为Users。每当我必须重新定义查询以获取给定User的上次访问site时,我发现自己违反了DRY主体。

例如,我的查询可能如下所示:

from site in Context.Sites
where site.ID == 99
select new {
  ID = site.ID,
  Name = site.Name,
  URL = site.URL,
  LastVisitedUser = site.Users.OrderByDescending(u => u.LastVisited).Select(u => new {
      ID = u.ID,
      Username = u.Username,
      Email = u.EmailAddress
   })
   .FirstOrDefault()
}

该查询返回我想要的内容,但我发现自己在多个地方为LastVisitedUser重复这个相同的选择,因为我以不同的方式选择网站来填充我的各种ViewModel。

所以,我认为我只是使用如下属性扩展我的Site Entitiy类:

public partial class Site {
  public LastVisitedUser {
    get {
      var query = from user in Users
                  where user.SiteID == this.ID
                  orderby user.LastVisited descending
                  select user;
      return query.FirstOrDefault()
    }
  }
}

通过这种方式,每当我选择一个网站时,抓住这个属性都是相当简单的。这个几乎有效,但是我试图将我的UserViewModel属性中的Entity用户分配到我的返回的LastVisited属性,而没有明显的方法来如何将User投影到我的ViewModel中版本

也许一个例子可以帮助解释。我想要完成的事情是这样的:

from site in Context.Sites
where site.ID == 99
select new SiteViewModel {
  ID = site.ID,
  Name = site.Name,
  URL = site.URL,
  LastVisitedUser = site.LastVisitedUser <--- NOTE    
}

注意=这是我的失败点。 LastVisitedUser是一个ViewModel,其中包含User个数据的子集。

我是否以正确的方式解决这个问题?我可以实现我想要做的事情,还是我可怕的被误导?我是否想要解决这个问题并遇到其他问题?

谢谢!

2 个答案:

答案 0 :(得分:3)

编辑:前一个答案不正确。您不能在导航属性上使用扩展方法,但仍可以为整个Site投影创建扩展方法。

只需创建简单的可重用扩展方法:

public static IQueryalbe<SiteModel> GetSiteModels(this IQueryable<Site> query)
{
    return query.Select(site => new SiteModel {
                     ID = site.ID,
                     Name = site.Name,
                     URL = site.URL,
                     LastVisitedUser = site.Users
                                           .OrderByDescending(u => u.LastVisited)
                                           .Select(u => new LastVisitedUser {
                                                ID = u.ID,
                                                Username = u.Username,
                                                Email = u.EmailAddress
                                            }});
}

现在,您应该能够在之前的查询中使用该扩展程序:

Context.Sites.Where(site => site.ID == 99).GetSiteModels();

您的示例无效,因为您的属性对于Linq-to-entities不可见。

答案 1 :(得分:0)

如果您的意思是重复使用具有不同扩展名的常见查询,那么您只需要编写一些基本查询并获得不同的结果和一些Where lambda表达式。如果您对其进行分析,您将看到只有一个查询到DB只是在基本查询中返回IQuerable