Составное исключение запроса nhibernate
Я получаю сообщение об ошибке, которая выглядит довольно простым QueryOver. Сложность заключается в том, что выбор включает CompositeId.
Я получаю ошибку:
System.InvalidOperationException: переменная 'x' типа 'nha.cs.utility.mole.QueryParameters' refrenced from scope '', но она не определена.
Я отображаю запрос, который имеет много параметров запроса. Составной идентификатор с запросом и именем параметра запроса показан ниже.
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. Простые выражения. .Select()
может сузить набор результатов, потому что его определение будет использоваться для создания предложения SELECT: 16.6. Прогнозы
Чтобы включить больше связанных объектов / сущностей в запрос, мы можем использовать 16.4. Ассоциации (т. Е. Связанные таблицы JOIN)
ПРИМЕЧАНИЕ: Брюс, если возможно, я бы попытался переосмыслить модель предметной области. "Многие ко многим" и составной идентификатор являются признаками чего-то слишком сложного (если не слишком сложного). Я пытался много раз, прежде чем отговаривать людей использовать экзотическое картирование... оно существует в унаследованных целях. Может быть, проверить этот раздел: 24. Лучшие практики