Laravel Eloquent last inserted object wrong properties - orm

I've got a problem while using Laravel Eloquent ORM:
When inserting a new Eloquent Model in the database, the data is corrupted.
To be concrete:
$newItem = new NotificationNewItem;
$newItem->item_id = $item->id; // item_id is the primary key (returned by getKeyName())
$newItem->save();
return NotificationNewItem::find($item->id);
This code does not return the same as
$newItem = new NotificationNewItem;
$newItem->item_id = $item->id;
$newItem->save();
return $newItem;
whereas the two items should be the same, shouldn't they ?
The weird part is that the returned JSON object (I show it directly in my browser) in the first case is exactly what is inserted in the database, and in the second case the JSON Object's primary key (here item_id) is equal to 0 even if in the database the corresponding entry has a primary key equal to 3 (or different values).
Here's the laravel code if you want to see that error again : http://pastebin.com/9wcsnvSq
There are two "returns" in the model function insertAndGetElement() and those return items with different primary keys (the first one in that pastebin is returning a primary key equal to 0).
Help will be much appreciated.
Thanks in advance,
Robin.

The solution to that problem (Primary key set to 0 after calling save()) is to precisely define the model as not auto_incrementing the primary key.
To do so, just use
public $incrementing = false;
in the model declaration. Thanks to AndreasLutro on #laravel!

i don't know what exactly you want, but to get last insert id use this:
$newItem = new NotificationNewItem;
$newItem->item_id = $item->id;
$newItem->save();
// $newItem->id; this is lastinsertedid
return $newItem->id;
//NotificationNewItem::find($newItem->id);

Related

Sitefinity - Safely delete orphaned dynamic content records

I've been adding records to a dynamic module via the API and in the process during my experimentation I added a bunch of records that weren't associated correctly with any valid parent record.
I've checked and so far I can see that Sitefinity stores data about these records in a number of tables:
mydynamiccontenttype_table
sf_dynamic_content
sf_dynmc_cntnt_sf_lnguage_data
sf_dynmc_cntent_sf_permissions
I would like to clean up the database by deleting these records but I want to make sure I don't create more problems in the process.
Anyone know if there are more references to these dynamic content type records or a process to safely delete them?
There are probably other tables, so your safest option would be to delete the items using the Sitefinity API.
Just get the masterId of the item and use a code like this:
public static void DeleteDataItemOfType(this DynamicModuleManager manager, string type, Guid Id)
{
Type resolvedType = TypeResolutionService.ResolveType(type);
using (var region = new ElevatedModeRegion(manager))
{
manager.DeleteDataItem(resolvedType, Id);
manager.SaveChanges();
}
}

Updating entities with primary key and alternate composite key

I have a series of metric snapshot data I am uploading into my database on a daily basis. I take the input and check to determine if it is already in the database, and if it's not I add it. Each record uses a composite key made up of three columns, and also has a primary key.
I have since tried to add logic so that I can optionally force an update on records that already exist in the database, in addition to adding those that don't yet exist. I run into an error though preventing me, saying that there is already an object with the specified key being tracked.
The instance of entity type 'MembershipSnapshot' cannot be tracked
because another instance of this type with the same key is already
being tracked. When adding new entities, for most key types a unique
temporary key value will be created if no key is set (i.e. if the key
property is assigned the default value for its type). If you are
explicitly setting key values for new entities, ensure they do not
collide with existing entities or temporary values generated for other
new entities. When attaching existing entities, ensure that only one
entity instance with a given key value is attached to the context.
Here's a snippet of my code.
// Get the composite keys from the supplied list
var snapshotKeys = snapshots.Select(s => new { s.MembershipYear, s.DataDate, s.Aggregate }).ToArray();
// Find which records already exist in the database, pulling their composite keys
var snapshotsInDb = platformContext.MembershipSnapshots.Where(s => snapshotKeys.Contains(new { s.MembershipYear, s.DataDate, s.Aggregate }))
.Select(s => new { s.MembershipYear, s.DataDate, s.Aggregate }).ToArray();
// And filter them out, so we remain with the ones that don't yet exist
var addSnapshots = snapshots.Where(s => !snapshotsInDb.Contains(new { s.MembershipYear, s.DataDate, s.Aggregate }))
.ToList();
// Update the ones that already exist
var updateSnapshots = snapshots.Where(s => snapshotsInDb.Contains(new { s.MembershipYear, s.DataDate, s.Aggregate }))
.ToList();
platformContext.MembershipSnapshots.AddRange(addSnapshots);
platformContext.MembershipSnapshots.UpdateRange(updateSnapshots);
platformContext.SaveChanges();
How do I go about accomplishing this task?
I don't have a compelling reason why I have an auto-increment primary key, other than perhaps whatever performance issues it might give SQL internally?
EDIT: The way I've currently solved this issue is my removing my surrogate key, which I'm not using at all for anything. Still, it would be nice to know a workaround without having to remove this as a surrogate key could come in handy in the future.

