Unanswered WCF Data Service Query error

  • 2012年3月22日 14:28
     
     

    Hi,

    I would like to filter the properties I return from the WCF Data Service but I am getting the error below:

    Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>' to 'System.Collections.ObjectModel.Collection<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>'. An explicit conversion exists (are you missing a cast?) 

    This is the code I have used. Could someone please shed some light on how I can achieve this:

    LabellerDataServiceRef.DocketHubEntities ctx = new LabellerDataServiceRef.DocketHubEntities(new Uri(@"http://localhost:2332/LabellerDataService.svc", UriKind.RelativeOrAbsolute));

            public IEnumerable<SiteClient> GetSiteClient()
            {
                var companies = (from sc in ctx.SiteClients.Expand("SiteClientMailing")
                                 orderby sc.ClientName
                                 select new SiteClient
                                 {
                                     SiteClientID = sc.SiteClientID,
                                     ClientName = sc.ClientName,
                                     SiteClientMailings = (from m in sc.SiteClientMailings
                                                            orderby m.ClientName
                                                            select new SiteClientMailing
                                                            {
                                                                ClientName = m.ClientName,
                                                                PlannedMailingDate = m.PlannedMailingDate

                                                            })
                                 });

    Cheers

    C

すべての返信

  • 2012年3月22日 15:00
    モデレータ
     
     

    There are three problems with your query:

    1) WCF DS Client doesn't support orderby in the expansion. So the orderby you specified for the SiteClientMailings will not work.

    2) The error comes from the C# compiler which is complaining that your SiteClientMailings property is Collection<T> but you're assigning an IEnumerable<T> to it. I think just a simple cast might solve this problem.

    3) Since you prescribed the shape of the result using select statements, the usage of Expand() method is not needed and I think it will also cause failures.

    Thanks,


    Vitek Karas [MSFT]

  • 2012年3月22日 16:11
     
     

    Hi Vitek,

    Thanks for your help.

    2 - Could you please show me where and how to cast it?

    3 - I think the expand is causing problems as you mentioned but how can I get all the child SiteClientMailings if I do not use expand? Please also note that I am trying to limit the properties returned by the method.

    Cheers

    C

  • 2012年3月22日 18:22
    モデレータ
     
     

    2 - Just add (Collection<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>) in front of your inner query (from ...).

    3 - The fact that you have an inner query for the SiteClientMailings will tell the LINQ translator to expand it already.

    Thanks,


    Vitek Karas [MSFT]

  • 2012年3月22日 19:23
     
     

    Hi Vitek,

    Thanks again. I will try this tomorrow since I do not have the computer with me at the moment.

    I will let you know how I get on.

    I had an idea but I would like your suggestion to see if this is the right approach. Would that be better if I created a ?

    I have tried creating a custom model to encapsulate the EF model where I return only one properties of Department - ID but also return some properties of the related Employees that are in that departmet.

    However, I get an error to do with Data services not liking complex properties.

    Is it possible to achive what I need?

    [DataServiceKey(ID)]
    public class DepartmentModel
    {

      public int ID { get; set; }
      public IQueryable<EmployeeModel> Employees

    }

    [DataServiceKey(ID)]
    public class EmployeeModel
    {
      public int ID { get; set; }
      public string FirstName { get; set; }
    }

    public class DataModel
    {
      public DataModel()
      {
        using (var dbContext = new ODataDemoEntities())
        {
          Departments = from d in dbContext.Departments
                        select new DepartmentModel
                        {
                          ID = d.DepartmentID,
                          Employees = (from e in d.Employees
                                select new EmployeeModel
                                {
                                   ID = e.EmployeeID,
                                   FirstName = e.FirstName
                                }
                          )
                        };

      public IQueryable<EmployeeModel> Employees { get; private set; }
      public IQueryable<DepartmentModel> Departments { get; private set; }
    }

    Cheers

    C

  • 2012年3月22日 22:55
    モデレータ
     
     

    I don't see anything particularly wrong with the above. Could you please post the exception along with its callstack when you get a chance?

    Thanks,


    Vitek Karas [MSFT]

  • 2012年3月23日 10:58
     
     

    Hi Vitek,

    How are you?

    I have casted the inner query as you suggested but I get another error during run time:

    Error translating Linq expression to URI: Initializing instances of the entity type LabellerWebTest.LabellerDataServiceRef.SiteClient with the expression Convert(sc.SiteClientMailings.Select(m => new SiteClientMailing() {ClientName = m.ClientName, PlannedMailingDate = m.PlannedMailingDate})) is not supported.}

    I am posting below my Test Repository class that calls the WCF Data Service and the WCF Data Service. Could you spot anything could be causing this error?

    I did not realise it was so difficult to flat the objects and limit the number of properties returned by WCF Data Services :-)

    Cheers

    TestRepository

     public class TestRepository : ILabellerRepositoryDataService, IDisposable
     {
             LabellerDataServiceRef.DocketHubEntities ctx = new LabellerDataServiceRef.DocketHubEntities(new Uri(@"http://localhost:2332/LabellerDataService.svc", UriKind.RelativeOrAbsolute));

     
            public IEnumerable<LabellerDataServiceRef.SiteClient> GetSiteClient()
            {
                var companies = (from sc in ctx.SiteClients
                                 select new LabellerDataServiceRef.SiteClient
                                 {
                                     SiteClientID = sc.SiteClientID,
                                     ClientName = sc.ClientName,
                                     SiteClientMailings =
                                     (Collection<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>)(from m in sc.SiteClientMailings
                                                    select new LabellerDataServiceRef.SiteClientMailing
                                                    {
                                                        ClientName = m.ClientName,
                                                        PlannedMailingDate = m.PlannedMailingDate

                                                    })
                                 });

                return companies;
            }      

            public void Dispose()
            {
                throw new NotImplementedException();
            }
    }

    WCF Data Service

     [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
      public class LabellerDataService : DataService<DocketHubEntities>
      {
            public static void InitializeService(DataServiceConfiguration config)
            {
                 config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
                 config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
                 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;

                 config.UseVerboseErrors = true;

                 config.MaxBatchCount = 40;
               
            }
    }

  • 2012年3月23日 20:00
     
     

    Any help? Thanks

    C

  • 2012年4月25日 22:40
    モデレータ
     
      コードあり

    Hi Claudio,

     Change your code to be :

     var companies = (from sc inctx.SiteClients
                                 select new LabellerDataServiceRef.SiteClient
                                 {
                                     SiteClientID = sc.SiteClientID,
                                     ClientName = sc.ClientName,
                                     SiteClientMailings = new List<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>(
                                                   from m in sc.SiteClientMailings
                                                    select new LabellerDataServiceRef.SiteClientMailing
                                                    {
                                                        ClientName = m.ClientName,
                                                        PlannedMailingDate = m.PlannedMailingDate
                                                    })
                                 });
    


    Phani Raj Astoria http://blogs.msdn.com/PhaniRaj

  • 2012年4月26日 11:19
     
     

    Hi Phani Raj,

    Thanks for your reply and sample code. Unfortunately I get this error when I try  you code?

    Cannot implicitly convert type 'System.Collections.Generic.List<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>' to 'System.Collections.ObjectModel.Collection<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>'

    Do you have any ideas what I have to do to fix it?

    Cheers

    New Code Below
    --------------------

    LabellerDataServiceRef.DocketHubEntities ctx = new LabellerDataServiceRef.DocketHubEntities(new Uri(@"http://localhost:2332/LabellerDataService.svc", UriKind.RelativeOrAbsolute));

    public IEnumerable<LabellerDataServiceRef.SiteClient> GetSiteClient()
    {
                var companies = (from sc in ctx.SiteClients
                                 select new LabellerDataServiceRef.SiteClient
                                            {
                                                SiteClientID = sc.SiteClientID,
                                                ClientName = sc.ClientName,
                                                SiteClientMailings =
                                                    new List<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>(
                                                    from m in sc.SiteClientMailings
                                                    select new LabellerDataServiceRef.SiteClientMailing
                                                               {
                                                                   ClientName = m.ClientName,
                                                                   PlannedMailingDate = m.PlannedMailingDate
                                                               })
                                            });
                return companies;
    }

  • 2012年4月26日 15:49
    モデレータ
     
     

    Hi Claudio,

     I didn't know that the left hand side type was Collection<T>,

     try changing the property assignment to be : 

    SiteClientMailings =
                                                  new Collection<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>(  new List<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>(
                                                    from m in sc.SiteClientMailings
                                                    select new LabellerDataServiceRef.SiteClientMailing
                                                               {
                                                                   ClientName = m.ClientName,
                                                                   PlannedMailingDate = m.PlannedMailingDate
                                                               }) )

    This way, you use the constructor of Collection<T> which takes a List<T> instance.


    Phani Raj Astoria http://blogs.msdn.com/PhaniRaj

  • 2012年5月1日 8:21
     
     

    Hi Phani Raj,

    Sorry for the long time I took to anwser back but I have finally had time to have a look at it.

    I tried your new sample code and got this error message:

    "
    Initializing instances of the entity type LabellerWebTest.LabellerDataServiceRef.SiteClient with the expression new Collection`1(new List`1(sc.SiteClientMailings.Select(m => new SiteClientMailing() {ClientName = m.ClientName, PlannedMailingDate = m.PlannedMailingDate}))) is not supported.

    "

    Do you have any ideas why I am getting this message? Is there a way to fix it?

    Cheers

    This is the full code:

     LabellerDataServiceRef.DocketHubEntities ctx = new LabellerDataServiceRef.DocketHubEntities(new Uri(@"http://localhost:2332/LabellerDataService.svc", UriKind.RelativeOrAbsolute));

    public IEnumerable<LabellerDataServiceRef.SiteClient> GetSiteClient()
    {
              
                var companies = (from sc in ctx.SiteClients
                                 select new LabellerDataServiceRef.SiteClient
                                            {
                                                SiteClientID = sc.SiteClientID,
                                                ClientName = sc.ClientName,
                                                SiteClientMailings =  new Collection<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>
                                                    (new List<LabellerWebTest.LabellerDataServiceRef.SiteClientMailing>
                                                        (
                                                    
                                                    from m in sc.SiteClientMailings
                                                    select new LabellerDataServiceRef.SiteClientMailing
                                                               {
                                                                   ClientName = m.ClientName,
                                                                   PlannedMailingDate = m.PlannedMailingDate
                                                               }))
                                            });
                return companies;
    }