Problem saving a new entity with new child collection

Posts   
 
    
Meteor
User
Posts: 67
Joined: 06-Apr-2007
# Posted on: 23-Mar-2009 22:51:58   

I'm using v2.6, adapter, on an SQLExpress 2008 database with c# .Net 3.5 General2008 presets.

I'm starting to run into some strange problems I've never experienced with LLBLGen before.

In my windows forms application, I have a dataGridView bound to a BindingSource control containing an LLBLGen collection of 'Route' entities. To allow the user to add a new Route, I use 'Addnew' to obtain a new Route item, and pass this to a pop-up form. Within the popup form I allow them to add to the child collection of 'Stop' entities - by creating the linking entities, 'RouteStop'. When they close the dialog, if the close action was DialogResult.Ok, I attempt to save the entity and call 'EndEdit()' on the BindingSource. 'Route' has a m:n relationship with 'Stop' in that one route can have many stops and each stop can belong to multiple routes. The 'RouteStops' table is the linking table for this and its primary key is a combination of route_fk and stop_fk, which are both mapped to their respective key fields in the route and stop tables. The stops that I'm trying to add to the new route already exist. The route table's key column is set to be 'identity' (int) with autoincrement. When I create the new Route entity, the 'key' is 0, and the route_fk for all the new routestop records is also 0.

When attempting to save the route entity, using this code


public static bool Save(IEntity2 ent)
        {
            bool result = false;            
            using (DataAccessAdapter adapter = new DataAccessAdapter(Utils.DBConnection))
            {
                result = adapter.SaveEntity(ent, true);
            }
            return result;
        }

I get the following error:

{"An exception was caught during the execution of an action query: Cannot insert the value NULL into column 'route_FK', table 'pis_db.dbo.routestops'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception."}

The QueryExecuted is:


    Query: INSERT INTO [pis_db].[dbo].[routestops] ([stop_FK], [stop_order], [active])  VALUES (@StopFk, @StopOrder, @Active)
    Parameter: @StopFk : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 14.
    Parameter: @StopOrder : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 0.
    Parameter: @Active : Boolean. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: False.

Why isn't LLBLGen putting in the Route_Fk? RouteStops has 5 fields: route_fk (PK, FK, int, not null), stop_fk(PK, FK, int, not null), departure_time (real, null), stop_order(int, null), and active(bit, not null).

Meteor
User
Posts: 67
Joined: 06-Apr-2007
# Posted on: 24-Mar-2009 00:07:48   

Although I have tried regenerating the projects earlier (over the top of the existing ones), I just tried deleting the old projects and regenerating them - and it's working.

I suspect that sometimes LLBLGen leaves code from earlier builds, which gets mixed in with the latest code and causes problems. From now on, I think I'll delete the old projects before regenerating new ones. Maybe this was introducing some of the weirdness I've been noticing of late. We've been making quite a few changes to the database schema and regenerating the LLBL projects each time.

Have you heard any other reports of this behaviour?

Meteor
User
Posts: 67
Joined: 06-Apr-2007
# Posted on: 24-Mar-2009 03:29:02   

Ignore that. Back to square one. Error as per originally stated.

Now all I'm trying to do is to save an existing Route.

I have enabled tracing on that, but all I see in the output window is the following:


Method Enter: DataAccessAdapterBase.SaveEntity(4)
Method Enter: DataAccessAdapterBase.DetermineActionQueues(7)
Method Exit: DataAccessAdapterBase.DetermineActionQueues(7)
Method Enter: DataAccessAdapterBase.StartTransaction
Method Enter: DataAccessAdapterBase.OpenConnection
Method Exit: DataAccessAdapterBase.OpenConnection
Method Exit: DataAccessAdapterBase.StartTransaction
Method Enter: DataAccessAdapterBase.PersistQueue
Method Enter: DataAccessAdapterBase.ExecuteActionQuery
Method Enter: DataAccessAdapterBase.OpenConnection
Method Exit: DataAccessAdapterBase.OpenConnection
Method Exit: DataAccessAdapterBase.ExecuteActionQuery
Method Enter: DataAccessAdapterBase.Rollback
Method Exit: DataAccessAdapterBase.Rollback
A first chance exception of type 'SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryExecutionException' occurred in SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll

