我有以下虚构的域类:
public class Pony
{
public string Name { get; set; }
public DateTime FoundDate { get; set; }
}
public class Person
{
public ICollection<Pony> Ponies { get; private set; }
public Pony NewestPony
{
get
{
return Ponies
.OrderBy(pony => pony.FoundDate)
.FirstOrDefault();
}
}
}
NewestPony
属性封装了一个域规则,用于确定幸运者找到的最新小马。
我可以使用Enumerable
扩展方法来使用此属性:
IEnumerable<Person> people = GetPeople();
people.Where(p => p.NewestPony != null);
这很棒。
但是,people
是SQL Server(本例中为NHibernate)的IQueryable
外观,查询必须由查询提供程序处理并转换为SQL。由于数据库中没有物理“NewestPony”列,查询提供程序将阻塞查询。
要解决此问题,我可以在查询中展开该属性,将其替换为get
实现:
IEnumerable<Person> people = GetPeople();
person.Where(p
=> p.Ponies.OrderBy(pony => pony.FoundDate).FirstOrDefault() != null);
因为查询提供程序了解SQL Server中的关系,所以它现在可以评估此查询。
此解决方案虽然可行,但却复制了之前封装的规则。我正在寻找一种方法来避免这种重复行为,甚至可能是一种扩展查询提供程序中的属性以允许它生成正确的SQL语句的方法。
答案 0 :(得分:1)
你遇到了一个典型的问题。有几种方法可以解决这个问题。如果使用某些自动化,则应排除该属性,如果使用普通映射(HBM文件),则可以忽略该属性。但是,根据LINQ声明,您可能仍然会出错,正如您所解释的那样。以下是一些解决方法:
Pony GetNewestPony()
作为声明。同样地,我在POCO中使用GetFullName()
解决了这个问题,partial
结合了名字,姓名,中间名。快速解决方法:使用nr 1或2.对于一个彻底的未来修复,改变你的架构,否则NHibernate会在后面咬你,而不是帮助你。
修改强>
下面,adriaanp使用扩展方法的痛点,我相信他是对的。因为我几乎总是使用自动生成的DTO,所以我希望它们与我手工介绍的任何方法完全分开。如果我想在对象上使用它们,而不是作为扩展方法,Microsoft为此目的引入了{{1}}类(在类本身中扩展自动生成的类,而不会丢失往返工程)。但是在这里:小心不要弄乱它,明确的文件名可以帮助很多。
答案 1 :(得分:1)
这不会完全解决您的问题,但也许可以提供帮助。 Using an NHibernate Formula to aid searching