Can't upadte a simple record in the database

Discussion of open issues, suggestions and bugs regarding LinqConnect – Devart's LINQ to SQL compatible ORM
Post Reply
shaharw18
Posts: 43
Joined: Thu 20 Oct 2011 20:07

Can't upadte a simple record in the database

Post by shaharw18 » Sun 06 Nov 2011 13:34

hi,

I'm trying to update a record using dotconnect (or is it linqconnect)...
anyway these are the lines i'm using:

ent.Clips.Attach(updClip);
ent.SubmitChanges();

it seems the database does not get updated.


thanks
Shahar.

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Mon 07 Nov 2011 09:12

Attaching an entity object to the context enables change tracking for this object. However, as data context has no information concerning the actual status of the attached entity, it supposes that the entity is up-to-date unless you specify that it is not.

To inform the context that an attached entity should be updated, you can, e.g., attach it together with its original state:

Code: Select all

ent.Clips.Attach(updClip, oldClip);
ent.SubmitChanges();
Please tell us if this helps.

shaharw18
Posts: 43
Joined: Thu 20 Oct 2011 20:07

Post by shaharw18 » Tue 08 Nov 2011 00:08

thank you for reply.

ent.Clips.Attach(updClip, oldClip);
ent.SubmitChanges();

updClip is the record I would like to update including the modified field in it.
what would be oldClip?
the entire table ?

I did'nt do a SELECT on the table only a straight update.

what is oldClip?
so you have a sample for your own code lines doing these task?

thanks



Shahar.

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Tue 08 Nov 2011 15:43

In the sample, 'oldClip' is an entity object with the same fields as 'updClip', except the fields being updated. For example,

Code: Select all

MyEntity oldEntity = new MyEntity() { Id = 10, Column1 = "C1", ColumnToBeUpdated = "Old Value", ... };
MyEntity updEntity = new MyEntity() { Id = 10, Column1 = "C1", ColumnToBeUpdated = "New Value", ... };
ent.MyEntities.Attach(updEntity, oldEntity);
ent.SubmitChanges();
Please tell us if this helps.

shaharw18
Posts: 43
Joined: Thu 20 Oct 2011 20:07

Post by shaharw18 » Wed 09 Nov 2011 07:41

Hi.

Here's the new code I've wrote.
I'm getting now an error message: Row not found or changed.

as you can see I've created a demi clipOrg object which is exactly the same one as "clip". except for a changed field as you wrote I need to have.

--------------------------------------------------------------------------

Db.Clip clip = new Db.Clip();
Db.Clip clipOrg = new Db.Clip();

clip.Id = Convert.ToInt32(id);
clip.Title = title.Text;
clip.Path = path.Text;
clip.Tags = tags.Text;

clipOrg = clip;
clipOrg.Title = "";

ent.Clips.Attach(clip,clipOrg);
clip.Title = title.Text;

ent.SubmitChanges();

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Fri 11 Nov 2011 18:03

Entity classes are reference types, thus in your sample 'clip' and 'clipOrg' are the same object. Thus, when you attach it like

Code: Select all

ent.Clips.Attach(clip,clipOrg);
the entity is still marked as unchanged (and its initial state includes 'Title' equal to an empty string).

When updating an entity, LinqConnect checks all its fields by default. In particular, it generates the condition like "Title = '' " in the WHERE part of the update statement. Unless 'Title' is an empty string in the database, this update will fail, leading to the exception you are getting.

To resolve the problem, you can do one of the following:
- make 'clipOrg' a memberwise copy of the 'clip' object (instead of assigning 'clip' to it);
- attach 'clip' and then modify its 'Title':

Code: Select all

ent.Clips.Attach(clip);
clip.Title = title.Text;
ent.SubmitChanges();
Feel free to contact us if anything is unclear.

shaharw18
Posts: 43
Joined: Thu 20 Oct 2011 20:07

Post by shaharw18 » Fri 11 Nov 2011 19:54

thanks for the reply.
what you've wrote is exactly what I"ve done except for the membership.

I'm not familiar with that definition. so, please help.
how do I make clipOrg a membership of clip?

thanks
shahar.

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Mon 14 Nov 2011 13:52

Memberwise copy is a new object with the fields equal to the ones of the original object. To create it, you should construct a new Clip object and assign the values from the 'clip' instance to its fields:

Code: Select all

Db.Clip clip = new Db.Clip(); 
Db.Clip clipOrg = new Db.Clip();

[initialize the 'clip' object]

clipOrg.Id = clip.Id;
clipOrg.Title = clip.Title;
clipOrg.Path = clip.Path;
clipOrg.Tags = clip.Tags;
[copy other properties (if any) from 'clip']
Otherwise, you can attach the 'clip' object having 'old' values, and after that set the 'new' values as shown in my previous post. In this case, the context will track these changes and automatically update the corresponding row in the database on SubmitChanges().

shaharw18
Posts: 43
Joined: Thu 20 Oct 2011 20:07

Post by shaharw18 » Mon 14 Nov 2011 18:18

Hi,

I found the solution which suits me.

var clip = ent.Clips.Single(c => c.Id == Convert.ToInt32(id));
clip.Title = title.Text;
clip.Path = path.Text;
clip.Tags = tags.Text;
ent.SubmitChanges();

I don't like the idea that before each update the application is going to query the database, but it seems like LINQ doesn't have any kind of a reasonable staight through query approach. the solution above, is good enough for me.

thanks for the help.

Shahar.

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Tue 15 Nov 2011 15:04

Glad to see that the problem was resolved.

LinqConnect does provide the possibility of updating an entity without querying for it first. However, it is necessary to pass the 'old' data of the row being updated to the context to create the proper update statement. Or, it is possible to set the Update Check property of all entity fields to 'Never', in which case the update statement will check for the primary key value only.

However, querying for the entity before updating it is in some sense safer, as this approach reduces the probability of using stale data in update checks.

shaharw18
Posts: 43
Joined: Thu 20 Oct 2011 20:07

Post by shaharw18 » Tue 15 Nov 2011 18:05

I would be happy if you will write down a simple example for an update.
without querying the database first. it's difficult for me to understand the reason for why they did what you described at the first place.
I'd thought that after simple SQL queries I used to do, the LINQ technology won't create "new headaques".

shahar.

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Wed 16 Nov 2011 15:48

I've sent you a sample project, please check that the letter was not blocked by your mail filter.

In the sample, a detached entity is updated in the following ways:
- by attaching both entity and its original state to the context before updating;
- by attaching the entity first, and then modifying it so that the context can track the changes;
- by attaching the entity as modified; this way needs to set all update check rules to 'Never'.

Feel free to contact us if anything is unclear.

Post Reply