When I use a filter on my Url as GET /api/modalidades?$orderby=Nome&$select=Nome,Id an error is displayed!
Packages:
FluentNHibernate 1.3.0.733
NHibernate 3.3.3.4000
Microsoft.AspNet.WebApi 5.0.0-rtm-130624
Microsoft.AspNet.WebApi.Client 5.0.0-rtm-130624
Microsoft.AspNet.WebApi.Core 5.0.0-rtm-130624
Microsoft.AspNet.WebApi.OData 5.0.0-rtm-130624
Microsoft.AspNet.WebApi.Web... 5.0.0-rtm-130624
Code
Domain
public class Modalidade : EntityNome
{ }
public abstract class EntityNome : IEntity
{
public virtual int Id { get; protected internal set; }
[StringLength(80)]
[Required]
public virtual string Nome { get; set; }
}
public interface IEntity : IKeyed<int>
{
}
public interface IKeyed<T> where T : struct
{
T Id { get; }
}
Web
WebApiConfig.css
public static void Register(HttpConfiguration config)
{
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Modalidade>("modalidades");
modelBuilder.Entity<Modalidade>()
.DerivesFrom<EntityNome>()
.Property(p => p.Id);
var model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute(routeName: "OData", routePrefix: "api", model: model);
config.EnableQuerySupport();
var jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
var enumConverter = new StringEnumConverter();
jsonFormatter.SerializerSettings.Converters.Add(enumConverter);
config.Formatters.Remove(config.Formatters.XmlFormatter);
var jqueryFormatter = config.Formatters.FirstOrDefault(x => x.GetType() == typeof(JQueryMvcFormUrlEncodedFormatter));
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.Remove(config.Formatters.FormUrlEncodedFormatter);
config.Formatters.Remove(jqueryFormatter);
config.Formatters.JsonFormatter.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
}
Controllers
public class baseApiController<T> : EntitySetController<T, int>
where T : class, IEntity
{
public IRepository<T> Repositorio { get; private set; }
public baseApiController(IRepository<T> repositorio)
{
Repositorio = repositorio;
}
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All, PageSize = 20)]
public override IQueryable<T> Get()
{
return Repositorio.All();
}
[HttpGet, Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
protected override T GetEntityByKey(int key)
{
return Repositorio.Get(key);
}
}
[Authorize]
public class modalidadesController : baseApiController<Modalidade>
{
public modalidadesController(IModalidadeRepository repositorio)
: base(repositorio)
{ }
}
Error
When no filter is applied, everything works. But when a filter is applied, an error is generated!
GET /api/modalidades?$orderby=Nome&$select=Nome,Id HTTP/1.1
Host: localhost:49971
Cache-Control: no-cache
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "An error has occurred."
},
"innererror": {
"message": "Exception has been thrown by the target of an invocation.",
"type": "System.Reflection.TargetInvocationException",
"stacktrace": " at System.Web.Http.ApiController.<InvokeActionWithExceptionFilters>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()",
"internalexception": {
"message": "could not resolve property: class of: CreditoImobiliarioBB.Model.Modalidade [.Take[System.Web.Http.OData.Query.Expressions.SelectExpandWrapper`1[[CreditoImobiliarioBB.Model.Modalidade, CreditoImobiliarioBB.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]](.Select[CreditoImobiliarioBB.Model.Modalidade,System.Web.Http.OData.Query.Expressions.SelectExpandWrapper`1[[CreditoImobiliarioBB.Model.Modalidade, CreditoImobiliarioBB.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]](.ThenBy[CreditoImobiliarioBB.Model.Modalidade,System.Int32](.OrderBy[CreditoImobiliarioBB.Model.Modalidade,System.String](NHibernate.Linq.NhQueryable`1[CreditoImobiliarioBB.Model.Modalidade], Quote(($it, ) => ($it.Nome)), ), Quote(($it, ) => ($it.Id)), ), Quote((, ) => (new SelectExpandWrapper`1()444fb09a-b4c8-43e1-b1f6-d469f9da76eanew NamedPropertyWithNext`1()IdEqual(, NULL) ? NULL : Convert(.Id)new NamedProperty`1()IsType(, CreditoImobiliarioBB.Model.EntityNome) ? Nome : NULLEqual(, NULL) ? NULL : IsType(, CreditoImobiliarioBB.Model.EntityNome) ? TypeAs().Nome : NULL)), ), p8, )]",
"type": "NHibernate.QueryException",
"stacktrace": " at NHibernate.Persister.Entity.AbstractPropertyMapping.ToType(String propertyName)\r\n at NHibernate.Persister.Entity.AbstractEntityPersister.ToType(String propertyName)\r\n at NHibernate.Hql.Ast.ANTLR.Tree.FromElementType.GetPropertyType(String propertyName, String propertyPath)\r\n at NHibernate.Hql.Ast.ANTLR.Tree.FromElement.GetPropertyType(String propertyName, String propertyPath)\r\n at NHibernate.Hql.Ast.ANTLR.Tree.DotNode.GetDataType()\r\n at NHibernate.Hql.Ast.ANTLR.Tree.DotNode.PrepareLhs()\r\n at NHibernate.Hql.Ast.ANTLR.Tree.DotNode.Resolve(Boolean generateJoin, Boolean implicitJoin, String classAlias, IASTNode parent)\r\n at NHibernate.Hql.Ast.ANTLR.Tree.FromReferenceNode.Resolve(Boolean generateJoin, Boolean implicitJoin, String classAlias)\r\n at NHibernate.Hql.Ast.ANTLR.Tree.FromReferenceNode.Resolve(Boolean generateJoin, Boolean implicitJoin)\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.Resolve(IASTNode node)\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.expr()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.exprOrSubquery()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.comparisonExpr()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.caseExpr()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.arithmeticExpr()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectExpr()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectExprList()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectClause()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.unionedQuery()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.query()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectStatement()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.statement()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlTranslator.Translate()\r\n at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Analyze(String collectionRole)\r\n at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 replacements, Boolean shallow, String collectionRole)\r\n at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Compile(IDictionary`2 replacements, Boolean shallow)\r\n at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode ast, String queryIdentifier, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)\r\n at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)\r\n at NHibernate.Engine.Query.HQLExpressionQueryPlan.CreateTranslators(String expressionStr, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)\r\n at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)\r\n at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)\r\n at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)\r\n at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)\r\n at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)\r\n at Remotion.Linq.QueryableBase`1.GetEnumerator()\r\n at System.Web.Http.OData.Query.ODataQueryOptions.LimitResults[T](IQueryable`1 queryable, Int32 limit, Boolean& resultsLimited)"
}
}
}
}
The $select part of the query is the troubling one. We haven't tried to get $select and $expand working with anything other than Linq2Objects and Entityframework. The expression that we generate to get $select and $expand working and in an efficient manner with Entityframework is non-trivial.
That said, one solution to your problem is to take ODataQueryOptions and apply the query in parts. Apply the $filter, $orderby, $skip, $top in the database and then apply $select and $expand in-memory by doing a ToList() after the first step.
I will play further with nhibernate to see if we can improve our expression generation to get this scenario working.
Try adding EnsureStableOrdering = false to your QueryableAttribute:
[Queryable(EnsureStableOrdering = false, AllowedQueryOptions = AllowedQueryOptions.All, PageSize = 20)]
public override IQueryable<T> Get()
Related
I'm building an odata service that is used for reading from sql and then rendering the results in json format. I'm not using entityframework though.
When applying the $select filter, if I have less properties than my model (removing a nullable one), I'm getting the following error. If I have the exact same amount of properties, everything works fine.
{
"error": {
"code": "",
"message": "An error has occurred.",
"innererror": {
"message": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata.metadata=minimal'.",
"type": "System.InvalidOperationException",
"stacktrace": "",
"internalexception": {
"message": "The EDM instance of type '[PrototypeOData.Models.DefaultRule Nullable=True]' is missing the property 'DateLastModified'.",
"type": "System.InvalidOperationException",
"stacktrace": " at System.Web.OData.EntityInstanceContext.GetPropertyValue(String propertyName)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateStructuralProperty(IEdmStructuralProperty structuralProperty, EntityInstanceContext entityInstanceContext)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateStructuralPropertyBag(IEnumerable`1 structuralProperties, EntityInstanceContext entityInstanceContext)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteObject(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__14.MoveNext()"
}
}
}
}
My model looks like this:
public class DefaultRule
{
public string Id { get; set; }
public int? RequestedCount { get; set; }
public DateTime? DateLastModified { get; set; }
}
In my controller the calls are as follows:
public IHttpActionResult Get(ODataQueryOptions<DefaultRule> options)
{
.............
var res = options.SelectExpand.ApplyTo(result, new ODataQuerySettings() { PageSize = 100}).AsQueryable();
//return result;
return Ok(res, res.GetType());
}
private IHttpActionResult Ok(object content, Type type)
{
Type resultType = typeof(OkNegotiatedContentResult<>).MakeGenericType(type);
return Activator.CreateInstance(resultType, content, this) as IHttpActionResult;
}
Is there any way I can mark specific properties as optional?
Any thoughts are appreciated.
This is because your the result of $select is not your original model. Then error occurs in Serialization. Try add the pagesize in attribute like:
[EnableQuery(PageSize=100)]
or create your own attribute
public class MyEnableQueryAttribute : EnableQueryAttribute
{
public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
{
return options.SelectExpand.ApplyTo(result, new ODataQuerySettings() { PageSize = 100}).AsQueryable().
}
}
[MyEnableQueryAttribute]
public IHttpActionResult Get()
{
....
return result;
}
Error when specified $filter {{api}}/Person/Get?$filter=substringof('rid', Name) eq true
Error
{
"$id": "1",
"$type": "System.Web.Http.HttpError, System.Web.Http",
"Message": "An error has occurred.",
"ExceptionMessage": "Exception has been thrown by the target of an invocation.",
"ExceptionType": "System.Reflection.TargetInvocationException",
"StackTrace": " at System.Web.Http.ApiController.<InvokeActionWithExceptionFilters>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()",
"InnerException": {
"$id": "2",
"$type": "System.Web.Http.HttpError, System.Web.Http",
"Message": "An error has occurred.",
"ExceptionMessage": "Exception of type 'Antlr.Runtime.NoViableAltException' was thrown. [.Take[BreezeWithNHiberbate.Model.Person](.OrderBy[BreezeWithNHiberbate.Model.Person,System.Int32](.Where[BreezeWithNHiberbate.Model.Person](NHibernate.Linq.NhQueryable`1[BreezeWithNHiberbate.Model.Person], Quote(($it, ) => (Equal(Equal(Or(Equal(Convert($it.Name), NULL), p1) ? NULLp3 : Convert(Convert($it.Name).Contains(p2, )), p4), p5))), ), Quote(($it, ) => ($it.Id)), ), p6, )]",
"ExceptionType": "NHibernate.Hql.Ast.ANTLR.QuerySyntaxException",
"StackTrace": " at NHibernate.Hql.Ast.ANTLR.ErrorCounter.ThrowQueryException()\r\n at NHibernate.Hql.Ast.ANTLR.HqlSqlTranslator.Translate()\r\n at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Analyze(String collectionRole)\r\n at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 replacements, Boolean shallow, String collectionRole)\r\n at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Compile(IDictionary`2 replacements, Boolean shallow)\r\n at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode ast, String queryIdentifier, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)\r\n at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)\r\n at NHibernate.Engine.Query.HQLExpressionQueryPlan.CreateTranslators(String expressionStr, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)\r\n at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)\r\n at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)\r\n at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)\r\n at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)\r\n at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)\r\n at Remotion.Linq.QueryableBase`1.GetEnumerator()\r\n at System.Web.Http.OData.Query.ODataQueryOptions.LimitResults[T](IQueryable`1 queryable, Int32 limit, Boolean& resultsLimited)"
}
}
When not specified a filter works! {{api}}/Person/Get?
{
"$id": "1",
"$type": "BreezeWithNHiberbate.Model.Person, BreezeWithNHiberbate.Model",
"Name": "Riderman de Sousa Barbosa",
"NickName": "ridermansb",
"Id": 1,
"CreateAt": "2013-06-21T19:38:27.000",
"UpdateAt": "2013-06-21T19:38:27.000"
},
{
"$id": "2",
"$type": "BreezeWithNHiberbate.Model.Person, BreezeWithNHiberbate.Model",
"Name": "Felipe de Sousa Barbosa",
"NickName": "felipegerais",
"Id": 2,
"CreateAt": "2013-06-21T19:38:35.000",
"UpdateAt": "2013-06-21T19:38:35.000"
},
{
"$id": "3",
"$type": "BreezeWithNHiberbate.Model.Person, BreezeWithNHiberbate.Model",
"Name": "Maria Helena de Sousa",
"NickName": " lelena",
"Id": 3,
"CreateAt": "2013-06-21T19:38:41.000",
"UpdateAt": "2013-06-21T19:38:41.000"
}
Source code
public class Person : Auditable
{
[Required]
public virtual string Name { get; set; }
public virtual string NickName { get; set; }
}
public abstract class Auditable : IAuditable
{
public virtual int Id { get; protected set; }
public virtual DateTime CreateAt { get; protected set; }
public virtual DateTime? UpdateAt { get; protected set; }
}
public interface IAuditable : IEntity
{
DateTime CreateAt { get; }
DateTime? UpdateAt { get; }
}
Full code here in BreezeWithNHiberbate folder;
I suspect that NHibernate's LINQ provider is choking on the filter expression because of null checking. Null checking wraps every filter parameter in an expression that NH LINQ can't handle.
WebApi OData turns off null checking for EF, Linq2Sql, and Linq2Objects, but turns it on for everything else. To turn it off, add
HandleNullPropagation = HandleNullPropagationOption.False
to your Querable attribute. So in your BaseApiController, you would have
[HttpGet, Queryable(AllowedQueryOptions = AllowedQueryOptions.All, HandleNullPropagation = HandleNullPropagationOption.False, PageSize = 20)]
public IQueryable<T> Get()
{
return Repositorio.All();
}
Note that if you use [BreezeNHController] (that's Breeze.Nhibernate.WebApi.BreezeNHControllerAttribute) instead of [BreezeController], it automatically applies this option to all the IQueryable methods. It also adds extra logic for handling $expand and for controlling lazy loading during serialization.
Official Breeze support for NHibernate is coming soon. Glad to see you are working with it already.
I use the IClientMessageInspector and it's method BeforeSendRequest, to inspect the request messages. The thing is that some of request messages has members, which members are of type object (in the real scenario thre may be in example string or some other value, which is specified in the KnownType attribute):
[DataContract(Namespace = "")]
[KnownType(typeof(SomeValueDTO))]
public class CenDTO
{
[DataMember]
public string Uri { get; set; }
[DataMember]
public object Value { get; set; }
}
Notice, that in this project the namespaces are not defined anywhere. So on the "BeforeSendRequest" I got exception. And looks like this interface uses not the same DataContractSerializer as in the real service, which hasn't such serialization errors or smth like that.
The error:
The empty string '' is not a valid name.
at System.Xml.XmlTextWriter.LookupPrefix(String ns)
at System.Xml.XmlDictionaryWriter.XmlWrappedWriter.LookupPrefix(String namespaceUri)
at System.Xml.XmlDictionaryWriter.XmlWrappedWriter.WriteXmlnsAttribute(String prefix, String namespaceUri)
at System.Xml.XmlDictionaryWriter.WriteXmlnsAttribute(String prefix, XmlDictionaryString namespaceUri)
at System.Runtime.Serialization.XmlWriterDelegator.WriteXmlnsAttribute(XmlDictionaryString ns)
at System.Runtime.Serialization.XmlWriterDelegator.WriteAttributeQualifiedName(String attrPrefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, XmlDictionaryString name, XmlDictionaryString ns)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteTypeInfo(XmlWriterDelegator writer, XmlDictionaryString dataContractName, XmlDictionaryString dataContractNamespace)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteTypeInfo(XmlWriterDelegator writer, DataContract contract, DataContract declaredContract)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteCenDTOToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter writer, PartInfo part, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameters(XmlDictionaryWriter writer, PartInfo[] parts, Object[] parameters)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BodyWriterMessage.OnBodyToString(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.ToString(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.ToString()
at CID.TopicAnalyst.CIA.Test.Utils.MessageInspector.BeforeSendRequest(Message& request, IClientChannel channel) in D:\git\...\MessageInspector.cs:line 25
at System.ServiceModel.Dispatcher.ImmutableClientRuntime.BeforeSendRequest(ProxyRpc& rpc)
Implementation of "BeforeSendRequest"(The crash is on the .ToString() ):
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if(request.Headers.Count > 0)
{
request.Headers.RemoveAt(0);
}
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
var message = buffer.CreateMessage().ToString();
var resultFile = ConfigurationManager.AppSettings.GetValues("requestFile").First();
_serializer.Write(resultFile, message);
return null;
}
The testing itself is a separate solution, which uses the service's reference.
On the service imnplmentation the operation looks like this:
[ServiceContract]
public interface ISoapService
{
[OperationContract]
SomeListResponseMessage GetSomeList(SomeListRequestMessage request);
}
[MessageContract]
public class SomeListRequestMessage : BaseRequestMessage
{
...
[MessageBodyMember]
public CenDTO Cen { get; set; }
...
}
[DataContract(Namespace = "")]
[KnownType(typeof(SemValueDTO))]
public class CenDTO
{
...
[DataMember]
public object Value { get; set; }
}
Some code of the Testing Solution:
static class Program
{
static void Main(string[] args)
{
while(true)
{
var client = new SoapServiceClient("BasicHttpBinding_ISoapService");
client.Endpoint.Behaviors.Add(new InspectorBehavior());
var soapService = client.ChannelFactory.CreateChannel();
var co = new CooRequestCreator(soapService);
co.CreateAndWriteRequests();
Console.WriteLine("Press y to repeat");
var str = Console.ReadLine();
if(str != "y") break;
}
}
Constructing the request message before calling the service:
class CooRequestCreator : BaseRequestCreator<SomeListRequestMessage>
{
SemValueDTO _semaValue = new SemValueDTO
{
Key = "fb",
Label = "Guild",
Type = "org"
};
public CooRequestCreator(ISoapService soapService) : base(soapService)
{
}
protected override SomeListRequestMessage CreateMinRequest()
{
return new SomeListRequestMessage
{
Cen =
new CenDTO
{
Value = _semaValue,
},
MaxCount = 5
};
}
Maybe someone can has the same experience and can help with that?
I'm using Sharp Architecture 1.6 VS2010 and investigating using GUIDs
but I'm encountering an error that I've been unable to resolve.
Person Entity
using System;
using NHibernate.Validator.Constraints;
using SharpArch.Core.DomainModel;
namespace SharpDemo.Core
{
public class Person : EntityWithTypedId<Guid>
{
[NotNullNotEmpty(Message = "First name must be provided.")]
public virtual string FirstName { get; set; }
[NotNullNotEmpty(Message = "Last name must be provided.")]
public virtual string LastName { get; set; }
}
}
Fluent Mapping
using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Alterations;
using SharpDemo.Core;
namespace SharpDemo.Data.NHibernateMaps
{
public class PersonMap : IAutoMappingOverride<Person>
{
public void Override(AutoMapping<Person> mapping)
{
mapping.Schema("dbo");
mapping.Table("People");
mapping.Id(x => x.Id).GeneratedBy.GuidComb();
}
}
}
The solution successfully builds but encounters the below error when
debugging (which I have been unable to resolve). Any assistance is
appreciated.
Source Error
Line 83: private void InitializeNHibernateSession()
Line 84: {
Line 85: NHibernateSession.Init(
Line 86: webSessionStorage,
Line 87: new string[] { Server.MapPath("~/bin/SharpDemo.Data.dll") },
Stack Trace
[FormatException: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).]
System.Guid..ctor(String g) +2486
NHibernate.Type.GuidType.FromStringValue(String xml) +75
NHibernate.Type.GuidType.StringToObject(String xml) +86
NHibernate.Engine.UnsavedValueFactory.GetUnsavedIdentifierValue(String unsavedValue, IGetter identifierGetter, IType identifierType, ConstructorInfo constructor) +644
[MappingException: Could not parse identifier unsaved-value: 0]
NHibernate.Engine.UnsavedValueFactory.GetUnsavedIdentifierValue(String unsavedValue, IGetter identifierGetter, IType identifierType, ConstructorInfo constructor) +872
NHibernate.Tuple.PropertyFactory.BuildIdentifierProperty(PersistentClass mappedEntity, IIdentifierGenerator generator) +220
NHibernate.Tuple.Entity.EntityMetamodel..ctor(PersistentClass persistentClass, ISessionFactoryImplementor sessionFactory) +696
NHibernate.Persister.Entity.AbstractEntityPersister..ctor(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) +784
NHibernate.Persister.Entity.SingleTableEntityPersister..ctor(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) +379
NHibernate.Persister.PersisterFactory.CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping cfg) +182
NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners) +2117
NHibernate.Cfg.Configuration.BuildSessionFactory() +189
FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory() +76
[FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
* Database was not configured through Database method.
]
FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory() +120
SharpArch.Data.NHibernate.NHibernateSession.CreateSessionFactoryFor(String[] mappingAssemblies, AutoPersistenceModel autoPersistenceModel, Configuration cfg, IPersistenceConfigurer persistenceConfigurer) in e:\WorkSpaces\Git\SharpArchitecture\Trunk\src\SharpArch\SharpArch.Data\NHibernate\NHibernateSession.cs:328
SharpArch.Data.NHibernate.NHibernateSession.AddConfiguration(String factoryKey, String[] mappingAssemblies, AutoPersistenceModel autoPersistenceModel, Configuration cfg, String validatorCfgFile, IPersistenceConfigurer persistenceConfigurer) in e:\WorkSpaces\Git\SharpArchitecture\Trunk\src\SharpArch\SharpArch.Data\NHibernate\NHibernateSession.cs:138
SharpArch.Data.NHibernate.NHibernateSession.AddConfiguration(String factoryKey, String[] mappingAssemblies, AutoPersistenceModel autoPersistenceModel, String cfgFile, IDictionary`2 cfgProperties, String validatorCfgFile, IPersistenceConfigurer persistenceConfigurer) in e:\WorkSpaces\Git\SharpArchitecture\Trunk\src\SharpArch\SharpArch.Data\NHibernate\NHibernateSession.cs:126
SharpArch.Data.NHibernate.NHibernateSession.Init(ISessionStorage storage, String[] mappingAssemblies, AutoPersistenceModel autoPersistenceModel, String cfgFile, IDictionary`2 cfgProperties, String validatorCfgFile, IPersistenceConfigurer persistenceConfigurer) in e:\WorkSpaces\Git\SharpArchitecture\Trunk\src\SharpArch\SharpArch.Data\NHibernate\NHibernateSession.cs:101
SharpArch.Data.NHibernate.NHibernateSession.Init(ISessionStorage storage, String[] mappingAssemblies, AutoPersistenceModel autoPersistenceModel, String cfgFile) in e:\WorkSpaces\Git\SharpArchitecture\Trunk\src\SharpArch\SharpArch.Data\NHibernate\NHibernateSession.cs:51
SharpDemo.Web.MvcApplication.InitializeNHibernateSession() in D:\Web\Mvc\Projects\Temp\SharpDemo\app\SharpDemo.Web\Global.asax.cs:85
SharpDemo.Web.MvcApplication.<Application_BeginRequest>b__3() in D:\Web\Mvc\Projects\Temp\SharpDemo\app\SharpDemo.Web\Global.asax.cs:76
SharpArch.Data.NHibernate.NHibernateInitializer.InitializeNHibernateOnce(Action initMethod) in e:\WorkSpaces\Git\SharpArchitecture\Trunk\src\SharpArch\SharpArch.Data\NHibernate\NHibernateInitializer.cs:46
SharpDemo.Web.MvcApplication.Application_BeginRequest(Object sender, EventArgs e) in D:\Web\Mvc\Projects\Temp\SharpDemo\app\SharpDemo.Web\Global.asax.cs:75
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +68
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
It looks like the unsaved value is being set to 0 by the automapping. Try changing your mapping override to:
mapping.Id(x => x.Id).GeneratedBy.GuidComb().Default(Guid.Empty);
mapping.Id(x => x.Id).GeneratedBy.GuidComb().UnsavedValue(Guid.Empty);
I'm mapping a objectified relationship (the many->many mapping table contains properties),
following this guide.
The SQL generated(see exception) is working and returns what i want(strictly speaking it should have been an inner join?).
But I get a GenericADOException saying:
could not initialize a collection: [Questionnaires.Core.Questionnaire.Questions#CBDEDAFC183B4CD7AF1422423A91F589][SQL: SELECT questions0_.ida_questionnaire_id as ida4_2_, questions0_.ida_questionnaire_question_id as ida1_2_, questions0_.ida_questionnaire_question_id as ida1_5_1_, questions0_.question_no as question2_5_1_, questions0_.ida_question_id as ida3_5_1_, questions0_.ida_questionnaire_id as ida4_5_1_, question1_.ida_question_id as ida1_3_0_, question1_.ida_question_type_id as ida2_3_0_, question1_.description as descript3_3_0_, question1_.validate_max as validate4_3_0_, question1_.validate_min as validate5_3_0_ FROM ida_questionnaire_question questions0_ left outer join ida_question question1_ on questions0_.ida_question_id=question1_.ida_question_id WHERE questions0_.ida_questionnaire_id=?]
I'm guessing this is because Questionnaire is really mapping to QuestionnaireQuestion not Question(Questionnaire->hasMany->QuestionnaireQuestion<-hasMany<-Question). But I can't seem to find a way of going around this.
Question:
public class Question : PersistentObjectWithTypedId<string>
{
#region Constructors
public Question()
{
Alternatives = new List<Alternative>();
Questionnaires = new List<Questionnaire>();
}
public Question(string description)
: this()
{
Check.Require(!string.IsNullOrEmpty(description) && description.Trim() != string.Empty);
Description = description;
}
#endregion
#region Properties
public virtual string Type { get; set; }
public virtual string Description { get; set; }
public virtual int Order { get; set; }
public virtual IList<Questionnaire> Questionnaires { get; set; }
public virtual IList<Alternative> Alternatives { get; set; }
public virtual Validator MyValidator { get; set; }
}
public class QuestionMap : ClassMap<Question>
{
public QuestionMap()
{
WithTable("ida_question");
Id(x => x.ID, "ida_question_id").WithUnsavedValue(0).GeneratedBy.UuidHex("");
Map(x => x.Description, "description").AsReadOnly();
Map(x => x.Type, "ida_question_type_id").AsReadOnly();
Component<Core.Validator>(x => x.MyValidator, m =>
{
m.Map(x => x.Type, "ida_question_type_id");
m.Map(x => x.RangeMin, "validate_min");
m.Map(x => x.RangeMax, "validate_max");
});
HasMany<QuestionnaireQuestion>(x => x.Questionnaires)
.Cascade.AllDeleteOrphan()
.WithKeyColumn("ida_question_id");
HasMany<Alternative>(x => x.Alternatives)
.IsInverse()
.WithKeyColumn("ida_question_id")
.AsBag().SetAttribute("cascade", "all");
}
}
QuestionnaireQuestion:
public class QuestionnaireQuestion : PersistentObjectWithTypedId<string>
{
protected QuestionnaireQuestion()
{
}
public virtual int QuestionOrder { get; set; }
public virtual Question Question {get;set;}
public virtual Questionnaire Questionnaire { get; set; }
}
public class QuestionnaireQuestionMap : ClassMap<QuestionnaireQuestion>
{
public QuestionnaireQuestionMap()
{
WithTable("ida_questionnaire_question");
SetAttribute("lazy", "false");
Id(x => x.ID, "ida_questionnaire_question_id")
.WithUnsavedValue(0)
.GeneratedBy.UuidHex("");
References(x => x.Question, "ida_question_id")
.WithForeignKey("ida_question_id")
.FetchType.Join();
References(x => x.Questionnaire, "ida_questionnaire_id")
.WithForeignKey("ida_questionnaire_id")
.FetchType.Join();
Map(x => x.QuestionOrder, "question_no");
}
}
Questionnaire:
public class Questionnaire : PersistentObjectWithTypedId<string>
{
#region Constructors
public Questionnaire()
{
Questions = new List<Question>();
}
public Questionnaire(string description) : this()
{
Check.Require(!string.IsNullOrEmpty(description) && description.Trim() != string.Empty);
Description = description;
}
#endregion
#region Properties
public virtual string Description { get; set; }
public virtual IList<Question> Questions { get; set; }
#endregion
}
public class QuestionnaireMap : ClassMap<Questionnaire>
{
public QuestionnaireMap(){
WithTable("ida_questionnaire");
SetAttribute("lazy", "false");
Id(x => x.ID, "ida_questionnaire_id")
.WithUnsavedValue(0)
.GeneratedBy.UuidHex("");
Map(x => x.Description);
HasMany<QuestionnaireQuestion>(x => x.Questions)
.Cascade.AllDeleteOrphan()
.WithKeyColumn("ida_questionnaire_id");
}
}
The result of running the SQL in the exception in the DB is 6 rows (the expected number) containing:
IDA4_2_: Guids
IDA1_2_: Guids
IDA1_5_1_: Guids
QUESTION2_5_1: Number (order
property)
IDA3_5_1_: Guids
IDA4_5_1: Guids
IDA1_3_0_: Guids
IDA2_3_0_: MOBILEPHONE (type
property)
DESCRIPT3_3_0_: mobiltelefon
(Description property)
VALIDATE4_3_0_: (RangeMin property)
VALIDATE5_3_0_: (RangeMax property)
The complete exception is:
[InvalidCastException: Cant use object type Questionnaires.Core.QuestionnaireQuestion as Questionnaires.Core.Question.]
NHibernate.Collection.Generic.PersistentGenericBag`1.ReadFrom(IDataReader reader, ICollectionPersister persister, ICollectionAliases descriptor, Object owner) +160
NHibernate.Loader.Loader.ReadCollectionElement(Object optionalOwner, Object optionalKey, ICollectionPersister persister, ICollectionAliases descriptor, IDataReader rs, ISessionImplementor session) +407
NHibernate.Loader.Loader.ReadCollectionElements(Object[] row, IDataReader resultSet, ISessionImplementor session) +412
NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) +472
NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +1010
NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +114
NHibernate.Loader.Loader.LoadCollection(ISessionImplementor session, Object id, IType type) +362
[GenericADOException: could not initialize a collection: [Questionnaires.Core.Questionnaire.Questions#CBDEDAFC183B4CD7AF1422423A91F589][SQL: SELECT questions0_.ida_questionnaire_id as ida4_2_, questions0_.ida_questionnaire_question_id as ida1_2_, questions0_.ida_questionnaire_question_id as ida1_5_1_, questions0_.question_no as question2_5_1_, questions0_.ida_question_id as ida3_5_1_, questions0_.ida_questionnaire_id as ida4_5_1_, question1_.ida_question_id as ida1_3_0_, question1_.ida_question_type_id as ida2_3_0_, question1_.description as descript3_3_0_, question1_.validate_max as validate4_3_0_, question1_.validate_min as validate5_3_0_ FROM ida_questionnaire_question questions0_ left outer join ida_question question1_ on questions0_.ida_question_id=question1_.ida_question_id WHERE questions0_.ida_questionnaire_id=?]]
NHibernate.Loader.Loader.LoadCollection(ISessionImplementor session, Object id, IType type) +528
NHibernate.Loader.Collection.CollectionLoader.Initialize(Object id, ISessionImplementor session) +74
NHibernate.Persister.Collection.AbstractCollectionPersister.Initialize(Object key, ISessionImplementor session) +59
NHibernate.Event.Default.DefaultInitializeCollectionEventListener.OnInitializeCollection(InitializeCollectionEvent event) +573
NHibernate.Impl.SessionImpl.InitializeCollection(IPersistentCollection collection, Boolean writing) +150
NHibernate.Collection.AbstractPersistentCollection.ForceInitialization() +287
NHibernate.Engine.StatefulPersistenceContext.InitializeNonLazyCollections() +213
NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +171
NHibernate.Loader.Loader.LoadEntity(ISessionImplementor session, Object id, IType identifierType, Object optionalObject, String optionalEntityName, Object optionalIdentifier, IEntityPersister persister) +493
NHibernate.Loader.Entity.AbstractEntityLoader.Load(ISessionImplementor session, Object id, Object optionalObject, Object optionalId) +82
NHibernate.Loader.Entity.AbstractEntityLoader.Load(Object id, Object optionalObject, ISessionImplementor session) +54
NHibernate.Persister.Entity.AbstractEntityPersister.Load(Object id, Object optionalObject, LockMode lockMode, ISessionImplementor session) +206
NHibernate.Event.Default.DefaultLoadEventListener.LoadFromDatasource(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) +133
NHibernate.Event.Default.DefaultLoadEventListener.DoLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) +948
NHibernate.Event.Default.DefaultLoadEventListener.Load(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) +436
NHibernate.Event.Default.DefaultLoadEventListener.ProxyOrLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) +236
NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent event, LoadType loadType) +1303
NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType loadType) +125
NHibernate.Impl.SessionImpl.Get(String entityName, Object id) +145
NHibernate.Impl.SessionImpl.Get(Type entityClass, Object id) +66
NHibernate.Impl.SessionImpl.Get(Object id) +91
SharpArch.Data.NHibernate.RepositoryWithTypedId`2.Get(IdT id) +152
Questionnaires.Controllers.QuestionnaireController.Create(String username, String id) in C:\Documents and Settings\berbor\Mine dokumenter\Visual Studio 2008\Projects\Questionnaires\Questionnaires.Controllers\QuestionnaireController.cs:40
lambda_method(ExecutionScope , ControllerBase , Object[] ) +205
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +178
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +24
System.Web.Mvc.<>c__DisplayClassa.b__7() +52
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +254
System.Web.Mvc.<>c__DisplayClassc.b__9() +19
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +192
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +350
System.Web.Mvc.Controller.ExecuteCore() +110
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +27
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7
System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) +119
System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) +41
System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) +7
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
As for the reason I'm doing this:
One Questionnaire may have many Questions, One Question may have many Questionnaire.
I want to be able to give Questions some properties dependent on context (which Questionnaire is in), one question may be required in one questionnaire but not another etc. It's more than just order, that was just an example trying to keep it simple.
The exception is when trying to load data into Questionnaire.IList<Question>. And it's still thrown after I modify my IList<Questionnaire> to IList<QuestionnaireQuestion> and the respective mappings.
The problem then would be that Questionnaire.Questions is mapped as containing QuestionnaireQuestion but is of type Question. But if I try to map it as containing QuestionnaireQuestion my SQL does no join at all and it still fails.
Is this what I should do, just that I'm doing it wrong?
In the example I read he does it like I did as far as I can see, only difference is the newer version of FluentNhibernate that now uses Generics. So I need to specify the correct type.
Then, you should not have a List of Questionnaires in your Question class, but a List of QuestionnaireQuestion objects.
Are you sure you receive an ADO.NET Exception ?
Can you execute the generated query against your database ?
I don't understand your situation however, what is this QuestionairreQuestion class ? You're not using it in your Question class ?
I understand that you want to have an order in which your questions should occur.
So, if you have extra properties , I think you should use the QuestionairreQuestion class in your Question class.
But, if you only have this QuestionairreQuestion class in order to enforce an 'order' (and no other attributes), then, you could maybe use another Collection-Type instead of an IList.
There are collections in NHibernate which allow you to have ordered-collections (a map , for instance). So, you could use this collection in your Question class to hold Questionairre objects.
(ps: nhibernate generates an outer join, because you didn't specify in your mapping that the collection should not be null. So, an outer join is used because in some circumstances, it could be possible that you have a Question without Questionaires, as far as nhibernate is concerned).