Why does Titan have this limitation? - titan

It says here:
The definition of an edge label, property key, or vertex label cannot
be changed once its committed into the graph.
In contrast SQL Server, which is what I'd normally use, doesn't have a problem with, say, changing the type of a field or the cardinality of a relationship.
This isn't even in the Temporary Limitations section of that web page.
Why is this limitation here and what am I supposed to do when I make a mistake when defining a type? Delete the whole database and import all the data into a new one?

Related

#RawQuery and Generated RxRoom.createFlowable(db, tables)

I'm using RxJava2 and Android's Room framework (v2.1.0). Ultimately, I'm using the Flowable from a #RawQuery-annotated abstract method in my #Dao class. When I updated a row/column of one of the referenced tables (using an #Update method in my #Dao on the root entity), I was expecting the Flowable to re-trigger when any of the referenced tables in the #RawQuery were touched. However, that didn't seem to be the case.
After digging into the generated code for my #Dao class, I noticed that the Room return value is wrapped in a call to RxRoom::createFlowable. I noticed that the tableNames argument only contained a subset of the expected tables names, so it made more sense why my Flowable was not re-triggering since I had updated one of the tables outside of the specified subset.
Upon further reflection, it made more sense why the code generator for Room couldn't derive the full set of table names, since all the table names were only available at runtime. (I wish the RxRoom documentation made it more plainly obvious that observing a #RawQuery would be flaky w/o using the observedEntities annotation argument!)
However, it's still a mystery to me how that subset of table names was even generated. While I probably could dive into the code base, it'd be great if someone knowledgeable could summarize how RxRoom derives the table names from a #RawQuery. My guess is that RxRoom is using the "leaf" joined tables of the root entity being queried, but I don't really understand why that's a reasonable default. IMHO, a safer default would be to NOT observe any referenced tables in a #RawQuery unless observedEntities is specified.

How to avoid duplicate records with user edits in a referential system?

PostgreSQL 10.1
I am curious to see how the SO Community deals with this common database problem.
The problem is this. I have textual descriptions of various problems being entered at the desktop into the table ICD_Descriptions (the middle box below). Generally speaking there will also be one code associated with each description. However, over time (i.e., years), the codes for a specific text phrase/description will change. Hence, a general many-to-many relationship will exist for some codes to descriptions. So a third table, dx_log, is being used to allow for a many-to-many relationship between the code and the descriptions. Lastly, other "children" tables that need to see a specific combination of 'code-description' will be given a reference to the primary key (the recid) of the dx_log. I believe this arrangement to be fairly standard database management.
O.K., now for the problem. I wish the codes in the icd_code table to be unique to that table. I also wish the descriptions in the icd_description table to be unique to their table.
The problem. This being a referential system, changes to either the "data" part of the code table, (the code), or the description (in the descriptions table) will be seen in the child tables.
But, how to correctly manage user edits to a code or description that would conflict with the "unique" rule of the respective table?
As an example, lets say the initial text of a description is "this is mispelled", whereas another description text has "this is misspelled". At one point it time, both phrases coexist and are unique. However, at a later point in time, the wrong record is corrected (i.e., mispelled --->misspelled). When the edits are attempted to be saved to the file, it will be detected that the correct record already exists.
So if the dx_log table is also unique on (icd_description_recid, icd_code_recid), then simply replacing the reference to the already existing correctly spelled record in the dx_log will lead to a violation of uniqueness for the dx_log table. Therefore, I can think of only three solutions:
The table which the children tables actually reference CAN NOT HAVE A UNIQUES constraint on its reference pointers,
Leave the uniqueness constraint on the dx_log, but when a conflict would violate uniqueness, then use a migrate procedure to move the child table references to the existing record (in postgresql this would be heavy use of the catalogs) to the "new record", then delete the existing record before adding the new record.
Add an additional self-reference pointer in the dx_log such that when a record would conflict with an already existing record in dx_log, then don't change it but rather place a pointer to the already existing "correct" record in the dx_log.
I hope I've explained my question well enough. What is the recommended approach?
Thanks for any comments.
I would say the 2. is the correct solution.
Yes, that requires that all dependent records in dx_log have to be updated when two entries are consolidated, but you have an index on dx_log(icd_description_recid) anyway, right?
The other solutions compromise data consistency and will make all queries on the system more complicated and probably slower.
Separate the idea of a natural unique constraint from the idea of a key. Use a system generated surrogate key for referential integrity, and a UNIQUE INDEX for the natural key. Then you don't have to reparent anything.

Do classes necessarily have to exist prior to record insertion?

I'm coming from Neo4j and evaluating OrientDB, and I had a quick question about classes - do they have to exist prior to inserting a record? That is, in Neo4j there's the 'MERGE' command, which will update or create a node if it doesn't exist. Classes seem roughly equivalent to Neo4j's labels, and if a label doesn't exist when performing a MERGE, it will be created. Is there similar functionality in OrientDB? Currently when I try to insert a record whose class doesn't exist, OrientDB throws an exception, "Class SOME_CLASS not found in database".
I've been reading through the docs trying to get a handle on the various data models available, but I can't find anything explicit on this issue. One thing I tried was to add a cluster, and then insert a record with a class that does not exist. This worked, and in OrientDB Studio, under 'DB', I see the cluster with number of records equal to '1'; however, the class of that new record does not appear under 'Schema'.
If dynamic class creation of this sort isn't possible, is it acceptable to check if a class exists in the schema, and if not, create it, and then proceed with creating the record? A different question is, if it's acceptable, is it good to do this, or should I always define the schema manually?
If you use one of the CREATE commands, then the object is placed in a default class; for example:
CREATE VERTEX
Created vertex 'V#9:0 v1' in 0.047000 sec(s).
(In this case, the class is V.)
And of course if you use the INSERT INTO ... form, then you have to specify a class.
So perhaps your first question boils down to whether it is possible to change the class of an OrientDB vertex or edge.
It is possible to change the parent class of a vertex -- see
http://orientdb.com/docs/2.1/SQL-Move-Vertex.html -- but there are important caveats.
To test whether a class exists programmatically, see e.g. this SO entry:
Check if class exists or not in orientdb
This gives a Java example, but a similar approach is possible using other supported languages.
As to the wisdom of changing the class of an entity dynamically -- perhaps the safe answer is that if you can achieve whatever you want using a property label, then use labels.

