- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
Issue with saving child entity alongwith parent
Joined: 17-Nov-2011
Hi there, We have issue with saving the child entity alongwith its parent entity.
Product: LLbLGen Pro v3.1 Final Runtime Library: 3.1.11.907 Database: SQL Server 2008 We use .NET 4.0 framework and VB.Net
Entity Relationship : We have the following relationship in our database We have EmpGeneralEntity and its child is EmpServiceEntity and the child of EmpServiceEntity is EmpServiceDetailEntity.
Scenario:
I create a new EmpGeneralEntity and save that entity, then I create a new EmpServiceEntity.Then I create a new EmpServiceDetailEntity and add it to the EmpServiceEntity (newly created one). I want to save the EmpServiceEntity (and its child EmpServiceDetailEntity both together). When I use SaveEntity(serviceEntity), I get the exception
"The value is of type 'System.DBNull' while the field is of type 'System.Int32'"
Stack Trace:
at SD.LLBLGen.Pro.ORMSupportClasses.EntityFieldCore.set_CurrentValue(Object value) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Core\EntityFieldCore.cs:line 1153
at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase2.SyncFKFields(EntitySyncInfo1 syncInfo) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\EntityBase2.cs:line 3289
at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase2.OnEntityAfterSave(Object sender, EventArgs e) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\EntityBase2.cs:line 3230
at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase2.SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore.FlagAsSaved() in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\EntityBase2.cs:line 4501
at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.PersistQueue(List
1 queueToPersist, Boolean insertActions, Int32& totalAmountSaved) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs:line 1426
at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.SaveEntity(IEntity2 entityToSave, Boolean refetchAfterSave, IPredicateExpression updateRestriction, Boolean recurse) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs:line 1312
at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.SaveEntity(IEntity2 entityToSave) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs:line 1137
at Grb.PlugIn.Assist.Presentation.ProfileServiceEdit.Page_Load(Object sender, EventArgs e) in C:\Mywork\RBS\AssistWeb\PlugIn\Assist\Presentation\UISandbox\ProfileServiceEdit.ascx.vb:line 651
The sample code is as follows: Dim employeeGeneralEntity As New Grb.Framework.Business.Lower.EntityClasses.EmpGeneralEntity employeeGeneralEntity.DomainId = 1 employeeGeneralEntity.FirstName = "Nov" employeeGeneralEntity.LastName = "17th" employeeGeneralEntity.Ssn = "545248514" employeeGeneralEntity.DateOfBirth = CDate("1960-01-01") employeeGeneralEntity.CurrentAppointmentDate = CDate("2010-01-01") employeeGeneralEntity.ServiceType = 2 employeeGeneralEntity.RetirementSystem = 2 Dim dataManager As Grb.Framework.Data.Main = m_FrameworkManagers.DataManager Using adapter As New Grb.Framework.Business.Lower.DatabaseSpecific.DataAccessAdapter(dataManager.ConnectionString) adapter.SaveEntity(employeeGeneralEntity) adapter.FetchEntity(employeeGeneralEntity) End Using Dim serviceEntity As New Grb.Framework.Business.Lower.EntityClasses.EmpServiceEntity
serviceEntity.EmpGeneral = employeeGeneralEntity
serviceEntity.DepositPaid = 2
serviceEntity.DepositState = 1
serviceEntity.ServiceType = 2
serviceEntity.FromDate = CDate("2001-01-01")
serviceEntity.ToDate = CDate("2005-01-01")
serviceEntity.RetirementSystem = 2
serviceEntity.IncludesPtOrLwop = 1
Dim serviceDetailsEntity As New Grb.Framework.Business.Lower.EntityClasses.EmpServiceDetailEntity
serviceDetailsEntity.BiweeklyTod = 60
serviceDetailsEntity.FromDate = CDate("2001-01-01")
serviceDetailsEntity.ToDate = CDate("2005-01-01")
serviceDetailsEntity.WorkSchedule = 3
serviceDetailsEntity.PaySchedule = 1
serviceDetailsEntity.PayRate = 0
serviceDetailsEntity.PartTimeActualHours = 2
serviceDetailsEntity.PartTimeType = 2
serviceEntity.EmpServiceDetails.Add(serviceDetailsEntity)
Using adapter As New Grb.Framework.Business.Lower.DatabaseSpecific.DataAccessAdapter(dataManager.ConnectionString)
adapter.SaveEntity(serviceEntity)
End Using
The query that was last executed in the ORMprofiler before the exception occured is : INSERT INTO [OUR_DATABASE].[OUR_SCHEMA].[EMP_SERVICE] ([AGENCY], [CONTRIBUTIONS_REFUNDED], [DEPOSIT_PAID], [DEPOSIT_STATE], [EMPLOYEE_ID], [FROM_DATE], [INCLUDES_PT_OR_LWOP], [NON_CREDITABLE_DAYS], [NON_CREDITABLE_MONTHS], [NON_CREDITABLE_YEARS], [REDEPOSIT_PAID], [REDEPOSIT_STATE], [RETIREMENT_SYSTEM], [SERVICE_TYPE], [TO_DATE], [TOTAL_1999_EARNINGS], [TOTAL_2000_EARNINGS], [TOTAL_POST_2000_EARNINGS], [TOTAL_PRE_1999_EARNINGS], [USERRA_RULES_APPLY]) VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21);SELECT @p7 = SCOPE_IDENTITY()
Observed that @p7 is NULL.
The last query that executed before the exception from SQL Profiler is declare @p9 int set @p9=NULL exec sp_executesql N'INSERT INTO [OUR_DATABASE].[OUR_SCHEMA].[EMP_SERVICE] ([DEPOSIT_BALANCE], [DEPOSIT_BALANCE_DATE], [DEPOSIT_PAID], [DEPOSIT_STATE], [EMPLOYEE_ID], [FROM_DATE], [INCLUDES_PT_OR_LWOP], [RETIREMENT_SYSTEM], [SERVICE_TYPE], [TO_DATE], [TOTAL_1999_EARNINGS], [TOTAL_2000_EARNINGS], [TOTAL_POST_2000_EARNINGS], [TOTAL_PRE_1999_EARNINGS]) VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15) ;SELECT @p7=SCOPE_IDENTITY()',N'@p1 int,@p2 datetime,@p3 int,@p4 int,@p5 int,@p6 datetime,@p7 int output,@p8 int,@p9 int,@p10 int,@p11 datetime,@p12 int,@p13 int,@p14 int,@p15 int',@p1=NULL,@p2=NULL,@p3=2,@p4=1,@p5=37,@p6='2001-01-01 00:00:00',@p7=@p9 output,@p8=1,@p9=2,@p10=2,@p11='2005-01-01 00:00:00',@p12=0,@p13=0,@p14=65780,@p15=0 select @p9
Thanks for your help, Dharini
Hi Dharini,
- Are you setting the [urldescription="SQL Compatibility level"]on you *.config?
My guess is that you have an InsteadOfInsert trigger on the EMP_SERVICE table. If that is the case, then SCOPE_IDENTITY won't work, you should use @@IDENTITY instead. So try the following: - Open your LLBLGen project and go to edit the EmpService entity. - Go to Field Mappings sub-tab. - Select the primary key field. There change it's sequence from SCOPE_IDENTITY to @@IDENTITY. - Regenerate the code and try again.
Additionally I have a couple of comments on your code:
dganesh wrote:
adapter.SaveEntity(employeeGeneralEntity) adapter.FetchEntity(employeeGeneralEntity)
Instead of doing two calls, you can use the overload where you indicate a refetch.
adapter.SaveEntity(employeeGeneralEntity, true, false)
dganesh wrote:
adapter.SaveEntity(serviceEntity)
You are not saving it recursively. So the just added serviceDetailsEntity wont be inserted. So use the save overload:
adapter.SaveEntity(serviceEntity, true, true)
As a matter of fact you can just add your empService to the parent (employeeGeneralEntity) and save the parent recursively. This has one advantage: it uses a transaction internally so the whole operation is atomic.