Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataServiceContext can't work with POCO's #1003

Closed
wizofaus opened this issue Nov 24, 2017 · 6 comments
Closed

DataServiceContext can't work with POCO's #1003

wizofaus opened this issue Nov 24, 2017 · 6 comments
Assignees
Labels
client only related to OData.Client feature P3

Comments

@wizofaus
Copy link

wizofaus commented Nov 24, 2017

Given the following

        class Product
        {
            public int ID { get; set; }
            public String Name { get; set; }
            public String Description { get; set; }
        }

        class MyContext : DataServiceContext
        {
            public MyContext() : base(new Uri("http://services.odata.org/V4/OData/OData.svc"))
            {
                Products = CreateQuery<Product>("Products");
            }
            public DataServiceQuery<Product> Products { get; set; }
       }

       var count = MyContext().Products.Count();  // this works, returns correct result
       var list = MyContext().Products.List(); // this fails, 'The complex type 'System.Object' has no settable properties.'

It would seem there should be enough information for the OData context to be able to parse the result and construct a list of Products with the expected property values read from the JSON.

At first I just got "'The complex type 'System.Object' has no settable properties.'", which makes no sense, as DataServiceQuery is templated and knows perfectly well what type it is for, but anyway I tried setting ResolveType to a delegate that could resolve the types, but nothing I tried worked - if it always returns typeof(Product) for both "Products" and "Product" (the two type names it gets called with), it results in a single empty Product with no properties set, and if it returns a collection type for "Products" that exposes a value indexer, I just get other errors about types not being assignable.

I understand normally you'd use DataServiceContext with an edmx file but I wish to avoid this - is the OData library not designed to be able to work with POCOs the way EntityFramework can, and if so, is there any reason why this wouldn't be a worthwhile feature to add?

@wizofaus
Copy link
Author

(As a workaround, it takes about 8 lines of code to do the HTTP fetch manually using the RequestUri exposed by the DataServiceQuery and deserialize using Json.net, so I'm OK with this now for now, but it does seem odd that it doesn't just work as is).

@wizofaus
Copy link
Author

wizofaus commented Nov 25, 2017

As part of this I was able to also fix the problem that the existing library can't handle collection.FirstOrDefault(<predicate>) (or .Count(<predicate>) etc.).
I was able to do this just by transforming the expression tree before creating the DataServiceQuery.
It's certainly not a bullet-proof solution at this point, but is there any reason the library doesn't natively support this?

@wizofaus
Copy link
Author

I've also managed now to implement

collections.Select(p => p.<member>)

Which required some real trickery as currently the OData library can only generate the right query if you use an anonymous type collections.Select(p => new { <member> = p.<member> }) and trying to build an expression tree for a type that doesn't exist is somewhat challenging (fortunately it doesn't actually have to exist, it just has to have the necessary properties for the tree to be parsed and transformed correctly). Again, seems odd the library doesn't natively support this, as it severely limits the usefulness of LINQ->OData.

@pmatrasc
Copy link

@wizofaus

While they work on the fix, would you please share some code snippets to better understand how you worked around the last two issues you listed?

Thanks!

@julealgon
Copy link

I'm also very interested in seeing your solution to the problem @wizofaus . I'd appreciate if you could share it here.

Right now I've resorted to the Simple.OData.Client library to interface with my OData service. As long as you have the $metadata endpoint properly exposed, it works fine with POCO classes.

@wizofaus
Copy link
Author

I'll have to dig out the code, it's being lying dormant for while, but sure, happy to share it.

@madansr7 madansr7 added the client only related to OData.Client label Jun 5, 2019
@madansr7 madansr7 added P3 feature and removed P4 labels Oct 7, 2019
ElizabethOkerio added a commit to ElizabethOkerio/odata.net that referenced this issue Feb 28, 2020
KanishManuja-MS pushed a commit to KanishManuja-MS/odata.net that referenced this issue Mar 24, 2020
OData#1614)

Added changes to DataServiceClientFormat to load edm model from network for certain cases
and updated tests and regression tests for failing test cases
 Closes OData#1003
KanishManuja-MS pushed a commit that referenced this issue Mar 24, 2020
#1614)

Added changes to DataServiceClientFormat to load edm model from network for certain cases
and updated tests and regression tests for failing test cases
 Closes #1003
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client only related to OData.Client feature P3
Projects
None yet
Development

No branches or pull requests

6 participants