2014-01-21 93 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絕對不容易學習,進入。真的不是。但後來...;) –