在NHibernate中,以下工作完全正常:
Session.Get(repoType.ToString(), id))
但是这个:
Session.QueryOver(repoType.ToString(), func)
由于某种原因,没有。从文档中,两种方法都将实体名称作为字符串作为第一个参数,但QueryOver会抱怨以下错误消息:
The type arguments for method 'NHibernate.ISession.QueryOver<T>(string, System.Linq.Expressions.Expression<System.Func<T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
我很确定这是由QueryOver的第一个参数(entityName参数)引起的,而不是func参数引起的。
为什么ISession.Get可以从给定的实体名称推断实体类型,但ISession.QueryOver不能?
答案 0 :(得分:1)
这不是nHibernate库的问题,它是.NET泛型和Linq表达式的问题。
NHibernate可能能够推断出实体类型,但你必须首先编译代码。 : - )
QueryOver函数的签名如下:
IQueryOver<T, T> QueryOver<T>(string entityName, Expression<Func<T>> alias) where T : class;
请注意,Func<T>
与System.Linq.Expressions.Expression<T>
的类型不同。
在您的示例中,我假设您已将Func<T>
声明为单独的变量,并且编译器无法确定要将其转换为什么。
以下是电话会议的一些变体:
// Defining the second parameter explicitly as an expression.
// This works
Company companyAlias = null;
System.Linq.Expressions.Expression < Func < Company >> expression = () => companyAlias;
var q1 = this.Session.QueryOver("Company", expression);
我们可以让编译器将内联lambda转换为表达式。这也有效,编译器会推断所有类型参数。
var q2 = this.Session.QueryOver("Company", () => companyAlias);
如果我们使用普通函数对象而不是表达式,它将失败。
在这里,编译器无法弄清楚如何使Func<Company>
适合通用表达式。因此错误&#34;类型参数不能通过用法来推断......&#34;
Func<Company> func = () => companyAlias;
var q3 = this.Session.QueryOver("Company", func);
我们通过明确说明类型来帮助编译器。下面的代码仍然会失败,但我们会得到更好的错误。 &#34;对...的最佳重载匹配有一些无效的参数&#34;
var q4 = this.Session.QueryOver<Company>("Company", func);
如果可能,最好将类型作为通用表达式而不是名称。这样,如果您重命名该类型但忘记更改函数中的字符串,则可以避免潜在的错误。
var q = session.QueryOver<Company>(() => companyAlias);
在这种情况下,您甚至不必将通用参数放入。
var q = session.QueryOver(() => companyAlias);
但是,为了便于阅读,我更喜欢保留泛型参数。