Problem with DataPortal.FetchChild and _guidID

Problem with DataPortal.FetchChild and _guidID

Old forum URL: forums.lhotka.net/forums/t/10043.aspx


Mark Sulkowski posted on Tuesday, February 08, 2011

I'm evaluating CodeSmith, and I've set up a test project in C# using the SQL AdventureWorks database with generated CSLA business objects.

It looks good, except for one problem. I get an exception thrown due to the existence of this in the generated  code:

private readonly Guid _guidID = Guid.NewGuid();

My approach, and correct me if you think this is a less than ideal approach, is to write a public static method on the List object (SalesOrderDetailList in my example) that in turn calls the generated internal static GetBySalesOrderID method, which in turn uses its generated code to call DataPortal.FetchChild.

Here is the exception:

System.ArgumentException was unhandled
  Message=Expression must be writeable
Parameter name: left
  Source=System.Core
  ParamName=left
  StackTrace:
       at System.Linq.Expressions.Expression.RequiresCanWrite(Expression expression, String paramName)
       at System.Linq.Expressions.Expression.Assign(Expression left, Expression right)
       at Csla.Reflection.DynamicMethodHandlerFactory.CreateFieldSetter(FieldInfo field) in C:\Projekt\CslaSource\Csla\Reflection\DynamicMethodHandlerFactory.cs:line 189
       at Csla.Reflection.DynamicMemberHandle..ctor(FieldInfo info) in C:\Projekt\CslaSource\Csla\Reflection\DynamicMemberHandle.cs:line 44
       at Csla.Core.UndoableHandler.BuildHandlers(Type type) in C:\Projekt\CslaSource\Csla\Core\UndoableHandler.cs:line 55
       at Csla.Core.UndoableHandler.GetCachedFieldHandlers(Type type) in C:\Projekt\CslaSource\Csla\Core\UndoableHandler.cs:line 24
       at Csla.Core.UndoableBase.CopyState(Int32 parentEditLevel) in C:\Projekt\CslaSource\Csla\Core\UndoableBase.cs:line 130
       at Csla.Core.BusinessBase.BeginEdit() in C:\Projekt\CslaSource\Csla\Core\BusinessBase.cs:line 770
       at Csla.Core.BusinessBase.System.ComponentModel.IEditableObject.BeginEdit() in C:\Projekt\CslaSource\Csla\Core\BusinessBase.cs:line 695
       at System.Windows.Forms.CurrencyManager.OnCurrentChanged(EventArgs e)
       at System.Windows.Forms.CurrencyManager.ChangeRecordState(Int32 newPosition, Boolean validating, Boolean endCurrentEdit, Boolean firePositionChange, Boolean pullData)
       at System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e)
       at System.Windows.Forms.BindingSource.OnListChanged(ListChangedEventArgs e)
       at System.Windows.Forms.BindingSource.ResetBindings(Boolean metadataChanged)
       at System.Windows.Forms.BindingSource.SetList(IList list, Boolean metaDataChanged, Boolean applySortAndFilter)
       at System.Windows.Forms.BindingSource.ResetList()
       at System.Windows.Forms.BindingSource.set_DataSource(Object value)
       at AdventureWorksWinFormTest.Form1.btnLoad_Click(Object sender, EventArgs e) in C:\Users\Mark.DIGRAD-MARK8710\Documents\CodeSmith Generator\Templates\CSLA\AdventureWorks3\AdventureWorksWinFormTest\Form1.cs:line 30
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at AdventureWorksWinFormTest.Program.Main() in C:\Users\Mark.DIGRAD-MARK8710\Documents\CodeSmith Generator\Templates\CSLA\AdventureWorks3\AdventureWorksWinFormTest\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

Is there any graceful way of dealing with this problem aside from turning off the undo feature?  (Which I would consider anyway.)

Mark Sulkowski

RockfordLhotka replied on Tuesday, February 08, 2011

If you mark the field as readonly, you also need to mark it as NonSerialized and NotUndoable. It is readonly after all, so the serializers and undo features can't change it after the fact.

This would also mean that you assume responsibility for resetting that value (or avoiding its use) after any serialization or undo operation, because the value becomes meaningless from that point forward.

JonnyBee replied on Tuesday, February 08, 2011

Hi,

I'd just like to add that a field marked as readonly can only be set in the constructor or at declaration as you do. This causes problems for deserializers and undo.

csmith1 replied on Tuesday, October 25, 2011

In CodeSmith I changed the CompositeKeyMethods.cst script. Add the [NonSerialized] and [NotUndoable] attributte to the _guidID parameter.

 

Copyright (c) Marimer LLC