views:

891

answers:

3

Background

Currently I have a C# Silverlight business application which uses RIA Services. The application is hosted in ASP.NET using the ADO.NET Entity Framework and a domain service class to read and write to the SQL Server database.

Since the RIA class doesn't support multiple JOINs between tables, it was therefore necessary to implement LINQ as part of the domain service to JOIN all the tables together and return results.

Problem

I get the error message when I try and use a foreach loop on a returned list of objects:

Does not contain a public definition for GetEnumerator

What are my options for getting data out of this method?

Most of the time I only need one object, so I could just modify the method to select the first result and return a single object.

This method exists in the Domain Service Class. This method defines the context and then calls the method in the Silverlight client.

Method Invocation from Silverlight Client

var context = dds.DomainContext as InmZenDomainContext;
context.GetJobImagesQuery(imageJob.JobID.ToString())

Server Side Linq Query Method (Exists within Domain Service Class)

public List<Image> GetJobImages(string jobGuid)
        {
            var query =
                (
                 from j in Context.Job
                 orderby (j.ShortCode)
                 where j.JobID.Equals(jobGuid)
                 join a in Context.Audit //.Distinct()
                 on j.JobID equals a.Job.JobID
                 join i in Context.Image
                 on a.Image.JobID equals i.JobID
                 //join s in Context.States
                 //on z.States.StateID equals s.StateID
                 select new Image
                 {

                     //ShortCode = j.ShortCode,
                     HighResUrl = i.HighResUrl,
                     LowResUrl = i.LowResUrl,
                     UploadDate = i.UploadDate
                 }).ToList();

            return query;
        }


Invocation method

        var context = dds.DomainContext as InmZenDomainContext;
        foreach (var item in context.GetJobImagesQuery(imageJob.JobID.ToString()))
        {

        }

GetJobImagesQuery Declaration (Exists within the generated code file - .Web.g.cs):

        /// <summary>
        /// Returns an EntityQuery for query operation 'GetJobImages'.
        /// </summary>
        public EntityQuery<Image> GetJobImagesQuery(string jobGuid)
        {
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            parameters.Add("jobGuid", jobGuid);
            return base.CreateQuery<Image>("GetJobImages", parameters, false, true);
        }
A: 

Well what does your method return? It sounds like it's some kind of list which doesn't implement IEnumerable or IEnumerable<T> but we can't tell what it does support.

Jon Skeet
Hey Jon, i've added a code sample of the method.
Goober
+1  A: 

GetJobImagesQuery is a method that is generated because of the GetJobImages function. Your method is not supposed to return a List of Images but an IQueryable list of Entity Objects.

For example:

    public IQueryable<TableName> GetTableByID(long otherTable_ID)
    {
        return this.Context.TableName.Where((x) => x.otherTable_ID == otherTable_ID);
    }

would be generated into:

    public EntityQuery<TableName> GetTableNameByRx_IDQuery(long otherTable_ID)
    {
        Dictionary<string, object> parameters = new Dictionary<string, object>();
        parameters.Add("otherTable_ID", otherTable_ID);
        return base.CreateQuery<TableName>("GetTableNameByotherTable_ID", parameters, false, true);
    }

I think that if you change the return type of GetJobImages to an IQueryable of type "Image" you could grab the Images with a foreach.

public List<Image> GetJobImages(string jobGuid)

would become:

public IQueryable<Image> GetJobImages(string jobGuid)

then your code:

    foreach (var item in context.GetJobImagesQuery(imageJob.JobID.ToString()))

would work

thepaulpage
Sorry which method should I be changing the return type of and what should I change it to?
Goober
modified my answer. does that help?
thepaulpage
A: 

RIA Services, like all Silverlight communications, is asynchronous. You are also getting the pattern wrong. You can't do anything with context.getJobImagesQuery(imageJob.JobID.ToString()) directly. You have to use it in a Load operation. The Load is async and returns a LoadOperation object. If the plan is to bind to the returned entities then the pattern is usually to immediatly set the binding to LoadOperation.Entities. The return value used INotifyCollectionChanged so when the load completes the binding would also be updated automatically. In your case you want to do a foreach through the returned entities so the pattern in that case would look like this:

    context.Load(context.getJobImagesQuery(imageJob.JobID.ToString()), OnImagesLoaded, null);


private void OnImagesLoaded(LoadOperation lo)
{
  foreach (var item in lo.entities)
 {
 }
}

EDIT: What CTP are you on? I just realized that you are probably on a really old version of RIA Services for your code to make any sense at all. You should be using the July CTP.

Colin Blair