Linq to Sql using a non-column attribute property in Association attribute - c#-4.0

I am trying to create an association between 2 linq to sql entities, say Entity A and Entity B.
A uses a non-column attribute property ( named BaseDocumentType ) and a column attribute in an Association for "ThisKey" and 2 column attributes for "OtherKey". The following is an example of my Association attribute definition...
[System.Data.Linq.Mapping.AssociationAttribute ( ... ThisKey = "BaseDocumentType, Column2" , OtherKey = "Column1,Column2" )]
When I run it I get the following error...
"Data member 'System.String BaseDocumentType' of type 'Library' is not part of the mapping for type 'A'. Is the member above the root of an inheritance hierarchy?"
How can I define the relationship using the non-column attribute property or how do I make this work?
Thanks.

The message is quite clear. LINQ to SQL translates statements to SQL and you tried to use a property that doesn't map to a column, so it can't be translated to SQL.
You'll have to retrieve the entities you want from the database then try to query them using LINQ to Objects, ie LINQ operations on the resulting lists or arrays. A better option is to rethink your design and find a way to retrieve only the data you need from the database and avoid processing the results on the client.
Linq to SQL in this case prevented you from doing something really dangerous. It could have retrieved all the data and process them using your non-column attribute but that would create an enormous performance hit. Some naive LINQ providers actually do just that. Imagine retrieving 1000 objects from the database only to find the two objects that match over this non-column attribute.

Related

Association without ReferenceVersionField

Is it possible to have a OneToManyAssociationField as entity extension on for example ProductManufacturer without the ReferenceVersionField in my related custom entity?
If this is not possible, is it possible for the reference version field to have a custom name (so not product_manufacturer_version_id) On first sight, this also does not seem possible.
About the error
I am currently getting the following error when trying to search for manufacturers using $criteria->addAssociation('myCustomEntity'):
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'product_manufacturer.myCustomEntity.product_manufacturer_version_id' in 'field list'
About the big picture
The use case is similar to the SeoUrl entity where there is a ‘foreign_key’ field which can have a relation to multiple entity types. My entity has not associations, but the other entities are extended to have an association to my entity. Just like the SeoUrl.
However, the DAL creates a query which uses the ‘product_manufacturer_version_id’ field, which does not exist on my custom entity…
Is it possible to have a OneToManyAssociationField as entity extension on for example ProductManufacturer without the ReferenceVersionField in my related custom entity?
No, you must set a ReferenceVersionField when adding associations to the definition of a versionized entity. This is too deeply rooted in the basic principles of the data abstraction layer to work around.
If this is not possible, is it possible for the reference version field to have a custom name (so not product_manufacturer_version_id) On first sight, this also does not seem possible.
You can change the storage name of the field. That is the name of the corresponding column within your database table. When you instantiate ReferenceVersionField you can use the second, optional argument to provide the storage name:
public function __construct(string $definition, ?string $storageName = null)
The storage name should be provided in snake case. The name of the object property for the field will then be derived from the storage name and converted to camel case. So given you provide my_version_custom_id for the storage name, the object property of the entity will be myVersionCustomId.
Your entity may have multiple associations to different entities, but if those entities are versionized your foreign key constraint has to be a combination of columns for both the foreign primary key as well as the foreign version id.

Is it possible in Pony ORM to add extra attributes to the intermediate table of a many-to-many relationship?

