How to implement a cross-database foreign key constraint? - asp.net

Let's say I have two schemas: HR and Orders.
[HR].Employees [Orders].Entries
-------------- ----------------
Id_Employee ----> Employee
Fullname Id_Entry
Birthday Description
Amount
As you can see, what I'd want is to be able to establish a cross-database foreign key, but when I try this using a database link, I get:
-- From [Orders]
ALTER TABLE Entries
ADD CONSTRAINT FK_Entries_Employees FOREIGN KEY (Employee)
REFERENCES Employees#HR;
COMMIT;
ORA-02021: DDL operations are not allowed on a remote database
Is there a way around this? It's a legacy database, so I can't change the existing schema.
For the NHibernate crowd: I would then use this relation to map the NHibernate's domain objects.

One option would be to create a materialized view of Employees on [Orders] and then use that as the parent for the foreign key.
Of course, that has some drawbacks. In particular,
-- you won't be able to do a complete refresh of the materialized view without disabling the foreign key, so it'll have to fast refresh.
-- keys entered into EMPLOYEES won't be available to ENTRIES until the materialized view refresh. If that's critical, you may want to set it to refresh on commit.
Other alternatives are to handle the key enforcement yourself through a trigger or through a post cleanup process. Or convince the DBA's that these schemas can reside on the same database instance.

As far as I know constraints and referential integrity are only supported within one single database.
If you need to cross the boundaries of the database, you'd have to be creative. Maybe write some triggers checking for data in the other database or enforce these constraints on the application level. But then you may encounter the problem with transaction scope limited to one single database.

Related

sqlite- interlinking two database tables using foreign keys

