views:

55

answers:

1

I'm going nuts over what should be a very simple situation. In an ASP.NET MVC 2 app (not that I think this matters), I have an edit action which takes a very small entity and makes a few changes. The key portion (outside of error handling/security) looks like this:

Todo t = Repository.GetTodoByID(todoID);

UpdateModel(t);
Repository.Save();

Todo is the very simple, small entity with the following fields: ID (primary key), FolderID (foreign key), PercentComplete, TodoText, IsDeleted and SaleEffortID (foreign key). Each of these obviously corresponds to a field in the database.

When UpdateModel(t) is called, t does get correctly updated for all fields which have changed.

When Repository.Save() is called, by the time the SQL is written out, FolderID reverts back to its original value. The complete code to Repository.Save():

public void Save()
{
    myDataContext.SubmitChanges();
}

myDataContext is an instance of the DataContext class created by the LINQ-to-SQL designer. Nothing custom has been done to this aside from adding some common interfaces to some of the entities.

I've validated that the FolderID is getting lost before the call to Repository.Save() by logging out the generated SQL:

UPDATE [Todo].[TD_TODO]
SET 
    [TD_PercentComplete] = @p4, 
    [TD_TodoText] = @p5, 
    [TD_IsDeleted] = @p6
WHERE 
    ([TD_ID] = @p0) AND 
    ([TD_TDF_ID] = @p1) AND /* Folder ID */
    ([TD_PercentComplete] = @p2) AND 
    ([TD_TodoText] = @p3) AND 
    (NOT ([TD_IsDeleted] = 1)) AND 
    ([TD_SE_ID] IS NULL) /* SaleEffort ID */
-- @p0: Input BigInt (Size = -1; Prec = 0; Scale = 0) [5]
-- @p1: Input BigInt (Size = -1; Prec = 0; Scale = 0) [1] /* this SHOULD be 4 and in the update list */
-- @p2: Input TinyInt (Size = -1; Prec = 0; Scale = 0) [90]
-- @p3: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [changing text]
-- @p4: Input TinyInt (Size = -1; Prec = 0; Scale = 0) [0]
-- @p5: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [changing text foo]
-- @p6: Input Bit (Size = -1; Prec = 0; Scale = 0) [True]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 4.0.30319.1

So somewhere between UpdateModel(t) (where I've validated in the debugger that FolderID updated) and the output of this SQL, the FolderID reverts. The other fields all save. (Well, OK, I haven't validated SaleEffortID yet, because that subsystem isn't really ready yet, but everything else saves.)

I've exhausted my own means of research on this: Does anyone know of conditions which would cause a partial entity reset (EG, something to do with long foreign keys?), and/or how to work around this?

+1  A: 

The only thing I can think of, is if something forces the datacontext to load the related entity (which would be Folder in this case, I think) before the call to UpdateModel.

If you try to change FolderID after the Folder entity has been loaded, it will silently fail and retain it's old value. This can be kindof annoying. I don't know if this is the case here, however as you appear positive that the values are updated by the UpdateModel call.

Normally, if the foreign key is changed before the datacontext tries to load the related entity, then the correct entity will be loaded (the one with the new key), but somehow, maybe something happens that triggers a mysterious behaviour in this case - I know it's not much to go on, but I would definitely expect this to have something to do with deferred loading of the related entity.

AHM
I think you're onto something; the one thing I *wasn't* checking in the debugger was the actual `TodoFolder` property -- and yes, I'm changing that FK after the entity pointed to loads. I'll work with that and see how far it gets me.
John Rudy
You've earned the bounty. That was it; thank you! (That was *killing* me, too!) (Unfortunately, SO won't let me give you the bounty yet. 22 hours.)
John Rudy
Great! I'm glad I could help you :-)
AHM
Enjoy the rep bump. :)
John Rudy