I am developing a simple application that has a Parent and Child model. The problem is that the parents are often updated through reading a text file, but the Children for each of the Parents are updated through the web-app. So how can I keep the Children attached to each of their Parents since each time I read the files I create new Parents?
Well, the most obvious thing would be to not re-create the parents every time you parse the file (is that possible?). Using first_or_create(link) that shouldn't be to painful...
Related
I am creating a basic CMS for a small academic project I want to use to practice design patterns in code later and I am starting with designing the database.
The simple requirement is that a "Container" of some kind will contain "Pages" or "Controls". Also a "Page" will contain "Controls". Think of a container like the holder for several tabbed pages. So when something is saved, everything can be saved at once by simply calling save on the container.
Anyway, I have 3 tables. "Container", "Page" and "Control".
Think of a "Container" like a holder for all the things that will appear on screen. It can be split into other smaller containers if needed (for wide screen).
Think of a "Page" like a form of some kind. Something that will allow the user to place controls used to collect data.
Think of a "Control" like a label, text box, button, etc. There are various types of controls (not shown in the diagram), but the "Controls" table will hold multiple instances of any given control type. For example, a form that has 5 labels and 5 text boxes, will have 10 corresponding entries in the controls table - 5 entries for each type of control. So a control is a singular instance of a control type, will have a unique ID, and can only be used once.
If a container is deleted, I want this to cascade and delete the relevant pages and controls.
Likewise, if a page is deleted, I want this to cascade and delete the controls that were on that page.
I have 2 problems to solve.
Problem 1: A control can belong to either a container or a page, but not both. Essentially a control can have only one owner or parent. Likewise with a page. However with a control, because it can be put on either a container, or a page, I have to connect it with 2 relationships, and create a constraint on the PageId and ControlId columns that ensures only one of them is not null. This I have done successfully, but I am wondering if there is a better way?
Problem 2: Because I am using cascade update and delete with 3 tables. I am getting an error:
Introducing FOREIGN KEY constraint 'FK_Pages_Containers' on table
'Pages' may cause cycles or multiple cascade paths. Specify ON DELETE
NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY
constraints.
I want the controls belonging to a page or container, AND the pages belonging to a container deleted if either the page or container is deleted. So, in my mind, I need the cascading update and delete. So this error is forcing me to change my relationship requirements in a way that will leave orphans.
As a side note, a container could also contain other containers. This might be useful on large wide screens to display a form (page) in two parts, one on the left and one on the right for example, and still be able to save everything by clicking a save button on the parent.
So how can I overcome this? Am I overlooking something in my design?
For clarity here is an ER diagram:
You can see from the stars (*) that it is not saved yet because of the above error. My first goal is to get the database right. I don't like entity framework code first, and I want to use either entity framework database first or an alternative ORM that does it's thing as needed. But I want data integrity handled by the database where it should be.
Any suggestions would be welcome.
Based on the comments under the question. I tried a few solutions. Here is one that I came up with that seems to work best so far. I am just posting this for my own reference later, and maybe it will help others. So I still welcome any other suggestions for improvement.
To start I removed all the relationships and created a container type table. This I linked to a container manager table. Then I lined the container and pages table with a 1:1 relationship to the container management table. The logic behind this was that I currently have 2 types of containers, but later I could add more if I wanted.
In the container types I added data for "Container" and "Page" then referenced this back to the container manager table. I added an additional field in the container manager table to show who the parent of the container or page was. This is a self referencing relationship. It simplified the container and pages table somewhat.
Next I repeated the process with the controls table. It was slightly more complicated but the same idea. It just split containers from controls very nicely and then let the management tables link up to "manage" things.
From there it was simply a matter of adding a container parent to the control manager table and relating it back to the container manager table. All the relationships are cascading and work without problems. As you can see, the management tables, combined with the 1:1 relationships to controls, containers, and pages tables, provide instance specific information allowing for easy management. I really like that I don't have to build any constraints like I had in my original solution to ensure only one of 2 fields were filled in as constraints are not obvious. However, I have noticed that I could technically just combine the data from the linked 1:1 tables directly into the management tables and simplify the diagram even more. Which I may yet do as it is easier and faster to look at 2 tables, than 5. I would be interested to hear peoples opinion of this.
The general use case would be that we know the types of containers or controls in advance. So we can select the type of controls we want to put on a page or container. This information adds data to the management tables and generates a unique Id for the instance of the container, page, or control being used. Then we use that Id to create the actual container, page, or control instance the user will see. Obviously saving the data behind the controls is another matter that is not part of the question so I wont go into my solution for that here.
Thanks to D Mayuri who inspired this approach with is help and comments about separating out the relationships. I am not sure if this is how he intended me to do it. If he posts his own answer, I will of course accept and give him credit.
I am working on VB.NET project using Entity Framework 4.
When I create new entity and add it to context.EntityCollection, without calling context.SaveChanges I cannot found newly added entity in that collection.
I need to check for duplicate records before saving to database and it appears that only working solution is to store entities in some dictionary outside of whole EF-generated stuff for checking duplicate records.
Is there any better solution?
Checking database directly before saving changes is possible solution.
I've read a lot of complaints about the treepanel, now I'm having some trouble with it.
The first is that paging in the treegrid isn't working correctly. I found a solution in another post that doesn't work, so I'm trying to fix it for everybody.
The second is where I need help. The first time a parent node is expanded, it make a call to the server and displays the children correctly. When I collapse and then expand it again, however, it will paint the same child twice. The tree crashes, showing this error:
Uncaught TypeError: Cannot read property 'internalId' of undefined
After working on it, I discovered that the problem is not when it inserts it again, but in the beforeitemexpand function. It appends the same child twice, causing the js and the treestore to contain 2 nodes with the same internalId, which in turn causes the crash.
Any ideas?
The way tree store works is a bit complicated. I suspect the issues you are having are related to the idProperty of the models your tree store is storing.
I ran into these issues as well. I found out you can not have two records with the same identity in mutliple places in the tree. For example if your tree was representing a file system and you copied the same file into two directories. If your file had an idProperty (set to id by default) the store puts your file model into a hash keyed off the id, regardless of it's path in the tree.
The suggested solution was to either not have the id set at all (not a very good solution for an editable tree grid), or to set a compound key that takes into account the entire chain of nodes up to the root to grantee uniqueness in the tree.
Once you get passed these issues the tree works fairly well. Oh, and paging the tree ... don't think that will happen any time soon, already asked.
I have a very simple situation but I can't seem to get my head around; I have a table promotions which has many sites. The site can be used with different promotions and in my (postgres) database I've 3 tables; promotions, sites and promotions_sites.
In my web application a user can edit the promotion and add a collection of sites (new line seperated). So in a save the collection of sites is saved at the promotion. This works. Still there are 2 problems;
1) old site records are not removed (when one is delete from the lines of sites)
2) when a current site is saved all original sites are re-created
My question is at which level I should manage the sites;
1) application level; just deleting all sites before re-inserting
2) data level; is there a nhibernate configuration to do this?
3) database level; create triggers/cascade deletes on the site table based upon the absence of an item in promotions_sites
At first the automatical orphan deletes. Sites can't be deleted automatically when your relation is defined as many-to-many. But if your promotions_sites table is mapped as separate entity and you have two one-to-many relations in sites and promotions, you can achieve automatic deletes by setting cascade on those relations to all-delete-orphan.
Second thing - where to manage the collection. You should let NHibernate to do this. Assuming you have proper mappings, you should not care about it on application level or especially at database trigger level. Anyway, the logic of handling collections in NHibernate is somehow different that you may be familiar with from database level. Generally you need to load parent object with the existing child collection, modify the collection and commit back the changes to the database. You should not replace the whole collection.
But it will be easier to talk when you show your mappings and code used to save changes.
I have an app, using Core Data with a SQLite store.
At some point I'd like to remove all objects for a few entities. There may be close to a thousand objects.
From what I can tell via google and the official docs, the only way to delete objects is to [managedObjectContext deleteObject:(Entity *)] for every object. But this means that I must first fetch all objects.
The data store is just sqlite, is there no way to simply pass a TRUNCATE TABLE ZENTITY; to it?
If you relate your objects to a parent entity simply delete the parent. If your parents delete rule is set to 'cascade' all of those (1k) children will be removed as well.
John
The issue is that CoreData isn't just a SQLite wrapper. It's an object graph management solution and it stores cached versions of your object in memory in addition to other stuff. As far as I know to remove all instances of a given managed object you'll have to fetch them and then delete each. This isn't to say that this functionality shouldn't exist, because it probably should.
Have you actually tried it and found it to be a performance issue? If so, then you could provide some information showing that, and more importantly file a bug report on it. If not, then why are you bothering to ask?
It's not as simple as doing a TRUNCATE TABLE ZENTITY; since Core Data must also apply the delete rule for each object (among other actions), which means doing a fetch. So they may as well let you make the fetch and then pass the results into the context one-by-one.