OData / WCF Data Service not working with complex

2019-07-05 09:18发布

问题:

I'm brand new to OData and WCF data services so this might be an easy problem. I'm using VS Web Developer Express 2010 where I have a very simple WCF Data Service hosted in a console app. It's returning an IQuerable collection of a simple 'Study' class from a repository (located in a separated dll project), which in turn retrieves 'Study' classes from a db project in another dll (so 3 projects in the solution).

I also have an 'Experiment' class in the db project and there can be multiple Experiments in a Study. When I exclude the Experiment class from the Study everything works and I get data coming back. The problem happens when I add a List collection to the Study class, then I get a runtime error when I try to run the service. In Firebug the error is '500 Internal Server Error', and the message in the browser is 'Request Error. The server encountered an error processing the request. See server logs for more details.'

I have IIS 7 and I also just installed IIS 7.5 but again it's brand new to me, so I can't figure out where the service is hosted or where to view the server / web logs. There are only IIS 7 logs visible in 'C:\inetpub\logs\LogFiles\W3SVC1'. The VS web server (Cassini) doesn't start when I run the app, so this suggests it's being hosted in IIS 7.5 (?).

So
- how do I return child classes / complex objects?
- how do I know where my service is hosted and where can I find the server logs?

Here's the host app:

using MyStudyRepository;
using MyStudyDB;

namespace MyStudyService
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string serviceAddress = "http://localhost:998";
            Uri[] uriArray = { new Uri(serviceAddress) };
            Type serviceType = typeof(StudyDataService);

            using (var host = new DataServiceHost(serviceType,uriArray))
            {
                host.Open();
                Console.WriteLine("Press any key to stop service");
                Console.ReadKey();
            }
        }
    }

    public class StudyDataService : DataService<StudyRepository>
    {
        public static void InitializeService(IDataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        }
    }
}

Here's the repository:

using MyStudyDB;

namespace MyStudyRepository
{
    public class StudyRepository
    {
        List<Study> _List = new List<Study>();

        //Add constructor to populate myStudies list on creation of class
        public StudyRepository()
        {
            for (int i = 1; i < 5; i++)
            {
                Study myStudy = new Study() { ID = i, StudyOwnerId = i, StudyName = "Study" + i.ToString() /*, Experiments = null */ };
                _List.Add(myStudy);
            }
        }

        public IQueryable<Study> Studies
        {
            get
            {
                return _List.AsQueryable<Study>();
            }
        }
    }
}

And here's the DB:

namespace MyStudyDB
{
    public class Study
    {
        public int ID { get; set;}
        public int StudyOwnerId { get; set; }
        public string StudyName { get; set; }
        //public List<Experiment> Experiments { get; set; }
    }

    public class Experiment
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int StudyId { get; set; }
    }
}

回答1:

To debug the WCF Data Service please refer to this blog post: http://blogs.msdn.com/b/phaniraj/archive/2008/06/18/debugging-ado-net-data-services.aspx As to why the collection of Experiment doesn't work, there are two reasons:

  • The Experiment class is not recognized as an entity type because there's no entity set for it. (Entity set is the IQueryable property on your repository class, which you don't have). As a result the Experiment class is only recognized as a complex type.
  • The currently released version of WCF Data Services doesn't support MultiValues, MultiValue is effectively a collection of primitive or complex types.

So you have two way to "fix" this. Either make sure that Experiment is in fact an entity, by adding IQueryable property on your repository class. Or use the latest CTP (http://blogs.msdn.com/b/astoriateam/archive/2011/06/30/announcing-wcf-data-services-june-2011-ctp-for-net4-amp-sl4.aspx) which does support MultiValues.



回答2:

Thanks! And I guess it is missing the DataServiceKey attribute on the class as follows:

[DataServiceKey("ID")]
public class Study
{ 
    .....
}