2014-01-21 56 views
1

我收到了一个看起来相当简单的QueryOver的错误。复杂的是,选择涉及一个CompositeId。nhibernate查询compositeid异常

我得到的错误是:

System.InvalidOperationException:变量 'X' 类型的 'nha.cs.utility.mole.QueryParameters' 从范围'refrenced,但 不定义。

我正在映射具有许多查询参数的查询。复合标识符包含查询和查询参数名称,如下所示。

public class Query 
{ 
    public virtual int id { get; protected set; } 
    public virtual string name { get; set; } 
    public virtual string query { get; set; } 
    public virtual IList<QueryParameters> parameters { get; set; } 
    public virtual IList<Application> applicationsUsedIn { get; set; } 

    public Query() 
    { 
     this.parameters = new List<QueryParameters>(); 
     this.applicationsUsedIn = new List<Application>(); 
    } 

    public virtual void AddParameter(QueryParameters qp) 
    { 
     qp.query = this; 
     this.parameters.Add(qp); 
    } 
} 


public class QueryParameters 
{ 
    public virtual Query query { get; set; } 
    public virtual string name { get; set; } 
    public virtual string type { get; set; } 
    public virtual int order { get; set; } 

    public QueryParameters() 
    { 
    } 

    public QueryParameters(Query qry, string nm) 
    { 
     this.query = qry; 
     this.name = nm; 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj == null) 
      return false; 
     var t = obj as QueryParameters; 
     if (t == null) 
      return false; 
     if (query == t.query && name == t.name) 
      return true; 
     return false; 
    } 
    public override int GetHashCode() 
    { 
     return (query.id + "|" + name)).GetHashCode(); 
    } 
} 


public QueryMap() 
    { 
     Table("dbo.Queries"); 
     Id(x => x.id); 
     Map(x => x.name); 
     Map(x => x.query); 
     HasMany(x => x.parameters) 
      .Cascade.All() 
      ; 
     HasManyToMany(x => x.applicationsUsedIn) 
      .Table("dbo.ApplicationsQueries") 
      .ParentKeyColumn("qryid") 
      .ChildKeyColumn("appid") 
      .Inverse() 
      .LazyLoad(); 
    } 


public QueryParametersMap() 
    { 
     Table("dbo.QueryParameters"); 
     CompositeId() 
      .KeyReference(x => x.query) 
      .KeyProperty(x => x.name) 
      ; 
     References(x => x.query).Column("qryid").Not.Insert(); 
     Map(x => x.name); 
     Map(x => x.order); 
     Map(x => x.type); 
    } 


public Query addParameterToQuery(Query qry, string paramname, string paramtype, int paramorder) 
    { 
     if (null != qry) 
     { 
      string qryname = qry.name; 
      string qrystr = qry.query; 

      using (ISessionFactory isf = getSessionFactory()) 
      { 
       using (var sess = isf.OpenSession()) 
       { 
        using (var tran = sess.Transaction) 
        { 
         try 
         { 
          tran.Begin(); 

          var critqry = sess.CreateCriteria<Query>() 
           .Add(Restrictions.Eq("name", qryname)); 

          Query qryd = (Query)critqry.UniqueResult(); 

          if (null == qryd) 
          { 
           qryd = new Query(); 
           qryd.name = qryname; 
           qryd.query = qrystr; 
           sess.Save(qryd); 

           Console.Out.WriteLine("Query was null, added new query with name '" + qryname + "'"); 
          } 
          else 
          { 
           Console.Out.WriteLine("Query was not null, has name '" + qryname + "'"); 
          } 

          //EXCEPTION THROWN ON THIS LINE BELOW 
          var cp = sess.QueryOver<QueryParameters>() 
           .Select(x => x.query == qryd, x => x.name == paramname); 

          QueryParameters qryparam = cp.List().First<QueryParameters>(); 

         } 
         catch (Exception ex) 
         { 
          tran.Rollback(); 
          lws.logMessage(AppName, "addParameterToQuery", ex.ToString(), MessageType.Info, MessageLevel.Error); 
          Console.Out.WriteLine(ex.ToString()); 
         } 
        } 
       } 
      } 
     } 

     return (null); 
    } 

任何想法或指针将不胜感激。

谢谢,

布鲁斯。

更新的代码

public class QueryMap : ClassMap<Query> 
{ 
    public QueryMap() 
    { 
     Table("dbo.Queries"); 
     Id(x => x.id); 
     Map(x => x.name); 
     Map(x => x.query); 
     HasMany(x => x.parameters) 
      .Cascade.All() 
      .KeyColumn("qryid"); 
     HasManyToMany(x => x.applicationsUsedIn) 
      .Table("dbo.ApplicationsQueries") 
      .ParentKeyColumn("qryid") 
      .ChildKeyColumn("appid") 
      .Inverse() 
      .LazyLoad(); 
    } 
} 


public class QueryParametersMap : ClassMap<QueryParameters> 
{ 
    public QueryParametersMap() 
    { 
     Table("dbo.QueryParameters"); 
     Id(x => x.id); 
     References(x => x.query).Column("qryid").Not.Insert(); 
     Map(x => x.name); 
     Map(x => x.type); 
     Map(x => x.order).Column("ordr"); 
    } 
} 


var cp = sess.QueryOver<QueryParameters>() 
     .Where(x => x.query.id == qryd.id) 
     .And(x => x.name == paramname); 

回答

1

的一个问题是.Select()作为过滤部分的使用。当使用QueryOver我们必须使用.Where()代替:

var cp = sess.QueryOver<QueryParameters>() 
    //.Select(x => x.query == qryd, x => x.name == paramname) 
    .Where(x => x.query.Id == qryd.ID) 
    .And(x => x.name == paramname) 
    .List<QueryParameters>(); 

16.2. Simple Expressions。该.Select()可以缩小结果集,因为它的定义将被用于SELECT子句创建:16.6. Projections

,包括更多相关的对象/实体进入查询我们可以使用16.4. Associations(也就是联合相关表)

注:布鲁斯,如果可能的话,我会尝试重新考虑域模型。多对多和复合id是一些复杂的迹象(如果不是过于复杂)。在鼓励人们使用异国情调的地图之前,我尝试了许多时间......这是为了传统目的。也许检查这个部分:24. Best Practices

+0

Radim,非常感谢你的帮助。我也接受了您的建议并创建了一个主键,它解决了我遇到的其他问题,并简化了我的代码。 –

+0

我确实需要向父级(查询)添加一个'KeyColumn'来修复由此产生的无效列名。固定代码张贴在上面 –

+0

看到这一切真是太棒了。 NHibernate绝对不容易学习,进入。真的不是。但后来...;) –