Base solution for your next web application
Open Closed

insert or Update not inserting #3428


User avatar
0
carelearning created

We have two entities defined as:

public class UserImport : AuditedEntity
    {
        public int Position { get; set; } = -1;
        public string Last { get; set; }
        public string First { get; set; }
        public string DepartmentId { get; set; }
        public DateTime? Date { get; set; }
        public string IdBadge { get; set; }
        public string JobCodeId { get; set; }
        public string EmailAddress { get; set; }

        public virtual UserImportPresentation Presentation { get; set; }

        public override string ToString()
        {
            return $"{Last}, {First}";
        }
    }

and

public class UserImportPresentation : Entity
    {
        public int UserImportId { get; set; }
        public string Name { get; set; }
        public string Department { get; set; }
        public string JobCode { get; set; }

        public virtual UserImport UserImport { get; set; }
    }

We save a record like this from our EnrollmentAppService : AbpZeroTemplateAppServiceBase, IApplicationService:

foreach (var import in imports)
            {
                await userImportRepository.InsertAsync(import);
                var presentationUser = BuildUserImportPresentationResult(import, departments, jobCodes);

                await userImportPresentationRepository.InsertAsync(presentationUser);
            }

Note that userImportPresentation has a foreign key to userImport. When we try to save a new record to these tables we get "Validation failed for one or more entities."(image attached)

It appears that the first save has not written yet and is expected for the second save. Is there a way to force the save to importUser before the insert to userImportPresentation?

Thank you for your time and effort.


5 Answer(s)
  • User Avatar
    0
    alirizaadiyahsi created

    Hi,

    You used

    public virtual UserImportPresentation Presentation { get; set; }
    

    for mapping to

    public class UserImportPresentation
    

    EF use name conversation to map entities. So maybe it can't maped entities one-to-one. Could you try to rename Presentationto UserImportPresentation or use fluent API to custom mapping.

    Check this (one-to-one under Other Relationship Patterns title): <a class="postlink" href="https://docs.microsoft.com/en-us/ef/core/modeling/relationships">https://docs.microsoft.com/en-us/ef/cor ... ationships</a>

  • User Avatar
    0
    carelearning created

    Dear alirizaadiyahsi, thank you for the reply.

    Below are the fluent mappings for the two classes.

    UserImportConfiguration

    namespace MyCompanyName.AbpZeroTemplate.Configuration
    {
        using System.Data.Entity.ModelConfiguration;
        using UserImport;
    
        public class UserImportConfiguration : EntityTypeConfiguration<UserImport>
        {
            public UserImportConfiguration()
                : this("dbo")
            {
            }
    
            public UserImportConfiguration(string schema)
            {
                ToTable(schema + ".UserImports");
                HasKey(x => x.Id);
    
                Property(x => x.Id).HasColumnName("Id").IsRequired().HasColumnType("int").HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
                Property(x => x.Position).HasColumnName("Position").IsRequired().HasColumnType("int");
                Property(x => x.Last).HasColumnName("LastName").IsRequired().HasColumnType("nvarchar").HasMaxLength(50);
                Property(x => x.First).HasColumnName("FirstName").IsRequired().HasColumnType("nvarchar").HasMaxLength(50);
                Property(x => x.DepartmentId).HasColumnName("DepartmentId").IsRequired().HasColumnType("nvarchar").HasMaxLength(50);
                Property(x => x.Date).HasColumnName("Date").IsOptional().HasColumnType("datetime");
                Property(x => x.IdBadge).HasColumnName("IdBadge").IsOptional().HasColumnType("nvarchar").HasMaxLength(15);
                Property(x => x.JobCodeId).HasColumnName("JobCodeId").IsOptional().HasColumnType("nvarchar").HasMaxLength(50);
                Property(x => x.EmailAddress).HasColumnName("EmailAddress").IsOptional().HasColumnType("nvarchar").HasMaxLength(254);
            }
        }
    }
    

    UserImportPresentation

    namespace MyCompanyName.AbpZeroTemplate.Configuration
    {
        using System.Data.Entity.ModelConfiguration;
        using UserImport;
    
        public class UserImportPresentationConfiguration : EntityTypeConfiguration<UserImportPresentation>
        {
            public UserImportPresentationConfiguration()
                : this("dbo")
            {
            }
    
            public UserImportPresentationConfiguration(string schema)
            {
                ToTable(schema + ".UserImportPresentations");
    
                HasKey(x => new { x.UserImportId });
    
                Property(x => x.Name).HasColumnName("Name").IsRequired().HasColumnType("nvarchar").HasMaxLength(66);
                Property(x => x.Department).HasColumnName("Department").IsRequired().HasColumnType("nvarchar").HasMaxLength(103);
                Property(x => x.JobCode).HasColumnName("JobCode").IsRequired().HasColumnType("nvarchar").HasMaxLength(103);
    
                Ignore(x => x.Id);
    
                HasRequired(x => x.UserImport);
            }
        }
    }
    

    Attached is the schema for both tables (see included image below).

    I can comment out the UserImportPresentation insert statement and run the application the data will be added.

    foreach (var import in imports)
                {
                    await userImportRepository.InsertAsync(import);
    
                    // var presentationUser = BuildUserImportPresentationResult(import, departments, jobCodes);
                    // await userImportPresentationRepository.InsertAsync(presentationUser);
                }
    

    Next stop the application and fetch the UserImport records and I can then comment out the UserImport insert statement and run the application a second time and the data will be added.

    var import = await userImportRepository.GetAllListAsync();
    foreach (var import in imports)
                {
                    // await userImportRepository.InsertAsync(import);
    
                    var presentationUser = BuildUserImportPresentationResult(import, departments, jobCodes);
                    await userImportPresentationRepository.InsertAsync(presentationUser);
                }
    

    The problem appears to be trying to insert the data on the same run, the second insert fails because the first is not in the table yet.

    Thank you for your time and effort.

  • User Avatar
    0
    alirizaadiyahsi created

    Thanks for detailed explanation.

    Could you check this: <a class="postlink" href="https://aspnetzero.com/Documents/Developing-Step-By-Step-Angular#addphone-and-deletephone-methods">https://aspnetzero.com/Documents/Develo ... ne-methods</a>

    There is a line in document that could help you to solve your problem.

    //Get auto increment Id of the new Phone by saving to database
    await CurrentUnitOfWork.SaveChangesAsync();
    
  • User Avatar
    0
    carelearning created

    Thank you

    await CurrentUnitOfWork.SaveChangesAsync();
    

    flushes the changes to the database and now my queries are working appropriately without errors.

    This issue has been resolved!

  • User Avatar
    0
    alirizaadiyahsi created

    Glad it works...