Self referencing foreign key - GUID - Entity framework 4 insert problems - entity-framework-4

I have successfully used EF4 to insert rows automatically with a server generated GUID:
http://leedumond.com/blog/using-a-guid-as-an-entitykey-in-entity-framework-4/
Now how does one perform this task if there exists a RowID (guid) and ParentRowID (guid) with a primary-foreign key constraint between the two? What would I set .ParentRowID to?
NewCut = New Row With
{
.ParentRowID = .RowID
}
SaveChanges throws a fit every time.
The fact that the primary key is a GUID is in fact irrelevant because I attempted the same test using a standard autogenerated integer without success.

The solution is as simple as the one you have posted.
Just create both parent and child entities in code, do not set Entity Key and not forget to set StoreGeneratedPattern for all server-generated Guid columns.
Then perform either MasterEntityInstance.Children.Add(ChildEntityInstance), or ChildEntityInstance.MasterEntity = MasTerEntityInstance and call SaveChanges.
After the SaveChanges call both guid properties will be populated with the correct Guid values, and ChildEntity.MasterEntity Entity Key will be populated with the necessary MasterEntity Entity Key value.

Related

Entity Framework DB First Identity Column override?

I have a MVC-Project with a DB-First EDMX file from a production database.
Let's say table Person has an identity-column named ID.
I also have a copy of this database where I have turnd OFF the Identity-Option for the ID column. My goal is to synchronize data between these two databases.
To connect to each of these databases I use the same context-class with different connection-strings.
The problem with this is, that when I try to add a copy of a row from table Person from productionDB to my copyDB I get an error, because EntityFramework is trying to insert NULL for the ID column. I know that this is totally normal, because the EDMX-File has set identity to TRUE for the ID-column of table Person, but is there a way to programatically change this behaviour?
Context prod = new Context("ProductionConnectionString");
Context prodCopy = new Context("CopyConnectionString");
var prodEntity = prod.Person.First(); \\ RETURNS A PERSON WITH ID 1
prodCopy.Person.Add(prodEntity):
prodCopy.SaveChanges(); \\THIS WILL THROW AN EXCEPTION BECAUSE EF WILL REPLACE 1 WITH NULL BECAUSE IDENTITY OPTION
Any ideas?

Updating a primary key value on grails gorm

I'm wondering if I can change a value of a primary key member of a composite primary key in a Grails Domain class? For example having this domain:
class StudentHistory implements Serializable {
String studentNumber
String schoolYear
Integer yearLevel
String section
Float average
String status
static mapping = {
...
id composite: ["studentNumber", "schoolYear", "yearLevel", "section"]
...
}
}
Let say, On the schoolYear: "2014-2015", a certain yearLevel: 1 student with studentNumber: "2011-488-MN-0" transferred section from section: "1D" to section: "1N". Now to perform this record update, we do something similar inside a service:
StudentHistory record = StudentHistory.find {
eq("studentNumber", "2014-488-MN-0")
eq("schoolYear", "2014-2015")
eq("yearLevel", 1)
eq("section", "1D")
}
record.setSection("1N")
record.save(flush: true, insert: false)
The problem is that the update on the primary key doesn't take effect but when I tried to update other non-Primary fields such as average and status, updating them works fine (I tried performing an SQL directly on the database to confirm). How can I update primary keys?
PS: Now, based on this design, I know some will suggest that why not just create another record, then just fetch the record that has been last entered? But what I am required to do is to update that composite primary key instead.
PPS: Please don't suggest on removing the old instance, and create a new one, copying the old details except for the section. I cannot do that since many tables are connected to this table.
I believe it is a good practice to avoid changing primary keys. Primary key is a unique identifier of an object and changing it effectively means creating a new object. So if your composite primary key is mutable (or can mutate) then you should use a surrogate key - an artificial primary key. At the same time you can create a unique constraint on the 4 fields currently being your primary key.
In your case it would be:
static mapping = {
...
}
static constraints = {
studentNumber(unique: ["schoolYear", "yearLevel", "section"])
}
Hope it makes sense.

BreezeJS custom SaveResult containing additional deleted entities

We are parsing the SaveBundle on the server and returning a custom SaveResult. We want to be able to notify the client of additional changed entities as a result of processing the SaveBundle.
For example we have a SaveBundle from the client containing 1 entity to be deleted which when we parse and process on the server we actually delete 2 entities.
As far as we can tell the SaveResult does not contain any properties that would allow us to indicate an entity was 'deleted', rather than say 'modified'.
Is there a way to return additional entity changes through the SaveResult? Or is the only solution to refresh the data by resubmitting a Breeze query client side after the save changes?
I 'think' that if you return the deleted entities with their foreign keys set to null or empty (in the case of non-nullable guids etc.) in the SaveResult then Breeze client-side will detect this and mark them as deleted
I couldn't find anything explicitly in the documentation or the source about this though
here is your answer:
var result = context.SaveChanges(saveBundle);
//create your own EntityInfo object and fill it with the the entity and it's state
var entityInfo = new EntityInfo();
//...
//add it to the result
result.Entities.Add(entityInfo);
//return the result
return result;
Breeze client will then treat that entity like any other entity returned from you normal save proc.
Hope this helps

