- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
UnitOfWork2 problems
Joined: 01-Dec-2005
Cant figure out why my Insert doesnt work but the Delete works fine with this UnitOfWork2 object.
private void dgHier_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
uow = InitializeUnitOfWork2();
uow.AddForDelete((HierEntity)e.Row.DataBoundItem);
}
// This will send all changes to the db (Insert, Update, Delete)
private void saveToolStripButton_Click(object sender, EventArgs e)
{
uow = InitializeUnitOfWork2();
uow.AddCollectionForSave(hierColl); // hierColl is an EntityCollection of HierEntity entities. This is bound to the DataGridView
uow.Commit(new DataAccessAdapter(), true);
uow = null;
}
private UnitOfWork2 InitializeUnitOfWork2()
{
if (uow == null)
{
uow = new UnitOfWork2();
}
return uow;
}
I get error: The insert query doesn't contain any fields.
What's the version / build of the runtime libraries (rmb on ormsupport classes dl -> properties -> version tab) ?
No fields in a query happens when the entity is marked dirty but there are no fields changed, OR that the entity is NEW and it has an identity field as PK and there aren't any fields set.
Joined: 01-Dec-2005
Below is the Stack trace and the code that fills the hierColl. When I step into the code I can see that the UnitOfWork2 object's (uow) entititesToInsert=0. But looking the hierColl it contains 1 DirtyEntity of type HierEntity with the IsNew flag set to True. I have had no problems when inserting a new row in this grid previously without using uow when I was just using SaveEntityCollection.
Assembly info SD.LLBLGen.Pro.ORMSupportClasses.NET20: (Version: 1.0.2005.1)
private void FetchData()
{
DataAccessAdapter adapter = new DataAccessAdapter(true);
hierColl = new EntityCollection(new HierEntityFactory());
...
...
adapter.FetchEntityCollection(hierColl, null);
...
adapter.CloseConnection();
// Allow Deletes for the Grid bound collection
hierColl.AllowRemove = true;
}
My Hier table:
CREATE TABLE [dbo].[Hier](
[HierGUID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Hier_HierGUID_1] DEFAULT (newsequentialid()),
[ParentHierGUID] [uniqueidentifier] NULL,
[HierTypeGUID] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[NodeDescriptor] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[CompleteDescription] [nvarchar](1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[DateCreated] [datetime] NOT NULL CONSTRAINT [DF_Hier_DateCreated_2] DEFAULT (getdate()),
CONSTRAINT [PK_Hier] PRIMARY KEY CLUSTERED
(
[HierGUID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Hier] WITH CHECK ADD CONSTRAINT [FK_Hier_HierType] FOREIGN KEY([HierTypeGUID])
REFERENCES [dbo].[HierType] ([HierTypeGUID])
SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryConstructionException was unhandled Message="The insert query doesn't contain any fields." Source="SD.LLBLGen.Pro.DQE.SqlServer.NET20" StackTrace: at SD.LLBLGen.Pro.DQE.SqlServer.DynamicQueryEngine.CreateSingleTargetInsertDQ(IEntityFieldCore[] fields, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, Hashtable& fieldToParameter) at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateInsertDQ(IEntityFieldCore[] fields, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse) at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.CreateInsertDQ(IEntity2 entityToSave, IFieldPersistenceInfo[] persistenceInfoObjects) at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.PersistQueue(ArrayList queueToPersist, Boolean insertActions) at SD.LLBLGen.Pro.ORMSupportClasses.UnitOfWork2.Commit(IDataAccessAdapter adapterToUse, Boolean autoCommit) at SD.LLBLGen.Pro.ORMSupportClasses.UnitOfWork2.Commit(IDataAccessAdapter adapterToUse) at TempWorks.xR1.Configuration.HierSetup.saveToolStripButton_Click(Object sender, EventArgs e) in D:\Visual Studio Solutions\TempWorks.xR1\Configuration\HierSetup.cs:line 86 at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e) at System.Windows.Forms.ToolStripButton.OnClick(EventArgs e) at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e) at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e) at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met) at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met) at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ScrollableControl.WndProc(Message& m) at System.Windows.Forms.ToolStrip.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(Int32 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 TempWorks.xR1.Configuration.Program.Main() in D:\Visual Studio Solutions\TempWorks.xR1\Configuration\Program.cs:line 35 at System.AppDomain.nExecuteAssembly(Assembly 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) at System.Threading.ThreadHelper.ThreadStart()
Joined: 01-Dec-2005
No fields in a query happens when the entity is marked dirty but there are no fields changed, OR that the entity is NEW and it has an identity field as PK and there aren't any fields set.
My PK is a Guid type and I dont display that in the grid but I let the SQL Server default (newsequentialid()) put the value in the new row.
Arif wrote:
No fields in a query happens when the entity is marked dirty but there are no fields changed, OR that the entity is NEW and it has an identity field as PK and there aren't any fields set.
My PK is a Guid type and I dont display that in the grid but I let the SQL Server default (newsequentialid()) put the value in the new row.
newsequentialid() isn't supported yet. Set the GUID manually in .NET code with Guid.NewGuid().
The newsequentialid() isn't supported yet because the value it generates isn't retrievable with the current runtime libraries code structure, it requires a change in the code structure to be able to retrieve the value produced by newsequentialid(). This will be supported in v2.0 of LLBLGen Pro.
SaveEntityCollection uses the same code as UnitOfWork2.Commit(): both calculate a queue first and then persist the queue using the same routine.
Joined: 01-Dec-2005
Hi Otis,
Actually, I don't think the newsequentialid() is the problem here. I replaced the UnitOfWork2 code below with SaveEntityCollection & it does insert the new row in the db. (The grid, etc remains the same and that field is not displayed/assigned)
private void saveToolStripButton_Click(object sender, EventArgs e)
{
DataAccessAdapter adapter = new DataAccessAdapter();
//uow = InitializeUnitOfWork2();
//uow.AddCollectionForSave(hierColl);
//uow.Commit(adapter, true);
//uow = null;
adapter.SaveEntityCollection(hierColl);
}
There must be something wrong in my code for UOW but I cant figure it out.
Joined: 01-Dec-2005
One thing I notice is that the EntityCollection has one HierEntity object in its DirtyEntities collection (since I am inserting only one row in this example). Yet, watching the value of uow (when the error occurs), it has 2 HierEntity objects within its uow._entitiesToInsert collection. The last item in that is just a blank HierEntity object.
Arif wrote:
One thing I notice is that the EntityCollection has one HierEntity object in its DirtyEntities collection (since I am inserting only one row in this example). Yet, watching the value of uow (when the error occurs), it has 2 HierEntity objects within its uow._entitiesToInsert collection. The last item in that is just a blank HierEntity object.
And that last one is the problem. The UoW queue construction code doesn't filter on non-dirty, new entities which aren't in a hierarchy, SaveEntityCollection does.
I'll add the filter code to the UoW as well, as it should be there (I just noticed that it wasn't there when I compared the two routines)
As a workaround for now, you should only add entities to the UoW which you want to save, not every entity created up front.
This filtering is only done in non-recursive collection saves, as the entity then will never get 'dirty' later on through FK syncs as the save is non-recursive. SaveEntityCollection() and AddCollectionForSave() are non-recursive by default.
Joined: 01-Dec-2005
Thank you.
Ok, I made the changes to my Commit button's event handler (Below). But now I run into another problem. The below code works fine EXCEPT when I mix an Insert & Delete into the same UOW. If I just have all Inserts or all Deletes in a UOW it works but if I have both I get an ORMConcurrencyException (stack trace below) and the Delete statement generated is wrong (also below).
private void saveToolStripButton_Click(object sender, EventArgs e)
{
DataAccessAdapter adapter = new DataAccessAdapter();
uow = InitializeUnitOfWork2();
//uow.AddCollectionForSave(hierColl);
for (int i = 0; i<hierColl.DirtyEntities.Count; i++)
{
uow.AddForSave((HierEntity)hierColl.DirtyEntities[i]);
}
uow.Commit(adapter, true);
uow = null;
//adapter.SaveEntityCollection(hierColl);
}
private void dgHier_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
uow = InitializeUnitOfWork2();
uow.AddForDelete((HierEntity)e.Row.DataBoundItem);
}
Statements from Profiler when mixing Insert & Delete in one UOW. Insert statement appears correct but Delete doesnt have the PK value correct for row to delete
exec sp_executesql N'INSERT INTO [myDB].[dbo].[Hier] ([ParentHierGUID], [HierTypeGUID], [Name]) VALUES (@ParentHierGuid, @HierTypeGuid, @Name)',N'@ParentHierGuid
uniqueidentifier,@HierTypeGuid uniqueidentifier,@Name
nvarchar(50)',@ParentHierGuid='DB850937-F366-DA11-819D-001143DC2454', @HierTypeGuid='38E780EE-5365-DA11-819D-001143DC2454',@Name=N'a0'
exec sp_executesql N'DELETE FROM [myDB].[dbo].[Hier] WHERE ( [myDB].[dbo].[Hier].[HierGUID] = @HierGuid1)',N'@HierGuid1
uniqueidentifier',@HierGuid1='00000000-0000-0000-0000-000000000000'
Stack trace for error
SD.LLBLGen.Pro.ORMSupportClasses.ORMConcurrencyException was unhandled Message="During the commit of the UnitOfWork class, the delete action on an entity failed. The entity which failed is enclosed." Source="SD.LLBLGen.Pro.ORMSupportClasses.NET20" StackTrace: at SD.LLBLGen.Pro.ORMSupportClasses.UnitOfWork2.Commit(IDataAccessAdapter adapterToUse, Boolean autoCommit) at TempWorks.xR1.Configuration.HierSetup.saveToolStripButton_Click(Object sender, EventArgs e) in D:\Visual Studio Solutions\TempWorks.xR1\Configuration\HierSetup.cs:line 92 at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e) at System.Windows.Forms.ToolStripButton.OnClick(EventArgs e) at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e) at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e) at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met) at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met) at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ScrollableControl.WndProc(Message& m) at System.Windows.Forms.ToolStrip.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(Int32 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 TempWorks.xR1.Configuration.Program.Main() in D:\Visual Studio Solutions\TempWorks.xR1\Configuration\Program.cs:line 35 at System.AppDomain.nExecuteAssembly(Assembly 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) at System.Threading.ThreadHelper.ThreadStart()