Entity Framework foreign key that is not a primary key - c#

I am having problems with my MSSQL database design.
I had 2 tables that looked like this:
CREATE TABLE tenants
(
tenantId INT PRIMARY KEY,
tenantName VARCHAR
)
CREATE TABLE users
(
userId INT PRIMARY KEY,
userName VARCHAR,
tenantId INT,
FOREIGN KEY (tenantId) REFERENCES tentants(tenantId)
)
I wanted to switch from only IDs to GUIDs for uniqueness and changed the tables.
I have read that GUIDs as primary keys are not recommended for performance reasons. So I kept the IDs:
CREATE TABLE tenants
(
tenantId INT PRIMARY KEY,
tenantGuid UNIQUEIDENTIFIER,
tenantName VARCHAR
)
CREATE TABLE users
(
userId INT PRIMARY KEY,
userGuid UNIQUEIDENTIFIER,
userName VARCHAR,
tenantGuid UNIQUEIDENTIFIER,
FOREIGN KEY (tenantGuid) REFERENCES tentants(tenantGuid)
)
Now Entity Framework is going wild just dismissing all relationships because the guids are not part of the primary key.
On old posts I have read that this would be not supported. Is it still not supported?
How am I support to solve this?
Thanks a lot!
Also sorry for the bad formatting, the editor doesn't respect my line breaks :/
soomon

I wanted to switch from only IDs to GUIDs for uniqueness and changed the tables.
You don't really need to switch to GUIDs to ensure uniqueness.Your IDs will be guaranteed to be unique (whichever type they are, say integer) as long as they are set as your primary keys.
I have read that GUIDs as primary keys are not recommended for performance reasons. So I kept the IDs
tenantGuid uniqueidentifier foreign key to tenants.tenantGuid
Assuming you're talking about performance of 'joins' when using GUID as the key then keeping ID's as primary key will not make a difference since queries will be made on the GUID anyway.
Now entity framework is going wild just dismissing all relationships because the guids are not part of the primary key.
How am I support to solve this?
I believe you're better off not solving this and rather choosing either to go back to your previous database design which uses the integer ID. Or ultimately use GUID as your primary key (removing integer ID in the process).

If you still want to us the unique identifier, you need to take note on the below two things
Set the tenants.tenantGuid to UNIQUE KEY and also set the users.tenantGuid as the same data type
Modify the tables as below
CREATE TABLE tenants (
tenantId INT PRIMARY KEY,
tenantGuid UNIQUEIDENTIFIER UNIQUE,
tenantName VARCHAR
)
CREATE TABLE users (
userId INT PRIMARY KEY,
userGuid UNIQUEIDENTIFIER,
userName VARCHAR,
tenantGuid UNIQUEIDENTIFIER,
FOREIGN KEY (tenantGuid) REFERENCES tenants(tenantGuid)
)
Hope this works for you

Related

Microsoft Sync Framework unique index error

I use the MS Sync Framework to sync my SQL Server instance with a local SQL CE file to make it possible working offline with my Windows app.
I use GUIDs as keys. On my table I have a unique index on 2 columns: user_id and setting_id:
usersettings table
------------------
id PK -> I also tried it without this column. Same result
user_id FK
setting_id FK
value
Now I do the following:
I create a new record in this table in both databases - SQL Server and SQL CE with the same user_id and setting_id.
This should work and merge the data together since this can happen in real life. But I get an error when syncing saying the unique key constraint led to an error. The key pair already exists in the table.
A duplicate value cannot be inserted into a unique index. [ Table name = user_settings,Constraint name = unique_userid_settingid ]
Why can't MS sync handle that? It should not try to insert the key pair again. It should update the value if needed.
The issue is if you add the same key pair to different copies of the table, they get different IDs (GUIDs) as primary keys in this usersettings table.
As this is simply a many-to-many table between Users and Settings, there is no need to have that ID as a PK (or even a column at all).
Instead, just use a concatenated key of the two FKs e.g.,
CREATE TABLE [dbo].[usersettings](
[user_id] [UNIQUEIDENTIFIER] NOT NULL,
[setting_id] [UNIQUEIDENTIFIER] NOT NULL,
[value] [varchar](50) NOT NULL,
CONSTRAINT [PK_usersettings] PRIMARY KEY CLUSTERED ([user_id] ASC, [setting_id] ASC) );
Of course, include appropriate field settings (e.g., if you use VARCHARs to store the IDs) and relevant FKs.
As the rows inserted should now be identical on the two copies, it should merge fine.
If you must have a single column as a unique identifier for the table, you could make it meaningful e.g.,
the PK (ID) becomes a varchar (72)
it gets filled with CONCAT(user_ID, setting_id)
As the User_ID and Setting_ID are FKs, you should already have them generated so concatenating them should be easy enough.
Do you get the error during sync, then it should appear as a conflict, that you must solve in code.
https://learn.microsoft.com/en-us/previous-versions/sql/synchronization/sync-framework-2.0/bb734542(v=sql.105)
I also see this in the manual: By default, the following objects are not copied to the client database: FOREIGN KEY constraints, UNIQUE constraints, DEFAULT constraints, and the SQL Server ROWGUIDCOL property. This indicates poor support for your scenario
I suggest you remove the unique constraint from the device table.

