I have this simple code : (update value)
I'm trying to update column "c"
using (MaxEntities ctx = new MaxEntities())
{
aa orders = (from order in ctx.aa
select order).First();
orders.c = 22;
ctx.SaveChanges();
}
this is the table :
CREATE TABLE [dbo].[aa](
[a] [int] NULL,
[b] [int] NOT NULL,
[c] [int] NOT NULL
) ON [PRIMARY]
and values inside :
but i get an exception :
The property 'c' is part of the object's key information and cannot be modified.
I'm new to EF.
any help will be much appreciated.
The property 'c' is part of the object's key information and cannot be modified.
That's why you can't edit it. Maybe you need to add id column as a key with identity specified
As explained in another answer EF must uniquely identify every entity. If you don't have PK in the database, EF will infer some key. Key is considered as fixed so if EF inferred c as part of the key (and it did it because it uses all non-nullable non-binary columns) you cannot change its value. Moreover EF takes all tables without primary key as readonly so even if you remove c from the key in the designer and modify c value you will get another exception when you execute SaveChanges.
The reason for the second exception is in the way how EF describes model and the database. When EF inferred key, it did it only for description of your entities and for context's internal needs but not for description of the database. When EF tries to save changes it builds UPDATE statement from database description and without information about real database PK columns it will not be able to identify correct record for update (every update in EF can affect only single record - EF checks ROWCOUNT). This can be solved by cheating EF and updating its database description = by describing some column in the table description as primary key. This leads to multiple problems:
You must have some unique column in the database otherwise this method will not work.
You must edit EDMX manually (as XML) to add this change
You must not use default MS EDMX designer for updating your model from database because it will delete your change
Simple advice: Either use database tables with primary keys or don't use Entity framework.
Primary key missing here. Add primary key in table and it work.
I believe if there's no PK at all, EF uses all of the fields/columns as part of the key info.Here's a nice explanation: by #SteveWilkes of why. But what do your entities look like? The other possibility is that it doesn't have a property because the association is inside a different entity, if this is a foreign key.
EDIT
This got me thinking. There are just going to be situations where you have to work with legacy tables having no PK, even if you would never create such a thing. What about views? EF is a mapper - it has to uniquely identify that record so it infers and defines this key. Yes, you could use stored procedures, but could you also hack the XML and remove the keys from the table definition?
AND EDIT AGAIN
After posting this, I see #Ladislav Mrnka already said a similar idea (cheating EF and updating its database description), so it has been done (WARNING: Consume at your own risk - never tried). Quick google got me this blog with clear instructions:
Close the model designer in Visual Studio if it is still open and re-open the .edmx file in an XML editor
Find the edmx:StorageModels -> Schema -> Entity Container -> EntitySet element that refers to the table in question
On the EntitySet element, rename the store:Schema attribute to Schema
Remove the store:Name attribute altogether
Remove the opening and closing DefiningQuery tags and everything in between them
Save and close the .edmx file
But really, who doesn't like a PK? Can you not add an id?
Related
I am working on code which I cannot run until it's finished, as it is a long and tedious process to go through. I have been tasked to add a new table to the existing database, update the .edmx of the model and write a method to add new rows to the table through c# backend code.
In my situation, I have 2 default constraints on my table
SomeTable
------------
ID INT IDENTITY (1,1) PRIMARY KEY CLUSTERED,
SomeDate DATETIME2 NOT NULL DEFAULT GETDATE(),
SomeOtherField VARCHAR(1024) NOT NULL DEFAULT ''
Using the .edmx model of this table, I set SomeDate's StoreGeneratedPattern to Computed. I also manually double-checked it in the SSDL to ensure the computed StoreGeneratedPattern attribute was on the SomeDate Field in the SomeTable entity.
As far as I know, and are unsure of, when I have a the following code
public void AddSomeRow(...)
{
SomeDbContext context = new SomeDbContext;
var table = new SomeTable { SomeOtherField = "Value" };
context.SomeTables.Add(table);
context.SaveChanges();
}
I believe the SomeDate Field will be set to it's default constraint (because it hasn't been populated in the entity). Is this true?
Doing the same steps listed above for SomeOtherField, can I still manually give it a value (the value appearing into that field instead of the Default Constraint) or omit it (The default constraint will be set into that field)?
This question was hard to explain, I apologize if it doesn't make sense
The StoreGeneratedPattern implies that the value is always generated by the DB, so that you're not allowed to modify it. I.e it only makes sense for DB computed columns.
At least until EF 6.1 there is no direct way to support DB defaults. The only thing that you can do is move the default values out of the DB and generate them in the model (or code first) side. You'll find some work-aounds but they're not safe for some cases (specially for N-tier apps).
I followed this article on making a table-per-type inheritance model for my entities, but I ran into some issues. Below I'm posting steps to reproduce the problem I'm having in a minimal environment to rule out other factors.
First, I created a new MS SQL Server 2008 R2 database with the following two tables:
Users
Id : bigint (PK and set it as the identity column)
Name : nvarchar(25) NOT NULL (whatever, some random property
Customers
Id : bigint (PK, identity column, and FK on Users.Id)
Title : nvarchar(25) NOT NULL (also whatever, some random property)
Next, I generated the .edmx entity model from the database, and followed the link at the top verbatim. That is to say, I deleted the association between User and Customer, set User as the base class of Customer, deleted the Id property from the Customer entity, and made sure that the Customer.Id column was mapped to the inherited User.Id property. I then ran the following small program:
using (var db = new EF_Test.testEntities())
{
var cust = db.Users.CreateObject<Customer>();
db.Users.AddObject(cust);
db.SaveChanges();
}
I get the following error when I make that last call:
"A value shared across entities or associations is generated in more than one location. Check that mapping does not split an EntityKey to multiple store-generated columns."
With the following inner exception:
"An item with the same key has already been added."
Any ideas on what I could be missing?
A quick google on the error message turned up the following solution, maybe it helps you:
http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/4bfee3fd-4124-4c1d-811d-1a5419f495d4
I think that I figured it out. The
table for the Party sub type had its
key column set to autogenerate a key
value and since it's derived, the EF
wanted to set that value explicitly.
So have you tried removing the "identity" setting from the customer table? So it doesn't autogenerate the primary key?
Hope this helps.
I finally found the source of my troubles. For those still interested, in the Customers table, the Id column should not have been set to the identity column of the table (PK and the FK dependency are fine though).
Why you don't want to make a foreign key (UserId) as a separate column? Maybe it can help you.
Also try to use model first approach and generate db after model creation as it is described in the following article.
So I have a table in the database, with a column that is simply an nvarchar(800).
When I try to do:
try
{
UserTable = (from x in entities.userTable where x.uID == uID select x).Single();
UserTable.DateCreated = DateTime.Now;
UserTable.text= newText;
Update(UserTable);
}
I get the exception in catch: "The property 'text' is part of the object's key information and cannot be modified."
When I look into the table, I don't see anything under "key" or "index". So it's not a key, I don't understand why C# is giving me incorrect information. Nothing in SQL Management Studio says anything about "text" being a key or index. What do I do?
Is there a PK on the table at all? If not, EF uses all of the fields/columns as part of the "key information."
View the data model by double clicking on the edmx file under the Models folder.
Make sure the keys are properly mapped. If you right click on a column you can toggle the Entity Key property. Once the column in question is not marked as entity key you should be able to update the value.
Follow these simple steps
Step 1: Check whether your table is having primary key column in database or not. If it does not have any primary key then add a primary key. Because if we don't add a primary key to table than entity framework creates its own key collection and add all columns in it.
Step 2: Open your .edmx file to see table object mapping. You will be able to see each column of table is having icon like primary key. So Write click on your page and update .edmx from database.
Step 3: If you still see same primary key icons on all columns than click on column name you want to update one by one and go to property window and Set Entity Key property to false.
The problem here is that Entity Framework cannot make changes to the primary key of the particular table. Now if you have not specified a primary key for your Table, entity framework will consider everything as the primary key, and thus you won't be able to make changes to the table. What you need to do is, define a primary key in the table, delete the table from your model from the Model Browser, and then re-add the table in the model. This shall surely fix it. Happy coding. Cheers!
I have created a C# app that makes a clone copy from an MS Access database and migrates the data to another DB server, but that will require changing the primary keys. What is the best way to maintain the referential integrity to the child tables when the parent tables keys are changed?
Thanks,
Andrew
You may already know this but your primary key column values should not be changing, much, if at all. However, that aside, you don't mention what database you are using. But with SQL Server, you can set up FK's to do what is called a cascading update. This means that if a PK value changes, all FK rows in child tables will have the value changed as well.
The following is an article describing this: http://blogs.techrepublic.com.com/datacenter/?p=128
I'm assuming you have autoIncrement set as the datatype on the PK field of an Access table and you want equivalent functionality in your new db.
Import the Access tables into destination tables with numeric, not auto-increment, data types. Then add your RI back between parent and child tables. Then edit your PK field to auto increment.
I did end up using composite primary keys since each time the app makes a clone copy it is a "snapshot" of the entire dataset. I've therefore added a columne called "Revision" and set each table's primary key to Pk = OID + REVISION.
For the child table it should reference the parent table by their primary key, which means the foreign key will also be composite. How do you achieve that relationship in Access? What I have done is in Access 2007 go to "Database Tools" -> "Relationship" and there edit the relationship so that it displays the following:
(parent Oid) 1 <--- many (child parentKey), (parent Revision) 1 <--- many (child Revision)
Please tell me is this is the way to do it. Or if someone can tell me how to achieve that using SQL commands I'll try that too.
Thanks,
I have a table which uses three columns as a composite key.
One of these column values is used as a sequence tracker for ordered related records. When I insert a new record I have to increment the sequence numbers for the related records that come after the new record.
I can do this directly in SQL Server Management Studio, but when I attempt this in LINQ I get the following error:
Value of member 'Sequence' of an object of type 'TableName' changed.
A member defining the identity of the object cannot be changed.
Consider adding a new object with new identity and deleting the existing one instead.
Can anyone suggest a way around this limitation?
(Adding a new record (as suggested by the error message) isn't really an option as the table with the composite key has a relationship with another table.)
Changing primary keys is a "code smell" in my book.
The fix we implemented was as follows
Deleted the relationship that used the composite key
Added autoincrement ID field, set that as primary key
Added Unique contstraint to the three fields that we were previously using as our
Re-created the relationship using the three fields that were previously our primary key
I worked around this by using a SQL stored proc to update one of the primary keys and calling it from LINQ.
I think the compiler is right. The only way of doing this is creating a new record and deleting the old one.
(Adding a new record (as suggested by
the error message) isn't really an
option as the table with the composite
key has a relationship with another
table.)
I think there's no problem with this. Just copy all the fields of your entity, set the new sequence, and set also any relation by just assigning the old EntitySet reference to the new one. I tried this and it updates correctly.
Besides of this, couldn't you just create a new ID column with auto-increment? I agree with #ocdecio. I think changing primary keys is poor design ...
I don't know LINQ, but would this work if you have cascading update defined on the SQL Server for the FK relationships?
Mind, I think using a composite key is a bad idea and changing one is a worse idea. The primary key should not change. Too many things can get broken if the primary key changes. And what do you do when the primary key changes and it is now not unique? If you do this, you will need a way to handle that as well because it will happen.