Adding a new entry that has no foreign keys results in a "The relationship could not be changed [..]" error

I am running into a weird problem. When I deploy my code, everything works. I can add orders to my system. However, after some orders has been made, I start to get the famous error:
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
Now, I have read a lot about that error, but it doesn't help my case. I have a very simple database without any foreign keys:
My code looks like the following:
public NewOrder Create(NewOrder order)
{
var o = new WebshopOrder();
o.AdvertId = order.AdvertId;
o.DateCreated = DateTime.Now;
o.IsActivated = order.OrderState > OrderState.Created;
o.ProductId = order.Product.Id;
o.UserId = order.UserId.ToString();
Db.WebshopOrder.Add(o);
Db.SaveChanges();
return new NewOrder() { WebshopOrderId = o.Id};
}
Which in turn, then fails when I say Db.SaveChanges().
Any idea what on earth could be wrong here?
I see three possibilities at the moment:
ProductId is being sent to the DB as NULL
OrderId is being sent to the DB as NULL
Timestamp is being sent to the DB as NULL
I think it is complaining about one of those three columns that are the only ones that do NOT allow NULL. I think ProductId has the greatest chance of being the culprit, where your code is being called sometimes with a value there, and others times it is receiving a NULL product.
This may, or may not be the issue, but your code has:
order.Product.Id
Did you want to use this instead?
order.ProductId
That error message would be improved if it were split into two or more errors with each being more specific.
I can see from your question that you are looking into the Order table for relationships.
Instead you have to look into WebshopOrder table for any relations, because you are saving the WebshopOrder
Db.WebshopOrder.Add(o);
Db.SaveChanges();

Entity Framework 5 foreign key values not updating (VB.NET)

I realise many similar questions have been asked but after attempting tens of examples I still cannot get this to work. The problem I am having involves the updating of foreign key values in the Users table.
I am creating a website using ASP WebForms, .net 4.5, Entity Framework 5, SQL server 2012.
I created the EF using database first, here you can see a sample of the model:
I am using a 3 tier architecture - my data access layer queries the database using LINQ and returns a User object (as defined by T4).
This means the object is disconnected from the context when it is modified. (right?)
I modify the object in the page's code behind, updating the UserRole by doing this:
(in page load)
Dim _userAcces As UserLayer = UserLayer.getInstance
mUser = _userAcces.getUserWithCustomerAndRole(_ID)
Dim _rolesAccess As UserRolesLayer = UserRolesLayer.getInstance
mRoles = _rolesAccess.listUserRoles
(on button click)
mUser.UserRole = mRoles.Item(dropDownRole.SelectedIndex)
At this point the mUser object holds the correct (updated) UserRole object. I then pass the mUser object back into my data layer to update the database. The simnplest examples I have seen do this:
Using _context As New SaasPortalContext
_context.Entry(updatedUser).State = EntityState.Modified
_context.SaveChanges()
End Using
I have also tried using:
_context.users.attach
getting the original from the context using _context.users.find(id) and updating the original from the updated User object
getting the dbentityentry object from _context.entry(updatedUser) and setting the property("UserRole").isModified property to true
Using any of these methods I expect the foreign key value for UserRole in the Users table to update to be the ID of a different role in the UserRole table, reflecting the changes in the mUser object, but this does not happen and the value does not change.
What am I doing wrong? Why will the ID not update in the Users table?
Any help would be greatly appreciated
I finally worked out what I was doing wrong, I did not check the box for "include foreign key relationships" when setting up the model, meaning the relationships were not properly defined (I assume).

The "X" property on "Y" could not be set to a 'null' value. You must set this property to a non-null value of type 'Int32'

