Does Entity Framework 4 support Many-to-Many queries? - entity-framework-4

I have the exact same problem as described in this post (event content / tags objects):
LINQ to entities - Building where clauses to test collections within a many to many relationship
I am getting the Exception:
Unable to create a constant value of type 'XXX.Tag'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
Is this problem resolved in E.F. 4?

this should work fine in EF4.0
from tag in db.Tags
where tag.Name.Contains("mytag")
from content in tag.Contents
select content

Related

Generic itab in JOIN in SELECT?

I have a generic table in global area and i want to use it in SELECT from. Is this possible or is there a way do this ?
Example Code:
FIELD-SYMBOLS: <gt_data> TYPE STANDARD TABLE.
CLASS-DATA: mo_data TYPE REF TO data.
CREATE DATA mo_data LIKE lt_data.
ASSIGN mo_data->* TO <gt_data>.
<gt_data> = lt_data.
SELECT data~matnr,
mbew~malzeme_deger
FROM zmm_ddl_mbew AS mbew
INNER JOIN #<gt_data> AS data ON data~matnr EQ mbew~matnr
INTO TABLE #DATA(lt_mbew).
If the Generic table you are asking about is an internal Table which the code snippet suggests, then
No i dont think you cant build a join to work on 2 different sources.
Unless there are some new kernel developments, the select statements are converted to DB SQL statements.
ABAP 7.5 documentation of Select statement refers to the from "data_source" as dbtab,View or cds_entity as possible sources.
Even if it was possible there are still other generic options that may make more sense. If the source internal data is small enough, then you can build a generic where clause to solve the problem.
Select from DBTAB where (string_cond).
If the size of the internal table is so large that you end up with half the data in memory and half on a DB, there may be a better generic solution anyway.
No, it is not possible. From the SELECT datasource help:
If the FROM clause is specified statically, the internal table cannot be a generically typed formal parameter or a generically typed field symbol. Objects like this can only be specified in a dynamic FROM clause and must represent a matching internal table at runtime
The above rule remains valid whether itab joined with dbtab or not.

How do you query an OData Collection of Enumerations?

I have been searching for the definitive answer on this but can't seem to find it anywhere. What I do know is that it's legal to create a Collection of the OData 4.0 Enumeration type. I also know that the Olingo parser that we are using (4.2) allows us to query both an Enumeration or Collection of Enumeration using the 'has' keyword. What I can't find, however, is any documentation that proves that this is actually a legitimate query. I also know that using OLingo and Microsoft parsers, that the any/all syntax that would generally be used for a Collection does not seem to work. I would really appreciate any help figuring this out.
The OData version 4 spec says this about logical operators: "Operands of collection, entity, and complex types are not supported in logical operators." has is one of the logical operators. Therefore, has is not supported on a collection of enumeration type. Furthermore, has is defined to operate on a single enumeration value, so it is not appropriate for querying a collection of enumeration values.
The spec also says that the lambda operators operate on "a navigation path that identifies a collection". If navigation path means a path that ends with a navigation property, then any/all can only be applied to a collection identified by a navigation property. Since collections of enumeration type are represented by structural properties, it follows that any/all cannot be applied to collections of enumeration type. But this is conjecture, since the term navigation path is not defined in the spec.
In lieu of a collection of enumeration type, consider using an enumeration type that has the IsFlags attribute set. You can definitely query such an enumeration using the has operator.

How object tracking works in F# SQL Type Provider