MySqlException was unhandled error trying to create relational database

I get this error when i am trying to create a relational database:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' REFERENCES classes(Name))' at line 1
I used a Update method to update the data base and create new tables, the first Update method works but then the second one breaks it. This is my code
one.Update("CREATE TABLE classes (Name VARCHAR (30) , Primitive1 VARCHAR(30), Primitive2 VARCHAR(30), Primitive3 VARCHAR(30), PRIMARY KEY(Name)) ");
one.Update("CREATE TABLE primitives (Name VARCHAR(30), Size_bytes INT, Description TEXT, FOREIGN KEY (Classes), REFERENCES classes(Name))" );
You may have other problems, but you have an extra comma in the foreign key statement:
FOREIGN KEY (Classes), REFERENCES classes(Name)
should be:
FOREIGN KEY (Classes) REFERENCES classes(Name)
I note that you have no actual column called Classes in the table. Either you need to declare that, or you might mean:
FOREIGN KEY (Name) REFERENCES classes(Name)
EDIT:
And I'm a strong advocate of auto incrementing keys:
CREATE TABLE classes (
ClassesId int auto_increment primary key,
Name VARCHAR(30) not null unique,
Primitive1 VARCHAR(30),
Primitive2 VARCHAR(30),
Primitive3 VARCHAR(30)
);
CREATE TABLE primitives(
PrimitivesId int auto_increment primary key,
Name VARCHAR(30),
Size_bytes INT,
Description TEXT,
ClassId int references classes(ClassId)
);
Note the use of inline references. I'm sure some will disagree, but I find it easier to follow column definitions when they are in one place. Also, this adds auto-incrementing primary keys and uses the same column name for the primary key and foreign key.
Finally, having three columns that look the same -- Primitive1, Primitive2, and Primitive3 -- is usually a poor design. It is better to have another table with one row per class and "Primitive".
one.Update("CREATE TABLE primitives (Name VARCHAR(30), Size_bytes INT, Description TEXT, FOREIGN KEY (Classes) REFERENCES classes(Name))" );
is correct. You had comma , before REFERENCES

How do i assign unique identifier for a record in employee table?

I know it's first std question but someone asked me, but i was unable give him apropriate answer.
There are two tables Employee,Technology having many to many relation saved in employee_technology_rel.Employee table having fields- emp_id (auto_increment),emp_name(varchar),DOB (date) where Technology having fields tech_id(auto_increment),tech_name(varchar)
these two tables allows duplication of names.which unique constraint should i define for allowing unique entry?
You can define the unique entry on table employee_technology_rel,
ALTER TABLE employee_technology_rel
ADD CONSTRAINT emptech_pk PRIMARY KEY (emp_id, tech_id)
// or if you have set a primary key already, you can still define via UNIQUE
ALTER TABLE employee_technology_rel
ADD CONSTRAINT emptech_uq UNIQUE (emp_id, tech_id)
what it does is it only allows unique technology for every employee.
in order for you to have unique emp_name on table Employee as well as unique tech_name on table Technology, you can also alter the table by adding unique constraint
ALTER TABLE Employee ADD CONSTRAINT emp_uq UNIQUE (emp_name)
ALTER TABLE Technology ADD CONSTRAINT tech_uq UNIQUE (tech_name)
You want a composite primary key defined on the two columns in employee_technology_rel: emp_id and tech_id.
Unique Index and Unique Constraint are the same. They achieve same
goal. SQL Performance is same for both.
Add Unique Constraint
ALTER TABLE dbo. ADD CONSTRAINT
UNIQUE NONCLUSTERED ( ) ON
[PRIMARY]
Add Unique Index
CREATE UNIQUE NONCLUSTERED INDEX
ON dbo. ( ) ON
[PRIMARY]
Source sqlauthority.com and msdn from Google search: "SQL server unique index".