If I change the recurse parameter of the save call to 'false', I don't get the error - but then none of the records in the linking table get saved either.


SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryExecutionException was unhandled by user code
  Message="An exception was caught during the execution of an action query: Cannot insert the value NULL into column 'name', table 'pis_db.dbo.route'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception."
  Source="SD.LLBLGen.Pro.ORMSupportClasses.NET20"
  RuntimeBuild="01162009"
  RuntimeVersion="2.6.0.0"
  QueryExecuted="\r\n\tQuery: INSERT INTO [pis_db].[dbo].[route] ([path_FK])  VALUES (@PathFk);SELECT @Key=SCOPE_IDENTITY()\r\n\tParameter: @Key : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Output. Value: <undefined value>.\r\n\tParameter: @PathFk : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 20.\r\n"
  StackTrace:
       at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute()
       at SD.LLBLGen.Pro.ORMSupportClasses.BatchActionQuery.Execute()
       at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.ExecuteActionQuery(IActionQuery queryToExecute)
       at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.PersistQueue(List`1 queueToPersist, Boolean insertActions, Int32& totalAmountSaved)
       at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.SaveEntity(IEntity2 entityToSave, Boolean refetchAfterSave, IPredicateExpression updateRestriction, Boolean recurse)
       at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.SaveEntity(IEntity2 entityToSave, Boolean refetchAfterSave)
       at BLL.Save.General.Save(IEntity2 ent)
       at frmMainForm.btnEditRoute_Click(Object sender, EventArgs e)
       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.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
  InnerException: System.Data.SqlClient.SqlException
       Message="Cannot insert the value NULL into column 'name', table 'pis_db.dbo.route'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."
       Source=".Net SqlClient Data Provider"
       ErrorCode=-2146232060
       Class=16
       LineNumber=1
       Number=515
       Procedure=""
       Server="SOFTWARE11\\SQLEXPRESS2008"
       State=2
       StackTrace:
            at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
            at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
            at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
            at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
            at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
            at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
            at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
            at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
            at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
            at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute()
       InnerException: 


I can't understand why it's trying to insert anything into the Route table - this is an existing record. The entity IsNew flag is false. The related collection of routestops is unchanged.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 24-Mar-2009 11:01:03   

A side note:

I suspect that sometimes LLBLGen leaves code from earlier builds, which gets mixed in with the latest code and causes problems. From now on, I think I'll delete the old projects before regenerating new ones. Maybe this was introducing some of the weirdness I've been noticing of late.

You can automate this by setting the CleanUpVsNetProjects project property to true.

docs wrote:

**CleanUpVsNetProjects **When set to true, the VS.NET project file task performer will first remove all file references for files from an existing VS.NET project file, before adding the files generated. For VS.NET 2005 projects, it will remove all files generated by LLBLGen Pro, as these are marked with a Generator tag.

Note: Use with care as an old VS.NET project may contain references to files which aren't marked with LLBLGen Pro specific XML elements/attributes, so all file references are removed, which thus also means that references to files you've added yourself to the project are removed as well, which forces you to re-add the references to those files to the VS.NET project manually. Projects created for VS.NET 2005 and with LLBLGen Pro v2.0 or higher do have the files marked as LLBLGen Pro generated and it's safe to use this setting with these projects

Back to your problem: I'm really confused about what you are trying to do. Reading this:

I can't understand why it's trying to insert anything into the Route table - this is an existing record. The entity IsNew flag is false. The related collection of routestops is unchanged.

I thought you were trying to insert a new route as you said here:

In my windows forms application, I have a dataGridView bound to a BindingSource control containing an LLBLGen collection of 'Route' entities. To allow the user to add a new Route, I use 'Addnew' to obtain a new Route item, and pass this to a pop-up form

Meteor
User
Posts: 67
Joined: 06-Apr-2007
# Posted on: 24-Mar-2009 12:28:21   

Yeah sorry, in my second entry, I was getting the error even trying to edit an existing route. So I don't know why the insert statement is there.

You have to imagine me, sitting in front of a computer, head in hands, for nearly 8 hours, trying to figure out what's going on, while I should be moving ahead with the project. Instead of moving forward, I'm getting a series of errors relating to saving the entity. Yes, I started off with a new route, then, later ended up trying to save an existing route. Frustratingly, there's no-one awake on your side of the world at the time I'm trying to solve this, so you will get some slightly disparate posts. All I have is my project manager asking what's going on and me trying to explain that my ORM is doing some strange things wink

So if you have any suggestions, I'd be glad to hear them.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 24-Mar-2009 12:53:32   

I'll look into what you've posted and get back to you shortly. Hang in there, Meteor wink

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 24-Mar-2009 13:15:51   

Meteor wrote:

I'm using v2.6, adapter, on an SQLExpress 2008 database with c# .Net 3.5 General2008 presets.

I'm starting to run into some strange problems I've never experienced with LLBLGen before.

In my windows forms application, I have a dataGridView bound to a BindingSource control containing an LLBLGen collection of 'Route' entities. To allow the user to add a new Route, I use 'Addnew' to obtain a new Route item, and pass this to a pop-up form.

Keep in mind that 'AddNew' is for databinding purposes, so if you want to add a new entity in a collection, if AddNew somehow does weird things, it might be that some EndEdit is missing and instead the added new entity is removed again, and therefore go the safe route: create the entity manually, and add it manually to the collection.

The problem with AddNew is that if the collection is bound to a control, AddNew is considered to be called by the control, and if the control calls CancelEdit somewhere, the added entity has to be removed (this is the way things work when in a grid you press ESC twice in a new row, it is removed. Yes, databinding is funny sometimes).

Within the popup form I allow them to add to the child collection of 'Stop' entities - by creating the linking entities, 'RouteStop'. When they close the dialog, if the close action was DialogResult.Ok, I attempt to save the entity and call 'EndEdit()' on the BindingSource. 'Route' has a m:n relationship with 'Stop' in that one route can have many stops and each stop can belong to multiple routes. The 'RouteStops' table is the linking table for this and its primary key is a combination of route_fk and stop_fk, which are both mapped to their respective key fields in the route and stop tables. The stops that I'm trying to add to the new route already exist. The route table's key column is set to be 'identity' (int) with autoincrement. When I create the new Route entity, the 'key' is 0, and the route_fk for all the new routestop records is also 0.

When attempting to save the route entity, using this code


public static bool Save(IEntity2 ent)
        {
            bool result = false;            
            using (DataAccessAdapter adapter = new DataAccessAdapter(Utils.DBConnection))
            {
                result = adapter.SaveEntity(ent, true);
            }
            return result;
        }

I get the following error:

{"An exception was caught during the execution of an action query: Cannot insert the value NULL into column 'route_FK', table 'pis_db.dbo.routestops'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception."}

The QueryExecuted is:


    Query: INSERT INTO [pis_db].[dbo].[routestops] ([stop_FK], [stop_order], [active])  VALUES (@StopFk, @StopOrder, @Active)
    Parameter: @StopFk : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 14.
    Parameter: @StopOrder : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 0.
    Parameter: @Active : Boolean. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: False.

Why isn't LLBLGen putting in the Route_Fk? RouteStops has 5 fields: route_fk (PK, FK, int, not null), stop_fk(PK, FK, int, not null), departure_time (real, null), stop_order(int, null), and active(bit, not null).

You didn't post the correct code. What's important is how do you link the entities together? I.o.w.: Do you set the Route reference in the RouteStop entities to the Route entity instance? if not, the reference is null and won't get a value during inserts.

So if you want to tie two m:n related entities together (here, Stop and Route), do: (pseudocode) RouteStopEntity routeStop = new RouteStopEntity(); routeStop.Stop = new StopEntity(); routeStop.Route = _passedInRouteEntityFromGridView;

after this, all entities are connected.

Also, be sure that you don't hide the FK side of a relation, nor the field mapped onto the relation. Otherwise the field isn't synced.

So please post the code which links the entities together so we can follow what you're doing. Any line of code you omit will not be seen by us so we have to assume it's not there.

I've ignored your other posts, as I think they're either related (caused by the same problem) or have to do with other things and therefore IF they persist, open new threads for these.

Frans Bouma | Lead developer LLBLGen Pro