I have the following table:
create table tbl
(
id int identity(1,1),
val varchar(100)
)
Now when i use Entity Framework to map objects to this table, it works, however when i change the table definition as follows:
create table tbl1
(
id int,
val varchar(100)
)
Entity Framework does not maps objects to this table. Any clue as to why is this happening would be appreciated.
Entity Framework requires a Primary Key to generate a model from the database. If there is no Primary Key on a table it will simply select the non-nullable columns as a concatenated primary key and the Entity will be read/only.
In your first table identity definition makes your id column non-nullable so you were able to create an Entity. You should have seen this message while adding that table:
"The table/view 'tbl1' does not have a primary key defined. The key
has been inferred and the definition was created as a read-only
table/view."
In your second table however there is no non-nullable column and EF cannot create an Entity for it. See the message when you try to add it:
"The table/view 'tbl1' does not have a primary key defined and no
valid primary key could be inferred. This table/view has been
excluded. To use the entity, you will need to review your schema, add
the correct keys, and uncomment it."
Entity frameworks generally need a way to distinguish between two records in a table and so require a ID/Key discriminator which need not be a primary key constraint or a unique key constraint or an identity at the DB layer. But this discriminator, a column or a set of columns, should help the entity framework identify a record uniquely and distinguish it from other records. So, you need to define such a discriminator in your entity class at the C# layer.
Related
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.
Im working on database design on Microsoft Sql server management Studio, I have a small problem. A LibraryItem should have a required category tied with a foreign key of CategoryId mapped to Id in the table Category as shown in the picture.
SEE THE IMAGE
SECOND IMAGE
I need help with how I can tie CategoryId(FK) to Id(PK on Category Table). I just dont know how to do it excatly.
You'll need to add the reference to the script that creates the table and add a name to the constraint like so:
CONSTRAINT FK_LibraryItem_Category_CategoryId FOREIGN KEY ([CategoryId]) REFERENCES [dbo].[Category] ([Id])
Note: I've defaulted to the dbo schema. You will need to change that if it's different for the Category table you are creating.
That will create a Foreign Key for your LibraryItem table and link the CategoryId to the respective record in the Category table.
Another thing to note as well: This will throw errors if your value for the FK doesn't match an ID in the Category table.
To ellaborate on the errors:
Let's say you add a CategoryId of 2 to a record in your LibraryItem table but a record with the ID of 2 doesn't exist in your Category table, it will throw an error similar to this:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_LibraryItem_Category_CategoryId". The conflict occurred in database "foo", table "dbo.LibraryItem". The statement has been terminated.
This can be easily solved by ensuring the IDs match in both tables.
I am using EF6.1 Database First/ObjectContext/POCOs.
I have a table called Foo and another table called FooHistory. This is how my model looks like:
Due to legacy reasons, FooNo is primary key on Foo, but not on FooHistory and a foreign key constraint does not exist in the database. However, this is a logical foreign key, so I set up a 1 to Many independent association between Foo and FooHistory. The Principal/Dependent property is FooNo.
The following Linq-to-Entities query:
var qry = from f in context.Foo.Include("History")
where f.FooNo.Trim() == "SomeNo"
select f.History.Count();
returns a value of 6, whereas the SQL sent to the database returns 10 rows (which is what I want).
I managed to get the query to give me the full 10 rows by creating a foreign key constraint in the database on FooNo and updating the model. At that point EF the Referential Constraint in the association's properties changed to the name of the database constraint. The multiplicity also changed, becoming 0...1 to Many.
However, I'd like to understand why the first approach does not work - Why are the results different when in both cases the query sent to the database is the same? Exactly what is going on internally?
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.
I have a table in Microsoft SQL Server 2008 R2 called Page with a primary key called ID. I have another table called Navigation with a column PageID. PageID is a unique foreign key reference to the ID column of Page. This creates a one to one relationship between Navigation and Page records.
When generating models from the database, it creates a one to many relationship where a Page contains a list of Navigation records.
Is this simply the Entity Framework detecting that there is a foreign key involved and ignoring the uniqueness of the columns in the database?
The SQL for the PageID column in Navigation is:
[PageID] INTEGER FOREIGN KEY REFERENCES [Page](ID) UNIQUE NOT NULL
The SQL for the ID column in Page is:
[ID] INTEGER PRIMARY KEY IDENTITY(0, 1) NOT NULL
Here is the solution I had originally, which is what Ladislav was mentioning.
The SQL for the PageID column in Navigation was:
[ID] INTEGER PRIMARY KEY FOREIGN KEY REFERENCES [Page](ID) NOT NULL
Entity framework doesn't support unique keys yet so this information is really ignored and one to many relation is mapped. The only way to use one to one relation in EF is through shared primary key (Navigation's ID will be FK to Page's ID).