When I run my application and I click a specific button I get the error:
"The "X" property on "Y" could not be set to a 'null' value. You must set this property to a non-null value of type 'Int32'."
Cool so I go to my Entity project, go to Y table, find X column, right-click and go to X's properties and find that Nullable is set to False.
I verify in SQL that in Y table, X is set to allow nulls, and it is.
I then go back to my Entity project, set Nullable to True, save and build and I receive:
Error 3031: Problem in mapping fragments starting at line 4049:Non-nullable column "X" in table "Y" is mapped to a nullable entity property.
I've heard that deleting the table from the .edmx file and then re-adding it is a possibility but have never done that and don't understand the implications enough to feel comfortable in doing that.
I've heard that it could be in the view, could be in the stored procedure...
Also have heard that this is a bug.
Has anyone come across this and found an "across the board" fix or somewhat of a road map of sorts on where to look for this error?
Thanks!
"The "X" property on "Y" could not be set to a 'null' value. You must set this property to a non-null value of type 'Int32'."
In your EDMX, if you go under your Y table and click on X column, right-click, click on Properties, scroll down to Nullable and change from False to True.
If you get a "mapping fragment" error, you'll have to delete the table from the EDMX and re-add it, because in the Model Browser it stores the table properties and the only way to refresh that (that I know of) is to delete the table from the Model Browser under <database>.Store then retrieving it using Update Model from Database.. command.
I just replace data type int to int32?
public Int32 Field{ get; set; }
to
public Int32? Field{ get; set; }
and the problem is solved
My problem was that my Model database was out of sync with the actual (dev) database. So the EDMX thought it was smallint but the actual column was int. I updated the model database to int and the EDMX to Int32 and now it works.
For future readers.
I got this error when I had a multiple result stored procedure.
As seen here:
http://msdn.microsoft.com/en-us/data/jj691402.aspx
If you try to access an item in the first-result, after doing a .NextResult, you may get this error.
From the article:
var reader = cmd.ExecuteReader();
// Read Blogs from the first result set
var blogs = ((IObjectContextAdapter)db)
.ObjectContext
.Translate<Blog>(reader, "Blogs", MergeOption.AppendOnly);
foreach (var item in blogs)
{
Console.WriteLine(item.Name);
}
// Move to second result set and read Posts
reader.NextResult();
var posts = ((IObjectContextAdapter)db)
.ObjectContext
.Translate<Post>(reader, "Posts", MergeOption.AppendOnly);
foreach (var item in posts)
{
Console.WriteLine(item.Title);
}
Now, if before the line
foreach (var item in posts)
you put in this code
Blog foundBlog = blogs.FirstOrDefault();
I think you can simulate the error.
Rule of Thumb:
You still gotta treat this thing like a DataReader (fire-hose).
For my needs, I had to convert to a List<>.
So I changed this:
foreach (var item in blogs)
{
Console.WriteLine(item.Name);
}
to this:
List<Blog> blogsList = blogs.ToList();
foreach (var item in blogsList )
{
Console.WriteLine(item.Name);
}
And I was able to navigate the objects without getting the error.
Here is another way I encountered it.
private void DoSomething(ObjectResult<Blog> blogs, ObjectResult<Post> posts)
{
}
And then after this code (in the original sample)
foreach (var item in posts)
{
Console.WriteLine(item.Title);
}
put in this code:
DoSomething(blogs,posts);
If I called that routine and started accessing items/properties in the blogs and posts, I would encounter the issue. I understand why, I should have caught it the first time.
I verified that the entity was pointing at the correct database.
I then deleted the table from the .edmx file and added it again.
Problem solved.
Check your model & database both should be defined accordingly....
public Int32? X { get; set; } ----> Nullable
Accordingly in DB 'X' should be Nullable = True
or
public Int32 X { get; set; } ----> not Nullable
Accordingly in DB 'X' should be Nullable = false
In my case in created view in DB column that I select that contains null value I change that value by this select statement:
Before my change
select
..., GroupUuId , ..
after my change
select
..., ISNULL(GroupUuId, 0), ...
Sorry for my bad English
This may happen when the database table allows NULL and there are records that have a null value and you try to read this record with EF and the mapping class does not allow a null value.
The solution is either change the database table so that it does not allow null or change your class to allow null.
For me the following Steps corrected the Error:
Remove the 'X'-Property from the 'Y'-Table
Save EDMX
build Database from Model
compile
Add the 'X'-Property to 'Y'-Table again (with non-nullable and int16)
Save EDMX
build Database from Model
compile
to fix the error
Error 3031: Problem in mapping fragments starting at line 4049:Non-nullable column "X" in table "Y" is mapped to a nullable entity property.
open your EDMX file with and xml editor and lookup you table in
edmx:StorageModels
find the propertie which gives the error and set or add
Nullable="false" >> to Nullable="true"
save the edmx, open it in visual studio and build it. problem solved
Got same error but different context, tried to join tables using linq where for one of the tables in database, a non-null column had a null value inserted, updated the value to default and the issue is fixed.