Hi aaron,
I have custom mapping for id and dependent
configuration.CreateMap<DependentEnrolmentRuleCreateInputDto, DependentEnrolmentRule>() .ForMember(d => d.Id, options => options.MapFrom(s => s.Dependent)) .ForMember(u => u.BenefitEnrolmentRule, options => options.Ignore());
[edited]
Hi Aaron,
Thanks for the quick response. **For the first suggestion I get following error **
_Abp.Domain.Uow.AbpDbConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions. ---> Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
In SQL profile, I see only update for BenefitEnrolmentRule. no update statements for DependentEnrolmentRules .
For the second suggestion, I get the following error
An error occurred while updating the entries. See the inner exception for details.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK_DEPENDENTENROLMENTRULE'. Cannot insert duplicate key in object 'dbo.DependentEnrolmentRule'. The duplicate key value is (2, 32, 1).
In the SQL profiler... I see Update for BenefitEnrolmentRule and insert for DependentEnrolmentRules instead of update for DependentEnrolmentRules.
For the third suggestion, no error. But In SQL profile, I see only update for BenefitEnrolmentRule. no update statements for DependentEnrolmentRules .
Thanks
Here is the scenario...
Entities
public partial class **BenefitEnrolmentRule** : FullAuditedEntity, IMustHaveTenant
{
public BenefitEnrolmentRule()
{
DependentEnrolmentRules = new HashSet<DependentEnrolmentRule>();
}
[Key]
[Column(Order = 1)]
public int TenantId { get; set; }
[Key]
[Column("BenefitEnrolmentRuleId", Order = 2)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public override int Id { get; set; }
public bool? TrapLate { get; set; }
[Required]
[Column(TypeName = "char(3)")]
public string GracePeriod { get; set; }
public byte[] RecordVersion { get; set; }
[InverseProperty("BenefitEnrolmentRule")]
public ICollection<DependentEnrolmentRule> DependentEnrolmentRules { get; set; }
}
}
public partial class **DependentEnrolmentRule** : Entity<short>, IMustHaveTenant
{
[Key]
[Column(Order = 1)]
public int TenantId { get; set; }
[Key]
[Column("BenefitEnrolmentRuleId", Order = 2)]
public int BenefitEnrolmentRuleId { get; set; }
[Key]
[Column("Dependent", Order = 3)]
public override short Id { get; set; }
[Column(TypeName = "char(3)")]
public string WaitingPeriod { get; set; }
public short StartDateCalc { get; set; }
public int TerminationAge { get; set; }
public short TerminationDateCalc { get; set; }
[ForeignKey("TenantId,BenefitEnrolmentRuleId")]
[InverseProperty("DependentEnrolmentRules")]
public BenefitEnrolmentRule BenefitEnrolmentRule { get; set; }
}
}
Dto....
public class **BenefitEnrolmentRuleDto**
{
BenefitEnrolmentRuleDto()
{
}
public int TenantId { get; set; }
public int Id { get; set; }
public int BenefitOptionId { get; set; }
public bool? TrapLate { get; set; }
[Required]
public string GracePeriod { get; set; }
public List<DependentEnrolmentRuleCreateInputDto> DependentEnrolmentRules { get; set; }
}
public class **DependentEnrolmentRuleCreateInputDto**
{
DependentEnrolmentRuleCreateInputDto()
{
}
public int TenantId { get; set; }
public int BenefitEnrolmentRuleId { get; set; }
public short Dependent { get; set; }
public string WaitingPeriod { get; set; }
public short StartDateCalc { get; set; }
public int TerminationAge { get; set; }
public short TerminationDateCalc { get; set; }
public bool isEligible { get; set; }
}
Update Method
public async Task UpdateBenefitEnrolmentRule(BenefitEnrolmentRuleDto input)
{
var benefitEnrolmentRule = await _benefitEnrolmentRepository.GetAll()
.Include(e => e.DependentEnrolmentRules)
.Where(e => e.Id == input.Id)
.SingleOrDefaultAsync();
ObjectMapper.Map(input, benefitEnrolmentRule);
await _benefitEnrolmentRepository.UpdateAsync(benefitEnrolmentRule);
}
Data from Angualar client (Dto)
BenefitEnrolmentRules={
"tenantId":2,
"id":32,
"benefitOptionId":0,
"trapLate":true,
"gracePeriod":"04D",
"dependentEnrolmentRules":[
{
"tenantId":2,
"benefitEnrolmentRuleId":32,
"dependent":1,
"waitingPeriod":"02D",
"startDateCalc":1,
"terminationAge":3,
"terminationDateCalc":1,
"isEligible":true
}
]
}
After this statement in the update method var benefitEnrolmentRule = await _benefitEnrolmentRepository.GetAll() .Include(e => e.DependentEnrolmentRules) .Where(e => e.Id == input.Id) .SingleOrDefaultAsync();
After this statement in the update method ObjectMapper.Map(input, benefitEnrolmentRule);
After last statement in update method await _benefitEnrolmentRepository.UpdateAsync(benefitEnrolmentRule);
Checking the profiler,
SQL profiler Statements exec sp_executesql N'SET NOCOUNT ON; UPDATE [BenefitEnrolmentRule] SET [CreationTime] = @p0, [CreatorUserId] = @p1, [DeleterUserId] = @p2, [DeletionTime] = @p3, [GracePeriod] = @p4, [IsDeleted] = @p5, [LastModificationTime] = @p6, [LastModifierUserId] = @p7, [TrapLate] = @p8 WHERE [TenantId] = @p9 AND [BenefitEnrolmentRuleId] = @p10 AND [RecordVersion] = @p11; SELECT [RecordVersion] FROM [BenefitEnrolmentRule] WHERE @@ROWCOUNT = 1 AND [TenantId] = @p9 AND [BenefitEnrolmentRuleId] = @p10; ',N'@p9 int,@p10 int,@p0 datetime2(7),@p1 bigint,@p2 bigint,@p3 datetime2(7),@p4 varchar(3),@p5 bit,@p6 datetime2(7),@p7 bigint,@p11 varbinary(8),@p8 bit',@p9=2,@p10=32,@p0='2018-10-23 15:49:20.5956672',@p1=3,@p2=NULL,@p3=NULL,@p4='04D',@p5=0,@p6='2018-10-23 16:52:05.2990144',@p7=3,@p11=0x000000000000568D,@p8=1
exec sp_executesql N'SET NOCOUNT ON; UPDATE [DependentEnrolmentRule] SET [TerminationAge] = @p0, [WaitingPeriod] = @p1 WHERE [TenantId] = @p2 AND [BenefitEnrolmentRuleId] = @p3 AND [Dependent] = @p4; SELECT @@ROWCOUNT; ',N'@p2 int,@p3 int,@p4 smallint,@p0 int,@p1 varchar(3)',@p2=2,@p3=32,@p4=1,@p0=3,@p1='02D'
exec sp_executesql N'SET NOCOUNT ON; **DELETE FROM [DependentEnrolmentRule] WHERE [TenantId] = @p0 AND [BenefitEnrolmentRuleId] = @p1 AND [Dependent] = @p2; SELECT @@ROWCOUNT; ',N'@p0 int,@p1 int,@p2 smallint',@p0=2,@p1=32,@p2=1 ** Problem: In UpdateAsync method, it is updating the DependentEnrolmentRule and next step is, it is deleting the same record (see sql profile statements). Not sure why.
One reason I was thinking is, In GetAll, BenefitEnrolmentRule object in the DependentEnrolmentRule (which is associated by FK) has data and after mapping with input object,BenefitEnrolmentRule in the DependentEnrolmentRule is null.
Please let me know how to fix this issue. I have posted all the code here. Really appreciate your help.
Thanks
Hi @ismcagdas,
It is a Dto class.. public List<BenefitOptionPlanOutputDto> BenefitOptionPlans { get; set; }
I am calling this from Angular this._classServiceProxy.getBenefitOption(this.benefitOptionId, moment()).subscribe(result => { this.benefitOption = result;
Hi @aaron,
Sorry, don't understand your message. Can you please explain a bit
Thanks
Hi @alper, I read the link before posting this message. I think this issue is not not related to muti-thread.
@aaron, if you look at the first line in the code posted in the orginal message is var benefitOption = await _benefitOptionRepository.GetAsync(input.Id);
Thanks
In the screenshot... BenefitEnrolmentRule is Null for Ruletype 0 BenefitEnrolmentRule is Not Null for Ruletype 2
In JSON, BenefitEnrolmentRule is Not Null for Ruletype 0 BenefitEnrolmentRule doesn't exist for Ruletype 2
After further investigation, the problem is not related to parsing or serialization. The problem is with JSON.stringify
I wrote it to console log to get the above JSON and it is wrong. console.log("benefit " + JSON.stringify(this.benefitOption))
Hi Guys,
I noticed the DTO object transfered to Angular has different map when it comes to child object.
Here is the issue.. API return dto BenefitOptionDto in quick watch
JSON on Angular.
{
"tenantId":2,
"id":4,
"classBenefitId":9,
"optionCode":"Option2",
"optionDescriptionEn":"Option2 Desc",
"isActive":true,
"benefitOptionPlans":[
{
"tenantId":2,
"id":4,
"benefitOptionId":4,
"ruleType":0,
"fromDate":"1900-01-01T05:00:00.000Z",
"ruleId":null
},
{
"benefitEnrolmentRule":{
"tenantId":2,
"id":2,
"trapLate":true,
"gracePeriod":"01M",
"dependentEnrolmentRules":[
{
"tenantId":2,
"benefitEnrolmentRuleId":2,
"dependent":1,
"waitingPeriod":"01D",
"startDateCalc":1,
"terminationAge":2,
"terminationDateCalc":1,
"terminationMonth":3,
"terminationDay":4,
"isEligible":false
}
],
"employmentRules":[
{
"tenantId":2,
"benefitEnrolmentRuleId":2,
"employmentType":1,
"minHours":3,
"frequency":1
}
],
"trappingRules":[
{
"tenantId":2,
"benefitEnrolmentRuleId":2,
"trappingCondition":2,
"nonEvidenceLimit":4,
"age":5,
"covBeforeDecision":1
}
]
},
"tenantId":2,
"id":5,
"benefitOptionId":4,
"ruleType":2,
"fromDate":"1900-01-01T05:00:00.000Z",
"ruleId":2
}
],
"isDefaultOption":false
}
If you compare both screen shot and JSON, "benefitEnrolmentRule" object should have been in the "ruleType":2 segment of benefitOptionPlans not "ruleType":0,.
This seems to be a big problem is parsing and serializing. Please help!
Thanks