In Pony ORM, it is possible to ‘automatically’ create a many-to-many relationship. For example, from the documentation (for version 0.6, emphasis mine):
In order to create many-to-many relationship you need to define both
ends of the relationship as Set attributes:
class Product(db.Entity):
tags = Set("Tag")
class Tag(db.Entity):
products = Set(Product)
In order to implement this relationship in the database, Pony will
create an intermediate table. This is a well known solution which
allows you to have many-to-many relationships in relational databases.
Is it possible to create an extra attribute (column) in the automatically created intermediate table, so not just foreign keys to ‘Product’ and ‘Tag’, but, e.g., also a timestamp?
If yes, how?
If not, I guess I'll have to create the intermediate table explicitly. Can I in that case still use the nice Set-attribute definition (perhaps to the intermediate table, indicating the attribute of interest)?
Currently it is necessary to define explicit entity, like this:
class Product(db.Entity):
name = Required(str)
tags = Set("ProductTag")
class Tag(db.Entity):
name = Required(str, unique=True)
products = Set("ProductTag")
class ProductTag(db.Entity):
product = Required(Product)
tag = Required(Tag)
PrimaryKey(product, tag)
timestamp = Required(datetime, default=datetime.now)
Pony does not support virtual Set attributes like through in Django, but we plan to add them in the future. Right now you need to work with intermediate table explicitly.
Adding a tag to a product
p1 = Product[1]
tag1 = Tag.get(name='smartphones')
p1.tags.create(tag=tag1)
# or:
ProductTag(product=p1, tag=tag1)
Removing a tag from a product:
ProductTag[p1, tag1].delete()
Checking if a product has a specific tag:
ProductTag.get(product=p1, tag=tag1) is not None
Also, Pony support the concept of attribute lifting. That means that in Pony any collection attribute has all attributes of its items. The value of a such collection attribute is a collection of all values for individual items. For example, in order to get all tags for specific product, you can write:
p1.tags.tag
The p1.tags expression returns a collection of ProductTag items. Each ProductTag object has tag property which points to a specific tag object. So p1.tags.tag returns a collection of all Tag objects linked with a specific Product object.
It is possible to use attribute lifting inside queries. For example, in order to found all products with the tag smartphones you can write the following query:
select(p for p in Product if 'smartphones' in p.tags.tag.name)
Here, p.tags is a colection of ProductTag objects, p.tags.tag is a collection of Tag objects, and p.tags.tag.name is a collection of tag names. The query above is a syntactic sugar for the following query:
select(p for p in Product if 'smartphones' in select(item.tag.name for item in p.tags))
Also, the query can be rewritten as:
select(pt.product for pt in ProductTag if pt.tag.name == 'smartphones')

What is the use of the FROM in the Azure DocumentDB SQL-like query language?

I am using Azure DocumentDB. I only have one collection with heterogenous document types. I am using a type parameter to distinguish between different document types. I am making use of their SQL-like query language to get documents as follows:
SELECT * FROM Collection c WHERE c.ID = 123
I am getting my connection information, including the Endpoint URI, AuthKey, Database name and Collection name, from a configuration file. It seems like I can use any value for "Collection c" and it essentially just becomes an alias for the whole collection. So what is the point of the FROM section of my query?
I think you already got it :)
FROM allows you to set an alias to refer to the collection in other clauses. This may make more sense to you when you include multiple references (e.g. using a JOIN to form a cross-product with nested array elements).
For example:
SELECT food.description, tag.name
FROM food
JOIN tag IN food.tags
WHERE food.id = "09052"
In the query above, we are using referencing both the collection as well as nested array elements within a projection.
You can try this query out on the query demo website.

CMIS query language; Queryname cmis:document

I have some problems with CMIS query language. I want to get all documents (table no important), which have some property. So I wrote Select my_property from cmis:document.
Unfortunately I get answer: 0 documents. But when I alter query to Select my_property from my_table. I get different answer.
Could you tell me why?
The reason is that the spec does not provide for it. Here is what the spec says about the "relational view projection" (source):
In each Virtual Table, a Virtual Column is implicitly defined for each
property defined in the Object-Type Definition AND for all properties
defined on ANY ancestor-type of the Object-Type but NOT defined in the
Object-Type definition.
So a given object-type can be queried for properties of ancestor types, but the spec makes no provision for querying an object-type for properties of descendent types, which is what you are trying to do.
Jeff

ExecuteJoinedDataSet but with Where()

I did some searching and see that ExecuteJoinedDataSet will not work with the Where clause in 2.1. If I want to query a table with WHERE, but want the FK objects values to be bindable is the easiest way to just create a custom class(my table has tons of FK references).
Could you give us an example of what kind of query you are trying to write? If you are just trying to return a DataTable without creating a custom class just write your query and use the ExecuteReader which Returns an IDataReader. The IDataReader is bindable and if you need more you can just load it into a DataTable.

Resources