2014-01-21 3 views
1

Я получаю сообщение о том, что выглядит довольно простым QueryOver. Усложнение состоит в том, что выбор включает CompositeId.nhibernate query compositeid exception

Ошибка я получаю:

System.InvalidOperationException: переменная 'х' типа '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); 
    } 

Любые мысли или указатели были бы весьма благодарны.

Thanks,

Bruce.

обновленный код

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» к родительскому (Query), чтобы исправить недопустимое имя столбца, которое появилось в результате. Исправлен код, размещенный выше –

+0

Действительно здорово это увидеть. NHibernate определенно НЕ легко учится, чтобы попасть. на самом деле это не так. но позже ...;) –

Смежные вопросы