How to insert data in multiple tables if tables have relationship OneToMany, and #Column(unique = true) - sql

I have two tables MAKES and MODELS. Between them relationship #ManyToOne.
Table MAKES:
#Column(unique = true)
private String make;
Table MODELS:
#Column(unique = true)
private String model;
When I insert schema car:
makes.setMake("Porsche");
models.setModel("911");
em.persist(makes);
em.persist(models);
Data is added, but if Porsche exist in MAKES table an exception is returned: ... Duplicate entry 'Porsche' for key ....

This constraint violation error is supposed to happen to prevent you from accidentally doing what you are doing here - inserting two separate Make instances that both have the Make column value of "Porsche". If you need to have multiple Makes with the value "Porsche", you need to relax the constraint to allow duplicates.
What seems more likely is this is intended, and you have an existing Make that you want to associate to or under a new Model. Read in the existing make from the DB and use that managed instance within your EntityManager context instead of trying to persist a new Make instance.
Ie
Query q = em.createQuery("select m from Make m where m.make = 'Porsche'");
Make Porsche = q.getSingleResult();
models.setModel("911");
models.setMake(Porsche);
em.persist(models);

you must save two table in two Transaction if you want one Transaction before sava Make table must check unique row after that save it. when in one Transaction create one exception the Transaction reverse.

Related

Error Deleting a child object from its parent

I'm using vb.net 2013, Entity Framework 6 and SQL Server 2008 R2.
I'm trying to delete from child entities, and this does not work. But if I try to delete directly from context, this works.
In my database I have 2 tables Students and Result.
This is my code that does not work :
Dim context as Myentities = New myentities.
Dim s as student.
Dim lresult as new list (of result)
s = context.students.where(Function(t1) t1.value>5).Tolist.first
lresult = (from t in s.results where t.vl2=7 select t).Tolist
for each rs as result in lresult
if rs.vl3=11 then s.results.remove(rs)
Next
Context.SaveChanges
This code produces an error on the last line (context.SaveChanges) :
An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll
Additional information: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
But if I change the line that delete the item, like below, it works :
Dim context as Myentities = New myentities.
Dim s as student.
Dim lresult as new list (of result)
s = context.students.where(Function(t1) t1.value>5).Tolist.first
lresult = (from t in s.results where t.vl2=7 select t).Tolist
for each rs as result in lresult
if rs.vl3=11 then context.results.remove(rs)
Next
Context.SaveChanges
Why does my first snippet of code not work?
I guess you defined the relationship between Students and Results by adding a Foreign Fey from Results to Students, a non-nullable field named StudentId or similar. When you do the Remove from the parent Student collection of Results, EF does not really remove the deleted Result from the context, EF just removes the relationship between them and sets the StudentId value in your Result child as null, but the child remains in the context. So you get an orphaned child that can't be saved because the FK field is null.
The problem is that your relationship conceptually is an Identifying relationship, which means that you can't have a Result that does not belong to a Student. But EF sees your relationship as non-identifying.
You have two options:
Make EF recognize the relationship as an Identifying relationship, by adding the Foreign Key field StudentId to the Primary Key of Results. You will have a composite key. This way EF will take care of removing the child from the context when you remove it from the collection in the parent.
Leave the PK as is, and explicitly remove the child from the context before saving. That is, you do both the Removefrom the parent collection and the context.Remove.
Usually the second option is preferred because composite keys are a bit complicated to deal with in EF. You can write a method to encapsulate the two operations that should go together every time you delete a Result from a Student.
More info about Identifying relationships here.

How do I make updates to data in a unique-constrained column across multiple rows without risking violating the constraint?

I have a table with a column with a unique constraint. The user will edit the data in this table in the form of a DataTable bound to a DataGrid. Once they are done modifying the data, the save function must apply their changes back to the database. For application architecture reasons, each change to the database must be performed as a create, update, or delete action one row at a time. I can validate the DataTable to be sure that the end result does not violate the constraint, but it seems impossible to verify that it will never be violated in between. Even if I do not allow duplicate values inside the DataGrid itself, the user could put a placeholder value in while making the modifications that would violate the constraint, and the DataTable class only seems to store the original and final versions of each row, not the intermediate versions.
How can I avoid any unique constraint violations while making these changes to the data?
The easiest way is to update all of the constrained values in a SQL statement:
UPDATE [Foo] Set [SomeUniqueValue] = CASE [ID] WHEN 1 THEN 'A' WHEN 2 THEN 'B' WHEN 3 THEN 'C' END WHERE [ID] IN (1,2,3)
This will not violate the unique if you were swapping the values around, as long as the uniqueness is preserved by the time the statement is finished.
If you must do it one row at a time, you would likely have to brute force run through your list of updates, catching errors when it failed, and in a loop keep retrying the ones that errored, until all updates were completed, or no more updates could be made:
bool didSomething;
List<Row> rowsThatNeedToTryAgain = new List<Row>();
do {
didSomething = false;
rowsThatNeedToTryAgain.Clear();
foreach (Row row in rowsToUpdate) {
try {
UpdateTheRowInTheDatabase(row);
didSomething = true;
} catch {
rowsThatNeedToTryAgain.Add(row);
}
}
rowsToUpdate.Clear();
rowsToUpdate.AddRange(rowsThatNeedToTryAgain);
} while (didSomething && rowsThatNeedToTryAgain.Count > 0);
if (rowsThatNeedToTryAgain.Count > 0)
throw new Exception("sorry, couldn't do 'em all");
A more elegant solution might do this from code without hitting the database, but that would assume your process is the only one updates at that time.

