C# 是否可以使用公共查询扩展实体模型?
假设我有一组C# 是否可以使用公共查询扩展实体模型?,c#,asp.net-mvc-3,linq,entity-framework-4,C#,Asp.net Mvc 3,Linq,Entity Framework 4,假设我有一组网站,其中有一组用户。每当我必须重新定义查询以获取(比如)给定站点的上次访问用户时,我发现自己违反了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.
网站
,其中有一组用户
。每当我必须重新定义查询以获取(比如)给定站点的上次访问用户时,我发现自己违反了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()
}
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的相同选择,因为我正在以不同的方式选择站点以填充各种ViewModels
所以,我想我应该简单地用如下属性扩展我的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属性中,并将其分配到我的return的LastVisited属性中,对于如何将用户
投影到我的ViewModel版本中,我没有一个明显的方法
也许举个例子可以帮助解释。我想实现的是这样的目标:
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()
}
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
}
来自上下文中的站点。站点
其中site.ID==99
选择新的SiteViewModel{
ID=site.ID,
Name=site.Name,
URL=site.URL,
LastVisitedUser=site.LastVisitedUser编辑:前一个答案不正确。您不能在导航属性上使用扩展方法,但仍然可以为整个站点
投影创建扩展方法
只需创建简单的可重用扩展方法:
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
}});
}
您的示例将不起作用,因为您的属性对于Linq to实体不可见。编辑:前面的答案不正确。您不能在导航属性上使用扩展方法,但仍然可以为整个站点创建扩展方法
只需创建简单的可重用扩展方法:
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
}});
}
您的示例将不起作用,因为您的属性对于Linq to实体不可见。如果您的意思是要重用具有不同扩展名的常见查询,您只需编写一些基本查询并获得不同的结果和一些Where lambda表达式。如果您对其进行分析,您将看到只有一个查询需要DB just retu基本查询中的iqerable如果您的意思是要重用具有不同扩展名的常见查询,您只需编写一些基本查询,并获得不同的结果和一些Where lambda表达式。如果您对其进行分析,您将看到您只有一个对DB的查询,而在基本查询中只返回iqerable是否调用了这些方法我的存储库中。我的控制器正在处理IEnumerable变量或具体对象。这些方法是从控制器调用的,还是在哪一层上需要这些查询?在我的存储库中。我的控制器正在处理IEnumerable变量或具体对象s、 我一直在尝试这一点,但无论我做什么,我总是会遇到一个错误:EntityCollection不包含GetLastUsers()的定义并且找不到接受EntityCollection类型的第一个参数的扩展方法。我甚至在我的存储库类中放置了扩展方法,以确保我没有弄乱名称空间或其他东西。我是否遗漏了什么?没错,它不起作用,因为表达式方法不能在导航属性的投影中使用y、 您必须为整个站点投影创建扩展方法。我一直在尝试此方法,但无论我做什么,都会遇到一个错误:EntityCollection不包含GetLastUsers()的定义并且找不到接受EntityCollection类型的第一个参数的扩展方法。我甚至在我的存储库类中放置了扩展方法,以确保我没有弄乱名称空间或其他东西。我是否遗漏了什么?没错,它不起作用,因为表达式方法不能在导航属性的投影中使用y、 必须为整个场地投影创建扩展方法。