I would like to use Umbraco Forms to not only insert data but to edit it as well. So far when I want to edit a record I am passing in the form guid and the record id via querystring and populating the correct data in the fields.
So far so good.
I am then hooking in to the Umbraco.Forms.Data.Storage.RecordStorage.RecordInserting event successfully like so
void RecordStorage_RecordInserting(object sender, Umbraco.Forms.Core.RecordEventArgs e)
{
var ms = (Umbraco.Forms.Data.Storage.RecordStorage)sender;
if(this record exists){
ms.UpdateRecord(e.Record, e.Form);
}
}
However when I try to submit an edited record, and the ms.RecordUpdate(e.Record, e.Form) line runs I get this error
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_UFRecordDataString_UFRecordFields_Key". The conflict occurred in database "UmbracoPlay", table "dbo.UFRecordFields", column 'Key'.
The statement has been terminated.
I can't delete the old record and then insert a new record because it will re raise the same event everytime I call ms.InsertRecord
What am I missing?
How can I use Umbraco Forms to edit existing data?
I couldn't see a fix for this bug- it appears as though the UpdateRecord method actually tries to insert all UFRecordField objects a second time rather than updating the existing values ( or the existing field values ) resulting in this key violation.
If you really need to work around this - as I did - then one thing that works ( but leaves you with somewhat more fragmented primary keys ) is simply to remove and then reinsert the form data:
var ms = (Umbraco.Forms.Data.Storage.RecordStorage)sender;
if(this record exists){
ms.DeleteRecord(e.Record, e.Form);
ms.InsertRecord(e.Record, e.Form);
}
An untidy solution, but seemingly effective.
Related
I'm developing an application in Quasar/Electron and using Dexie/IndexedDB for my database. I want to find all distinct records in the database that contain both my Event ID and a Dog ID (both key indexed fields). I am able to do this with the following code:
await myDB.runTable
.orderBy('[fk_event+fk_dog]')
.eachUniqueKey((theDuo) => {
this.runsArray.push({eventID: theDuo[0], dogID: theDuo[1]})
})
I'm using a combined key which is working well. However, I need to have more of the records than just the keys. I need a few more fields, is this possible?
I was trying to get records with the unique key function while also using the where function, but that doesn't seem to work.
I need to get all the unique (distinct?) dogs in the table that are in a particular event. And also get their corresponding information. I'm not sure if there is a better, more efficient way to do this? I can always pull out all the records and loop through them to build a custom array, I was just hoping to do this at the table read level. (yeah I'm still in tables/records even though these are collections etc. :p ).
Even the above code gives me all the events, and I can pull out what I need with a filter. I just was thinking it would be faster and more efficient to do it at the read level.
this.enteredRuns = this.runsArray.filter((theEvent) => {
return ( (theEvent.eventID == this.currentEventID) )
})
Try
await myDB.runTable
.orderBy('[fk_event+fk_dog]')
.clone({unique: "unique"})
.toArray()
I know this isn't documented but it should do the work to use unique cursor while still extracting the whole objects and not just the keys. You cannot combine with where but you could use .filter. Just be aware that not all records with be scanned as it will jump over records with same keys - selecting the first visited records only.
I have a plannerTask and in its Details it has a CheckList. I use it to programatically insert CheckListItems in it, and it all works like a charm when inserting or retrieving the tasks.
My problem arrives when I am going to insert a new CheckListItem and the CheckList already has 20 items. It returns a MaximumChecklistItemsOnTask (because it is forbidden to insert more than 20 items in a check list).
Solution could be to remove the oldest item, but I am not able to do it. I have tried this:
var elementToRemove = oldDetails.Checklist.Where(c => c.Value.IsChecked).OrderBy(c => c.Value.LastModifiedDateTime).First();
oldDetails.Checklist = oldDetails.Checklist.Where(c => c.Value.LastModifiedDateTime <> elementToRemove.Value.LastModifiedDateTime);
But it throws a casting error in the second line:
Unable to cast object of type
'WhereEnumerableIterator1[System.Collections.Generic.KeyValuePair2[System.String,Microsoft.Graph.PlannerChecklistItem]]'
to type 'Microsoft.Graph.PlannerChecklistItems'.
Which is the right way to remove the oldest element from the ChecklistItem?
UPDATE:
In first place I retrieve a plannerTask from the server. Then I get the details from this plannerTask. So oldDetails is a plannertaskdetails object (https://learn.microsoft.com/en-us/graph/api/resources/plannertaskdetails?view=graph-rest-1.0). Inside the plannertaskdetails object (oldDetails), I have the plannerchecklistitems object (oldDetails.Checklist): https://learn.microsoft.com/en-us/graph/api/resources/plannerchecklistitems?view=graph-rest-1.0.
If plannerchecklistitems were just a List, it would be as easy as list.Remove(item), but it is not a normal list, and that is why I am not able to remove the item.
UPDATE 2:
I have found this way to remove the item from oldDetails:
oldDetails.Checklist.AdditionalData.Remove(elementToRemove.Key)
But, the the way I send the changes to the server is this:
await graphClient.Planner.Tasks(plannerTask.Id).Details.Request().Header("If-Match", oldDetails.GetEtag).UpdateAsync(newDetails)
As it is a PATCH request (not a PUT one), I only have in newDetails the records that have changed, it is, the new records. How could I specify there that a record has been deleted from the list? Sorry if my English is not good enough to express myself properly, but what I mean is that newDetails is not the full list, it only contains the records that must be added and I do not know how to specify in that request that one record must be deleted.
in my SAPUI5-Application I got the following function that takes the data and creates an entry in my HANA DB:
onCreateNewCustomer: function(){
var oEntry = {};
oEntry.NAME = this.byId("name").getValue();
oEntry.CITY = this.byId("city").getValue();
oEntry.PHONE = this.byId("phone").getValue();
oEntry.ID = this.byId("id").getValue();
// Post data to the server
this.getOwnerComponent().getModel("CustomerModel").create("/Customer", oEntry, null);
this.byId("createCustomer").close();
//location.reload();
}
The creating process works and my entries get saved. In the next step I wanted to implement my table in HANA in that way, that the ID of the entries will be autoincremented so the user does not have to enter it. I used the following command to create my table:
create column table TABLE
(ID bigint not null primary key generated by default as IDENTITY,
FIRSTNAME nvarchar(30))
That worked, table is created. The problem now is, if I use the code above without providing the ID, the following error is logged by the console:
The following problem occurred: HTTP request failed 400,Bad Request,The serialized resource has an missing value for member 'ID'.
The entry does not get saved in my DB. If I execute the following SQL-Statements in my HANA Workbench without providing the ID, it works:
insert into TABLE (FIRSTNAME) values (‘David’);
insert into TABLE (FIRSTNAME) values (‘Mike’);
insert into TABLE (FIRSTNAME) values (‘Bobby’);
So I did some searching on google but did not find a proper solution on how to do this. My goal is that the entry gets saved and the ID is provided by my HANA DB without providing it from my SAPUI5 Application.
Probably you are using ODataV2 XSODATA implementation which does not support auto-increment. The possible solution here is to use a database sequence and then with a separate request get a value from it and use it in OData create statement.
Did you try creating a new record by commenting out the below code like ?
oEntry.ID = this.byId("id").getValue();
With identity fields, if you provide the value you have to explicitly identify that you are providing the column value. Otherwise, just omit the columnn name and value from the INSERT command.
While updating with the help of LINQ to SQL using Entity Framework, an exception is thrown.
System.Data.UpdateException: Unable to update the EntitySet 't_emp' because it has
a DefiningQuery and no <UpdateFunction> element exists in the
<ModificationFunctionMapping>
The code for update is :
public void Updateall()
{
try
{
var tb = (from p in _te.t_emp
where p.id == "1"
select p).FirstOrDefault();
tb.ename = "jack";
_te.ApplyPropertyChanges(tb.EntityKey.EntitySetName, tb);
_te.SaveChanges(true);
}
catch(Exception e)
{
}
}
Why am I getting this error?
The problem was in the table structure. To avoid the error we have to make one primary key in the table. After that, update the edmx. The problem will be fixed
Three things:
Don't catch exceptions you can't handle. You're catching every exception possible, and then doing nothing with it (except swallowing it). That's a Bad Thing™ Do you really want to silently do nothing if anything goes wrong? That leads to corrupted state that's hard to debug. Not good.
Linq to SQL is an ORM, as is Entity Framework. You may be using LINQ to update the objects, but you're not using Linq to SQL, you're using Entity Framework (Linq to Entities).
Have you tried the solution outlined here? The exception you posted is somewhat cut off, so I can't be sure it's exactly the same (please update your post if it isn't), and if it is the same, can you comment on whether or not the following works for you?
"[..] Entity Framework doesn't know whether a given view is updatable
or not, so it adds the <DefiningQuery> element in order to safeguard
against having the framework attempt to generate queries against a
non-updatable view.
If your view is updatable you can simply remove the <DefiningQuery>
element from the EntitySet definition for your view inside of the
StorageModel section of your .edmx, and the normal update processing
will work as with any other table.
If your view is not updatable, you will have to provide the update
logic yourself through a "Modification Function Mapping". The
Modification Function Mapping calls a function defined in the
StorageModel section of your .edmx. That Function may contain the
name and arguments to a stored procedure in your database, or you can
use a "defining command" in order to write the insert, update, or
delete statement directly in the function definition within the
StorageModel section of your .edmx." (Emphasis mine, post formatted for clarity and for Stack Overflow)
(Source: "Mike" on MSDN)
But You can Set primary Key in Model if use MVC Asp.net
Just Open model.edmx in your table ,go to your field property and set Entity Key = True
I'm facing this exception An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported. when I try to insert a new entity into my Employees table (the master one).
There is a relationship between the master Employees table and the details Orders table, and I'm sure that the relationship between these two tables (and specifically Employee.Orders EntitySet) is the cause of the problem since when I removed the relationship, it returns back to insert into Employees table with no problems.
When I searched for the problem, there was this blog post which I tried to implement but my case is a different than the one in the blog post in these items:
He faces the exception when tries to update (while I try to insert).
The tables architecture is different.
how can I solve this problem?
Here's the insertion code:
Employee emp = new Employee();
emp.Name = empName; // empName is a local variable
// What should I default emp.Orders to?
dc.Employees.InsertOnSubmit(emp);
dc.SubmitChanges();
P.S: My DataContext is defined on class-level in my repository and the exception is being thrown when I call dc.SubmitChanges();. and I didn't Attach any object why does it say that?
Here is an article explaining what you need to do using the Attach and Detach methods:
http://www.codeproject.com/KB/linq/linq-to-sql-detach.aspx
I am guessing it is trying to save something else besides just the employee object or you aren't showing us the full code in your repository. When you instantiate your DataContext object (dc) try setting DeferredLoadingEnabled = false, and ObjectTrackingEnabled = false and see if it works. If it does, try watching the SQL code in SQL Server Profiler and see if it is modifying other objects that may have came from a different context like the message says.
var dc = new MyDataContext()
{
DeferredLoadingEnabled = false,
ObjectTrackingEnabled = false
};
My bet is on the primary key.
Are you sure the primary key is also set on auto increment?
Did you
try changing the name, does it work then?
What happens if you remove
all rows from your DB? can you insert one then?