How to link foreign key to auto-incremented primary key in Oracle?

I have two tables whose common field is Load_ID. The PK of the first has a one-to-many relationship with the FK of the second. For example:
Table1:
1, someValue
Table2:
1, value1, ...
1, value2, ...
1, value3, ...
I've embedded the actual insert statement in an ASP.NET class where the values are taken from user input:
"INSERT INTO Compare_Header_Table VALUES
(compare_sequence.nextval, //other values are inserted here)
The sequence I'm using to auto-increment the PK is CREATE SEQUENCE compare_sequence;
This seems to work even without creating a trigger or specifying any parameters because the sequence defaults to an increment of 1 and an initial value of 1, which is fine for my purposes.
Where I'm running into problems is trying to link the FK from the second table to the PK of the first. I cannot simply use compare_sequence.currval because I have a separate method for inserting into each table, so I'm creating a new connection each time. I don't want to combine these into one method because that will involve changing the logical structure of my C# class, which I'd rather leave intact.
Any suggestions for how to make this work?
What you can do is use the RETURNING cause to get the assigned value:
INSERT INTO Compare_Header_Table (ID) VALUES
(compare_sequence.nextval)
returning id into some_value;
This some_value is a local variable which you need to pass out of your first class and hand on to the second class. How precisely you do that rather depends on your architecture.
Incidentally I do hope that when you say 'I'm creating a new connection each time' this is some c# jargon and you're not really creating a new database conection each time. Because that's a pretty expensive operation.
The other thing is, if you're in different sessions for creating the parent and child records what happens to the transaction? You'll have to commit each insert (otherwise the new parent record won't be visible to the foreign key validation when you try to insert the child).
If you want the INSERT operations to be done in separate sessions, you'll need to retrieve the generated key from the first statement and pass that in to the method that inserts the data into table2. One way to retrieve the generated key without requiring a database round-trip would be to do something like
INSERT INTO compare_header_table
VALUES( compare_sequence.nextval,
... )
RETURNING name_of_primary_key_column
INTO :bind_variable

NHibernate mapping with two special cases

I am using NHibernate to map a class to a database table. The Part table has an ID column (primary key) and a ParentPart column (along with a few others).
class Part
{
public virtual long ID{ get; set; }
public virtual Part ParentPart { get; set; }
}
The ParentPart is normally another valid part in the part table but I have two special cases. I have a case where the ParentPart column can be 0 (zero) and another case where it can be -1. Neither of these cases currently represent another valid Part object. I was thinking I could make 2 subclasses of Part (ZeroPart and NegativeOnePart) that would never persist. I want the zero and -1 values to be entered in the column but not persist the entire ZeroPart or NegativeOnePart objects. I am unsure how to map this (I'm using hbm files) or if this even the correct approach.
How can I map this so that normal valid parts are persisted but I can also handle the special cases?
As an aside: My current hbm file has the Part.ID's unsaved value as zero but I think I can just change this in the mapping to something different and default it in the class.
If I understand you correctly, you have a tree structure and you want to assign dummy-objects (with ID = 0 or ID = -1) that shall not be persisted to the database when persisting the objects. The ParentPart column shall contain ID = 0 or -1, depending on some criteria.
Based on this information I assume that you do not have foreign-keys in your table, so that saving an object with a ParentPart = 0 or -1 will not result in a violation of referential integrity. Under normal circumstances I would suggest using a foreign key and allowing NULL in the ParentPart column.
However, since you want two different values (0 and -1) as an indicator that no parent exists, I believe that your best option is probably just creating the two entries in the database (both with ParentPart = NULL).
If you strictly do not want to add those entries, you can have a look at intereceptors and events.
I don't think you can solve this within your mapping files. The NHibernate mapping feature is not designed to handle such specific logic, nor should it be able to do so.
(Having that kind of logic in the database may not be very desirable, but it sounds like this is not a new project, so we don't need to argue about it here.)
Will there be Part values in your "parts" table with the specified IDs, to maintain referential integrity?
If so, then I would suggest creating two special Part instances, each representing the special cases your model implies. You would need to fetch these instances from the database when you want to assign them, but this can be made simple with some helper methods on your repositories.

Create a new record with an assigned PK - Castle ActiveRecord

I have a table with a GUID primary key. In ActiveRecord it is setup with a PrimaryKeyType.GuidComb. Is it possible to create this record with a manually assigned PK? If I set the primary key in the record and run Create() a new ID is assigned. If I run Save() I get an error (as one would expect).
The why:
This table is in two databases. Records need to be copied between these two databases on occasion. I would like to retain the ID as the record moves across the DBs.
No. A primary key is either generated (e.g. GuidComb) or manually assigned, it can't be both. You could create two classes that inherited from a base class defining all properties except the primary key, then each of these two classes would define their primary key as assigned or generated. But I'd recommend using SQL here, as a single INSERT INTO ... SELECT will be more efficient than using NHibernate/ActiveRecord.
I ended up setting the PrimaryKeyType to Assigned. Then I handled it with an overrided Create function:
public override void Create() {
if (ID == default(Guid)) ID = GUIDGenerator.Generate();
base.Create();
}
It would have been better to put this in OnSave, but the primary key cannot be modified in the interceptor. This works for my application, however this code will only be called if the object is explicitly created. It will not work if the object is created by cascade.