C# with SQLite and foreign key

I want to implement a patients data base for our software, and have an issue with the foreign key statement. I am using the latest SQLite DLLs, with C#.
When I try to run below code:
dbConnection = "Data Source=SQLiteMyDatabase.db;foreign keys=true;";
if (connections == 0)
{
cnn = new SQLiteConnection(dbConnection);
cnn.Open();
this.ExecuteNonQuery("CREATE TABLE IF NOT EXISTS patients ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(100) NOT NULL;");
this.ExecuteNonQuery("CREATE TABLE IF NOT EXISTS images ( FOREIGN KEY (patientID) REFERENCES patients(id), nameRed VARCHAR(20) NOT NULL PRIMARY KEY;");
}
I get the error:
SQLite error near "FOREIGN": syntax error
Why does this happen?
In order to create a foreign key, you must first create the column:
CREATE TABLE IF NOT EXISTS images (
nameRed VARCHAR(20) NOT NULL PRIMARY KEY,
patientID INT,
FOREIGN KEY (patientID) REFERENCES patients(id)
);
Please note:
I moved the primary key column (nameRed) first in the list of columns created, but that's just convention. It could go second.
You use the data type VARCHAR and SQlite will accept that, but be aware that it gets mapped to type TEXT, the maximum length will be ignored, and you will be able to store other data types in the column. SQLite is a bit funny when it comes to data types (it has a very well thought-out system but it's quite different from most other SQL databases).
To make things more confusing, you are allowed to declare the PRIMARY KEY as a property of the column (although you can also do it after the list of columns as with the FOREIGN KEY).

Having trouble creating a one to 'zero or one' relationship using Entity Framework

I have two tables:
CREATE TABLE Order (
orderId INTEGER IDENTITY NOT NULL,
PRIMARY KEY (orderId)
)
CREATE TABLE OrderAdditionalDetails (
additionalDetailsId INTEGER IDENTITY NOT NULL,
orderId INTEGER NOT NULL,
PRIMARY KEY (additionalDetailsId),
FOREIGN KEY (orderId) REFERENCES Order(orderId)
)
I have a Foreign key (FK_OrderAdditionalDetails_Order) declared on the OrderAdditionalDetails table, on the orderId field. I also have a 'unique' constraint on the orderId field in the OrderAdditionalDetails table. The idea is that each 'order' will have zero or one entries in the 'OrderAdditionalDetails' table.
This all picked up by the entity framework model file, however when I try to create the Navigation property, it only lets me declare a 1 to many relationship. The error I get is as follows:
Running transformation: Multiplicity is not valid in Role 'OrderAdditionalDetails' in relationship 'FK_OrderAdditionalDetails_Order'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be *.
I'm really not sure what this means - googling the error did not prove helpful. Can anybody shed some light on what I am doing wrong?
In your OrderAdditionalDetails table, remove the additionalDetailsID column and make the orderID the CLUSTERED PRIMARY KEY. Keep the FOREIGN KEY you already have. That is the right way to implement this.
There is not only no value added by the additionalDetailsId column, it makes things worse by taking more space in the table. The orderID is already a sufficient key; you need no secondary artificial key that is nothing but a surrogate for orderID.
Your Foreign Key must be defined as UNIQUE in order to enforce a One-To-Zero-Or-One relationship.
Maybe try something like this:
CREATE TABLE OrderAdditionalDetails (
additionalDetailsId INTEGER IDENTITY NOT NULL,
orderId INTEGER NOT NULL UNIQUE,
PRIMARY KEY (additionalDetailsId),
FOREIGN KEY (orderId) REFERENCES Order(orderId)
)
See Also: Implementing one-to-zero-or-one relation in SQL Server
I was trying to associate a table with a view of itself plus some other fields. (There is a very good reason for this that has nothing to do with the answer)
What cause the same error was there was more than one key field on the view. Even though I had specified the fields involved in the association it wanted both to be the only key fields for a 1 to 1 to work.
I also set the key field to be Distinct in the view, but I did that before I removed the key attribute of other fields, so it may ,or may not, be necessary.

Categories

Resources