Determine which entity properties have been modified in BeforeEntitySave

Using a custom EFContextProvider, I want to check which properties have been modified on an entity before it saves, so that I can implement:
Security: The client has permission to change only certain properties of an entity.
Auditing: Whenever certain properties are changed, the change needs to be logged.
There are suggestions on SO to use OriginalValuesMap to determine the modified properties, see here and here. If the original value differs from the new value, the property has been modified. However, these original values are supplied by the client, and thus can be forged to match the new values, bypassing this check.
The first SO question I linked suggests this is not an issue, because if the original values are forged in such a way, those properties won't be saved anyway:
For any other "unchanged" property, which we are not using in any way, we don't need to worry if it has been tampered with because, even if it has, the tampered value will not be persisted to the database
This is untrue however, as long as all modified properties on the entity have their original values forged. For example, the following code will bypass server-side security checks based on OriginalValuesMap and still save to the database:
manager.fetchEntityByKey('Employee', 42).then(function (result) {
var employee = result.entity;
employee.Salary(1000000); // do you think HR will notice?
delete employee.entityAspect.originalValues.Salary;
return manager.saveChanges();
});
When Breeze .NET receives the entity, it adds the entity to an Entity Framework context in Modified state, and with no properties marked as modified, Entity Framework's behaviour is to save all the supplied property values to the database.
IMO this is a security bug in EFContextProvider.HandleModified, where it overrides the EF entity state to Modified (there is even a comment in that method warning not to do so). In any case, what is the correct way to determine which properties have changed and are about to be saved?
In your Context intercept Save and check if it is legal save or not. For the sake of explanation, let's say you want to save entity of type RestrictedClass and you defined table RestrictedClasses which imitates table in your database.
public override int SaveChanges()
{
foreach (
var entry in
this.ChangeTracker.Entries()
.Where((e => (e.State == (EntityState) Breeze.WebApi.EntityState.Modified))))
{
if (entry.Entity.GetType() == typeof(RestrictedClass))
{
var entity = entry.Entity as RestrictedClass;
var originalEntities = RestrictedClasses.Where(e => e.Id = entity.Id).toList();
if (originalEntities.Count == 0) continue; // user is trying to add, illegal since it says it's modified, you do different check for EntityState.Added
var originalEntity = originalEntities[0]; // there should be only one, unique ID
//.... now you check differences between entity and originalEntity and decide whether it's legal or not based on user role.

Update part of primary key Entity Framework 4.0

I've a table with a compose primary key (3 columns):
UTP_ID (ITEMId)
UTS_ID (CategoryID)
USS_ID (SubCategoryID)
When I try to change SubCategory ,for example,with EF 4 i get follow error:
utl.USS_ID = Convert.ToInt32(ddlSubSetor.SelectedItem.Value);
the property is part of the object's key information and cannot be modified
Any Ideias?Why i can't change it?
EF implements an Identity Map between primary key property values and object references. It doesn't allow to change the key for the same object instance.
I would do this with direct SQL:
objectContext.ExecuteStoreCommand(
"UPDATE MyTable SET USS_ID = {0} WHERE UTP_ID = {1} AND UTS_ID = {2} AND USS_ID = {3}",
Convert.ToInt32(ddlSubSetor.SelectedItem.Value),
utl.UTP_ID, utl.UTS_ID, utl.USS_ID);
Make sure that your entity utl is detached from the context because this code directly writes into the database table and the entity doesn't get any information about this change. But this avoids having to delete and recreate the entity (which might be impossible due to existing foreign key constraints on the old row in the database).
As a result of being part of the entity key the object needs to be deleted from the context and re-attached with the new primary key value.
The Entity Framework works by having a context which manages the state of the entities, a collection of entities (basically the table) and the entity itself (a row of data). As data is read from the database it is added to the entity's collection which in turn is managed by the context for changes of state. Changing an Entity's key is really deleting the entry from the database and inserting a new one. As a result to change an entity key, first delete the entity from it's collection, detach the entity object to allow key modification, change the primary key value and re-attach the entity to the collection. Finally call save changes in the context to apply the changes to the database.
The following code should produce the desired results:
Context.UTLs.DeleteObject(utl);
Context.UTLs.Detach(utl);
Context.SaveChanges();
utl.USS_ID = Convert.ToInt32(ddlSubSetor.SelectedItem.Value);
Context.UTLs.AddObject(utl).
Context.SaveChanges();

Resources