S#harp architecture mapping many to many and ado.net data services: A single resource was expected for the result, but multiple resources were found

StackOverflow https://stackoverflow.com/questions/1848549

Question

I'm developing an application that reads data from a SQL server database (migrated from a legacy DB) with nHibernate and s#arp architecture through ADO.NET Data services. I'm trying to map a many-to-many relationship. I have a Error class:

public class Error
{
    public virtual int ERROR_ID { get; set; }
    public virtual string ERROR_CODE { get; set; }
    public virtual string DESCRIPTION { get; set; }

    public virtual IList<ErrorGroup> GROUPS { get; protected set; }
}

And then I have the error group class:

public class ErrorGroup
{
    public virtual int ERROR_GROUP_ID {get; set;}
    public virtual string ERROR_GROUP_NAME { get; set; }
    public virtual string DESCRIPTION { get; set; }

    public virtual IList<Error> ERRORS { get; protected set; }
}

And the overrides:

public class ErrorGroupOverride : IAutoMappingOverride<ErrorGroup>
{
    public void Override(AutoMapping<ErrorGroup> mapping)
    {
        mapping.Table("ERROR_GROUP");
        mapping.Id(x => x.ERROR_GROUP_ID, "ERROR_GROUP_ID");
        mapping.IgnoreProperty(x => x.Id);
        mapping.HasManyToMany<Error>(x => x.Error)
            .Table("ERROR_GROUP_LINK")
            .ParentKeyColumn("ERROR_GROUP_ID")
            .ChildKeyColumn("ERROR_ID").Inverse().AsBag();
    }
}

public class ErrorOverride : IAutoMappingOverride<Error>
{
    public void Override(AutoMapping<Error> mapping)
    {
        mapping.Table("ERROR");
        mapping.Id(x => x.ERROR_ID, "ERROR_ID");
        mapping.IgnoreProperty(x => x.Id);
        mapping.HasManyToMany<ErrorGroup>(x => x.GROUPS)
            .Table("ERROR_GROUP_LINK")
            .ParentKeyColumn("ERROR_ID")
            .ChildKeyColumn("ERROR_GROUP_ID").AsBag();
    }
}

When I view the Data service in the browser like: http://localhost:1905/DataService.svc/Errors it shows the list of errors with no problems, and using it like http://localhost:1905/DataService.svc/Errors(123) works too.

The Problem When I want to see the Errors in a group or the groups form an error, like: "http://localhost:1905/DataService.svc/Errors(123)?$expand=GROUPS" I get the XML Document, but the browser says:

The XML page cannot be displayed 
Cannot view XML input using XSL style sheet. Please correct the error and then click the Refresh button, or try again later. 
--------------------------------------------------------------------------------
Only one top level element is allowed in an XML document. Error processing resource 'http://localhost:1905/DataServic...
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
-^

I view the sourcecode, and I get the data. However it comes with an exception:

<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code></code>
  <message xml:lang="en-US">An error occurred while processing this request.</message>
  <innererror xmlns="xmlns">
    <message>A single resource was expected for the result, but multiple resources were found.</message>

    <type>System.InvalidOperationException</type>
    <stacktrace>   at System.Data.Services.Serializers.Serializer.WriteRequest(IEnumerator queryResults, Boolean hasMoved)&#xD;
   at System.Data.Services.ResponseBodyWriter.Write(Stream stream)</stacktrace>
  </innererror>
</error>

A I missing something??? Where does this error come from?

Was it helpful?

Solution 2

I think this was due to an error with linq and nHibernate, worked after I restricted the results to return just one.

OTHER TIPS

hrm... not familiar with this error but I wonder if it has something to do with lazy loading. Your current mapping would cause the child collection to be queried for when it is accessed which could be causing the serialization to freak out. Serializing the NHibernate proxied objects is a massive pain in the ass full of voodoo. Try changing your mapping like the example below and see if it allows you to continue.

public class ErrorOverride : IAutoMappingOverride<Error>
{
    public void Override(AutoMapping<Error> mapping)
    {
        mapping.Table("ERROR");
        mapping.Id(x => x.ERROR_ID, "ERROR_ID");
        mapping.IgnoreProperty(x => x.Id);
        mapping.HasManyToMany<ErrorGroup>(x => x.GROUPS)
            .Table("ERROR_GROUP_LINK")
            .ParentKeyColumn("ERROR_ID")
            .ChildKeyColumn("ERROR_GROUP_ID").Not.Lazy().AsBag();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top