I was trying to figure out how the DataContext.ObjectTrackingEnabled property works in F# SQL Type Provider. Unfortunatelly I don't find any useful documentation except this msdn entry which is unhelpful too.
Shouldn't the object tracking feature, track all the objects loaded inside the same "session/context"? Let's say I query for an object, it gets loaded to the "context" and if I query for the same object once again in the same "context" it should load it from the context without executing SQL statement in RDBMs?
This code results in two SQL queries. I was expected to see only one in SQL Server Profiler:
[<Literal>]
let connectionString = #"server=localhost;database=..."
type dbSchema = SqlDataConnection<ConnectionString=connectionString>
let db = dbSchema.GetDataContext(connectionString)
let result = (query
{
for t in db.Table1 do
where (t.Id = 1)
select t
}).SingleOrDefault()
let result2 = (query
{
for t in db.Table1 do
where (t.Id = 1)
select t
}).SingleOrDefault()
What do I miss?
This is really a property of the LINQ to SQL framework, so it shouldn't be specific to F# (and so finding more about object tracking in LINQ to SQL should answer the question).
I'm not really a LINQ to SQL expert, but my understanding of this feature is that having ObjectTrackingEnabled = true does not avoid running multiple queries to retrieve the data. What it does is that it ensures that the queries return the same .NET objects representing the entities.
This means that if you have two queries that return the same entitiy and you modify a property of one of the entity (before you commit the change to the database), this will also change the property of the entity returned by the other query (because they're the same object).
In contrast, if you disable this and run two queries, they both return new .NET objects with values exactly as in the database. If your program modifies one of the objects, it will not affect the other (and so if you try to commit changes to the DB using both entities, you'll get a conflict).
In summary - disabling this gives you better performance if you're just reading data (because there is less tracking overhead), but it might be inappropriate if you want to edit the objects in your application and save data back to the database.
As Tomas said this is not directly related to the Type Provider but to the underlying LINQ to SQL implementation. But many F# developers use those providers, so a little history on Linq to SQL would be useful.
In general ObjectTrackingEnabled = true avoid running multiple queries to retrieve the data under the following conditions :
In general, for a LINQ to SQL query to return an object from the
identity cache, the query must be based on the primary key of an
object and must return a single object.
so in where(predicate) predicate must be an expression in which the object's primary key property is set to a constant value. If an object has a primary key defined by more than one property, each primary key property must be set to a constant value. The following are examples of the form predicate must take:
c => c.PK1 == constant_value1 && c=> c.PK2 == constant_value2
This information is taken from MSDN

Dynamics CRM OData query filtering on expanded attributes only works if no results come out?

I have a requirement to fetch Price List Item records which adhere to the following requirements:
Filter by a specific PriceList
Filter by a specific currency
Filter by the Name of the related Product containing a given string
I got the first two points working no problem, but it feels like expanding doesn't cope well with filtering. I started from a "straight" query on Product entity:
.../ProductSet?$filter=substringof('sometext', Name)
Equivalent SQL (targeting the corresponding CRM filtered views for clarity):
SELECT * FROM FilteredProduct WHERE ProductNumber LIKE '%sometext%'
The above query works, I can tweak it and have no issues. However, if I attempt to move on to ProductPriceLevel (thus expanding the relationship with Product, which is product_price_levels) I end up with this:
.../ProductPriceLevelSet?$expand=product_price_levels&$filter=substringof('sometext', product_price_levels/Name)
Equivalent SQL (again, targeting the relevant filtered views):
SELECT * FROM FilteredProductPriceLevel PPL JOIN FilteredProduct P
ON PPL.ProductId = P.ProductId WHERE P.ProductNumber LIKE '%sometext%'
Which has two different outcomes I see:
If the $filter has no matches, it works fine and returns an empty result set
If the $filter matches something, I get an error
code: -2147220970
message: The result selector of the 'Join' operation must return an anonymous type of two properties.
AFAIK that's what happens when you hit a limitation of LINQ-to-CRM regarding using .Where() on multiple entities at once... doesn't seem relevant!
What's wrong with my query ?
NOTE: The CRM 2013 I'm using is On-Premise, without any update rollup / service pack.
ALSO NOTE: The equivalent SQL, as can be expected, works perfectly
I don't think CRM OData supports adding a filter on a joined entity. Try reversing the entity you're actually starting with, and add a path to the referencing entity:
ProductSet()?$filter=substringof('sometext',ProductNumber)&$expand=product_price_levels&$select=product_price_levels/*
P.S. If you have linqPad, this is the query I used to generate this:
from p in ProductSet
where p.ProductNumber.Contains("sometext")
select new { p.product_price_levels }

Can an OData query specify a filter that references a nested entity?

Here is the setup: I've got a "Student" who has a related entity "Course" (1 to many). Each "Course" has a related entity "Period" that contains all of the time and date details of the course. I want to get back all of the students who have had a course in 2011.
I've tried this:
~/Student()?$expand=Course/Period&$filter=Course/Period/Year eq 2011
but it results in an error: No property 'Period' exists in type 'System.Data.Objects.DataClasses.EntityCollection`1[[Course]]
Clearly, Period is being treated as a property rather than an Entity, but I'm confused, because the following query does return the results I expect, and it uses almost the same syntax:
~/Student()?$expand=Course/Period&$select=Course/Period/Year
So am I doing something wrong with the $filter syntax, or is this not possible?
TIA for any insight.
The filter would work if the navigation property would be a singleton, but since it's a collection (1 to many) the filter won't work. Mainly because it's unclear what would that mean. Do you want students which have all their courses in 2011 or just some... and so on.
In 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) There's a support for any and all operators which should allow you to do what you want. For more details see this blog post: http://www.odata.org/blog/even-more-any-and-all.
Yes it should be possible. You need to use something like this.
~/Student()?$expand=Course/Period&$filter=Course/any(d:d/Period/Year eq 2011)
Course/any() looks to see if anything in the collection matches the expression in ().
d: specifies an iterator for the collection which is then referenced in the d/Period/Year.
Reference can be found in OData Documentation In Section 5.1.1.10.1 (Search for "/any").
Note: You can also do /all to ensure that all courses match some criteria.

Resources