In SQL in general, but in SQLite for this case, can we establish a foreign key from one table say, table in db1.db to mainTable in db2.db. That is we can use a foreign key relationship in table by referencing the primary key in mainTable, the main idea being to use this relationship to trigger ON DELETE CASCADE. (Briefly in my case, mainTable happens to be a system maintained SQLITE database, which I'd like to avoid manual finding and analyzing. If I could somehow access establish this key, life would be a lot easier).

SQL Delete taking too long

We have a table(say T1) that is referenced by about 16 other tables with foreign keys in our SQL Server database. The data is accessed through an ASP.NET application with LINQToSQL. When the user tried to delete a record from T1 the statement would time out. So we decided to first delete the records from the tables that reference T1 and only then delete the record in T1. The problem is that deletion from T1 does not work as fast as expected.
My question is: is it normal that deletion from a table referenced by many other tables to be so time-consuming even if the record itself does not have any 'children' records?
EDIT: Apparently the cause for the timeout was not the delete itself but another query that retrieved data from the same DataContext. Thank you for your suggestions, I have marked as answer the suggestion to add indexes for all foreign keys because it improved our script's execution plan.
I suspect that you may need to look into the indexing on your child tables.
It sounds as if you FKs are set to Cascade Deletes, so I would suspect that some of your tables do not have an index that includes the key to the parent as the first in the index.
In this way your delete will be full scanning the child tables - even if you've already deleted the child records it will still check as you've still got the Cascade set.
When you define a relationship in DB, you can set the Delete rule as Cascade in SQL server. In this way, when you delete the record from the parent table, it will be automatically deleted from the child tables.
Please see the image below:
If it taking long time, you may have set other constraint that will slow
down the process of deletion.
Linq does not do bulk deletes if you're having it operate directly on the record set -- instead, it is probably deleting one record at a time.
To improve performance, use a stored procedure instead for any bulk insert, update or delete operations.

insert data from a asp.net form to a sql database with foreign key constraints

i have two tables
asset employee
assetid-pk empid-pk
empid-fk
now, i have a form to populate the asset table but it cant because of the foreign key constraint..
what to do?
thx
Tk
Foreign keys are created for a good reason - to prevent orphan rows at a minimum. Create the corresponding parent and then use the appropriate value as the foreign key value on the child table.
You should think about this update as a series of SQL statements, not just one statement. You'll process the statements in order of dependency, see example.
Asset
PK AssetID
AssetName
FK EmployeeID
etc...
Employee
PK EmployeeID
EmployeeName
etc...
If you want to "add" a new asset, you'll first need to know which employee it will be assigned to. If it will be assigned to a new employee, you'll need to add them first.
Here is an example of adding a asset named 'BOOK' for a new employee named 'Zach'.
DECLARE #EmployeeFK AS INT;
INSERT (EmployeeName) VALUES ('Zach') INTO EMPLOYEE;
SELECT #EmployeeFK = ##IDENTITY;
INSERT (AssetName, EmployeeID) VALUES ('BOOK',#EmployeeFK) INTO ASSET;
The important thing to notice above, is that we grab the new identity (aka: EmployeeID) assigned to 'Zach', so we can use it when we add the new asset.
If I understand you correctly, are you trying to build the data graph locally before persisting to the data? That is, create the parent and child records within the application and persist it all at once?
There are a couple approaches to this. One approach people take is to use GUIDs as the unique identifiers for the data. That way you don't need to get the next ID from the database, you can just create the graph locally and persist the whole thing. There's been a debate on this approach between software and database for a long time, because while it makes a lot of sense in many ways (hit the database less often, maintain relationships before persisting, uniquely identify data across systems) it turns out to be a significant resource hit on the database.
Another approach is to use an ORM that will handle the persistence mapping for you. Something like NHibernate, for example. You would create your parent object and the child objects would just be properties on that. They wouldn't have any concept of foreign keys and IDs and such, they'd just be objects in code related by being set as properties on each other (such as a "blog post" object with a generic collection of "comment" objects, etc.). This graph would be handed off to the ORM which would use its knowledge of the mapping between the objects and the persistence to send it off to the database in the correct order, perhaps giving back the same object but with ID numbers populated.
Or is this not what you're asking? It's a little unclear, to be honest.

parsing SQLException errors in an ASP.NET (MVC) application?

While validation can prevent most SQL errors, there are situations that simply cannot be prevented. I can think of two of them: uniqueness of some column and wrong foreign key: validation cannot be effective as the an object can be created or deleted by other parties just after validation and before db insertion. So there are (at least) two SQL errors that should lead to a message of invalid user input.
SQLException has a Number property for the error type, but I don't know how to find out which column is duplicated or which foreign key is wrong without trying to parse the actual error message text, which happens to be localized.
Is there any way to identify the offending column other than parsing the error message (which means at least to strictly choose a language for SQL Server and always use it)?
edit:
I should mention that I come from RubyOnRails, where the approach is: let's pretend that the db doesn't exist: no constraints, no db-enforced foreign keys etc. As I'm approaching ASP.NET MVC, I'd like to get rid of the rails biases, and accept the fact that the db indeed exists.
Are you sure these two situations absolutely cannot be prevented?
You can avoid unique constraint SQLexceptions on Insert, by using an Identity (database generated) primary key column. SQL Server will guarantee that the value is unique.
The same goes for inserting related rows into tables linked by a foreign key. Insert a row in each referenced table first, before inserting a row in the main table. Use IDENTITY_INSERT to get the value of each auto generated primary key and use this as the foreign key in your main table.
You should also wrap these individual statements in a transaction to ensure that either all tables are inserted successfully or none are. The transaction also isolates (hides) these changes from all other concurrent database accesses until the transaction is committed.

Update Data Model Business Entity

I have web application where Iam using linq to business entites i have business data model.
the problem is :
I have table with one column that it dosen't allow null value, when I try to update this table the folloeing error arise:
error The property 'e.g Carrier' is part of the object's key information and cannot be modified
what I can do?
The easiest thing to do is add a second column to the table that has a unique key eg guid and create a read only property on the entity that corresponds to it.
Linq to business entites needs some kind of key to keep track of what to update in the database. Usually this is the primary key on the database table. If you dont have a primary key it cannot reliably update the database and will then send you an exception.
Also if there is no primary key explicitly set on the table linq to business entites will select one of the columns (think its the first column in the table but i could be wrong) to act as a primary key and will therefore not allow you to update it.

Resources