Passing a session variable to the table update stored procedure in Entity Framework

How do I pass a session variable to the Insert, Update, Delete stored procedures mapped to a Table in an Entity Framework, and how do I get the mapping in the EDMX diagram to work with it?
I have a database with Stored Procedures (SPs) defined for Inserting, Updating, and Deleting rows. The SPs expect a userid parameter to be passed to them for audit trail purposes, this parameter does not exist as a column in the table.
When I'm in the EDMX diagram specifying the mapping for the Parameter I don't see any way to either a) ignore the parameter or b) (preferred) set the value to a Session value. I've created a partial class mapping of the Stored Procedures, however the model doesn't seem to see it or even acknowledge that it is there. The whole premise behind using this technology is to let it do the work. I can't even tell it to ignore this parameter as it is optional and has a value assigned to it. I can't even edit the SP definition as the file is marked autogenerated, and will lose any modifications when it is regenerated.
Entity Framework seems like a well thought out approach, and I've looked at several tutorials and books on the subject. However, this seems like a really obvious thing to do. I've looked through stack overflow and the MSDN forums and found similar questions from years ago, but no one ever seems to answer the question, they just dance around the issue.

Entity Framework: Ignore Columns

I have a database that I wish to build an EF model from, however I do not want to include certain columns from the database as the columns concerned are maintained exclusively on the server and should not be manipulated by any application.
Both of the columns are DateTime (if this makes any difference), one of the columns is nullable and is maintained by a trigger on updates and the other is not nullable and set using a default value in the table definition.
I guess I am looking for something like the "Server Generated" option in Linq2Sql; but I cannot find such an option.
Can anybody tell me how to work around this?
Caveat:
I have been trying to introduce business object modelling at my place of work for some years and it has always been rejected because of the amount of additional code that has to be hand-cranked. EF is currently being seen as a viable solution because of the designer and code generation therefore any option that involves hand-cranking the XML will only turn the rest of my colleagues away from EF. I am therefore looking for something that can be done either using the designer or using code.
EDIT:
I guess that what I am looking for here is either...
(a) a way to create the model without EF referencing the columns in the store (ssdl) and therefore not looking to manipulate it in any way
(b) a way to programatically set the "StoreGeneratedPattern" attribute against the property when I create the ObjectContext (the easy answer is to manually manipulate this in the .ssdl, but this would then be overwritten if I refreshed the model from the database and I cannot go down the route where the .csdl, .msl & .ssdl are hand-cranked).
Can you do this with the Entity Framework? Yes; it's easy. Can you do this with the Entity Framework designer? Unfortunately, that is much harder.
The problem you're having is that the column exists in the storage schema (SSDL) in your EDMX. Removing the column with the GUI designer simply removes it from the client schema, not the mapping or the storage schema. However, it's simple enough to go into the EDMX and remove it. Having done that, you can also remove it from the mapping in the client schema portions of the EDMX, and the entity framework will longer complain that it is unmapped.
Problem solved, right?
Well, no. When you use the GUI designer to update the EDMX from the database, the storage schema is thrown away and re-generated. So your column will come back. As far as I know, there is no way to tell the GUI designer to never map a particular column. So you will have to re-do this every time you update with the GUI designer. Fortunately, the EDMX is XML, so you can do this with a XML transform, LINQ, or the XML tool of your choice.
Can you not create a view with the columns you need and import it through entity function wizard and map it to your entities?
You could modify the text template to ignore these columns when generating your entity classes. For example if you added "IGNORE" to the documentation summary, you could modify the template to ignore them by replacing;
Dim simpleProperties as IEnumerable(Of EdmProperty) = typeMapper.GetSimpleProperties(entity)
with;
Dim simpleProperties as IEnumerable(Of EdmProperty) = typeMapper.GetSimpleProperties(entity).Where(Function(p) p.Documentation is nothing orelse p.Documentation.Summary.IndexOf("IGNORE")<0)
Right click on the field in the graphical representation and choose delete. Ive found that sometimes you will get errors when you make a lot of changes to the modeling at once and start to lose track of your changes. Your best bet might be to rebuild the EF generated model.
Keep in mind that when you "update from the database", that old fields on the generated models will not be removed, you will have to remove them manually. For example if you renamed DateField1 to DateField2 in your database, and then you "Update Model from Database", you will now see both DateField1 and DateField2 on the resultant model. This can be a cause of errors.
Do you not want the column to appear in the model at all?
Try selecting the column in the Designer view and hitting the delete key.
Edit
You could make the setter for the property private. Then your app won't be able to modify the value.
Timestamp is a different data type than DateTime. Timestamp seems to be recognized as an attribute the engine manages, much like an identity attribute. You can't "update" a timestamp attribute. Hence, the EDM can manage it correctly (just as it does an identity).
In EDMX designer, select the property and set StoreGeneratedPattern to Computed.