简体   繁体   中英

Why won't SubSonic ActiveRecord update my data?

I am playing around with SubSonic 3 ActiveRecord. I have a table called Users and I have the following fields in a MySQL database:

CREATE TABLE `users` (
  `ID` int(10) NOT NULL auto_increment,
  `Username` varchar(50) NOT NULL,
  `FirstName` varchar(50) default NULL,
  `LastName` varchar(50) default NULL,
  `EmailAddress` varchar(100) default NULL,
  `OfficePhone` varchar(25) default NULL,
  `MobilePhone` varchar(25) default NULL,
  `TimeZone` varchar(25) default NULL,
  `LastLogin` datetime default NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1  

I can read from the table with no problems. I can add new records with no problems but I can not update existing records for some reason. I have stepped through the code and the editUser object has the correct data in it.

[AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(FormCollection result)
    {
        var editUser = ServiceDesk.Data.User.SingleOrDefault(x => x.ID == Convert.ToInt32(result["ID"]));
        UpdateModel(editUser);
        editUser.Save();
        return RedirectToAction("Index", "Home");
    }

Here is the error I'm getting:

Server Error in '/' Application.

The given key was not present in the dictionary.

Description: An unhandled exception occurred during the execution of the current web     request. Please review the stack trace for more information about the error and where it     originated in the code. 

Exception Details: System.Collections.Generic.KeyNotFoundException: The given key was     not present in the dictionary.

Source Error: 

Line 1423:            
Line 1424:            if(this._dirtyColumns.Count>0)
Line 1425:                _repo.Update(this,provider);
Line 1426:            OnSaved();
Line 1427:       }

Source File: D:\Users\Mike\Documents\Visual Studio    2008\Projects\dolphin\src\ServiceDesk.Web\Models\_Generated\ActiveRecord.cs    Line:     1425 

Can anyone offer some assistance?

Here is the stack trace: [KeyNotFoundException: The given key was not present in the dictionary.] System.ThrowHelper.ThrowKeyNotFoundException() +28 System.Collections.Generic.Dictionary 2.get_Item(TKey key) +7456284 SubSonic.Extensions.Database.ToUpdateQuery(T item, IDataProvider provider) +642 SubSonic.Repository.SubSonicRepository 1.Update(T item, IDataProvider provider) +113 ServiceDesk.Data.User.Update(IDataProvider provider) in D:\\Users\\Mike\\Documents\\Visual Studio 2008\\Projects\\dolphin\\src\\ServiceDesk.Web\\Models_Generated\\ActiveRecord.cs:1425 ServiceDesk.Data.User.Save(IDataProvider provider) in D:\\Users\\Mike\\Documents\\Visual Studio 2008\\Projects\\dolphin\\src\\ServiceDesk.Web\\Models_Generated\\ActiveRecord.cs:1461 ServiceDesk.Data.User.Save() in D:\\Users\\Mike\\Documents\\Visual Studio 2008\\Projects\\dolphin\\src\\ServiceDesk.Web\\Models_Generated\\ActiveRecord.cs:1452 ServiceDesk.Web.Controllers.SettingController.Edit(FormCollection result) in D:\\Users\\Mike\\Documents\\Visual Studio 2008\\Pr ojects\\dolphin\\src\\ServiceDesk.Web\\Controllers\\SettingController.cs:48 lambda_method(ExecutionScope , ControllerBase , Object[] ) +140 System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary 2 parameters) +178 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary 2 parameters) +24 System.Web.Mvc.<>c__DisplayClassa.b__7() +52 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func 1 continuation) +254 System.Web.Mvc.<>c__DisplayClassc.<InvokeActionMethodWithFilters>b__9() +19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList 1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +192 System.Web.Mvc.ControllerActionIn voker.InvokeAction(ControllerContext controllerContext, String actionName) +399 System.Web.Mvc.Controller.ExecuteCore() +126 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +27 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7 System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) +151 System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) +57 System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) +7 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75

Looks like the problem is in this code:

public static ISqlQuery ToUpdateQuery<T>(this T item, IDataProvider provider) where T : class, new()
    {
        Type type = typeof(T);
        var settings = item.ToDictionary();

        ITable tbl = provider.FindOrCreateTable<T>();

        Update<T> query = new Update<T>(tbl.Provider);
        if(item is IActiveRecord)
        {
            var ar = item as IActiveRecord;
            foreach(var dirty in ar.GetDirtyColumns())
            {
                if(!dirty.IsPrimaryKey && !dirty.IsReadOnly)
                    query.Set(dirty.Name).EqualTo(settings[dirty.Name]);
            }
        }  

dirty.Name = "FirstName" but settings["FirstName"] doesn't exist, however settings["Firstname"] does exist. My columns in the db are named like "FirstName", "LastName", etc but subsonic ActiveRecord template named the object fields like "Firstname" and "Lastname"

My first guess is that TimeZone is a reserved word in C# (System.TimeZone) and while this really shouldn't matter - it's the first thing I can think of. The Key error could be that SubSonic is trying to find a property with the name "TimeZone" that has been renamed - check your Structs.cs class/User table to see if that's the case.

If so please file a bug. If not - a stack trace would help.

I'm also getting this exception in the 3.0.0.4 release when trying to update a row. I have previously used SubSonic 1.0 but this is my first attempt at using v3 - so I may have overlooked something in the process..

The quickest workaround I found is to simply delete the row, then insert it straight after.. This is probably less efficient than just updating - but may be acceptable within contexts that aren't performance critical.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM