Entity Framework not saving all the information into database

.net .net-core asp.net-core entity-framework entity-framework-core

Question

I'm facing a problem which one I tried some solutions to solve, but I couldn't. Basically, I have a method which I receive as parameter one string and one serialized Map from ajax post. Everything regarding this is working really well, except the fact when I have for example the same FileId with different UseCaseId, because then just one information is being saved, not both.

**UseCaseId and FileId ** are foreign keys from other tables.

The relationship:

modelBuilder.Entity<Content>()
        .HasIndex(ct => ct.FileId)
        .IsUnique(false);
    modelBuilder.Entity<Content>()
        .HasIndex(ct => ct.UseCaseId)
        .IsUnique(false);

    modelBuilder.Entity<Content>()
        .HasKey(cn => cn.ContentId);
    modelBuilder.Entity<Content>()
        .HasOne(cn => cn.File)
        .WithOne()
        .OnDelete(DeleteBehavior.Cascade);
    modelBuilder.Entity<Content>()
        .HasOne(cn => cn.UseCase)
        .WithOne()
        .OnDelete(DeleteBehavior.Cascade);

In the follow example, two elements, exactly the same with just a different UseCase , need to be saved, but only the last one is saved in the database.

Contents variable

Database - Result

Parameter received:

Parameter Received

This is the code where the problem occurs:

[HttpPost]
public JsonResult Create([FromBody] ContentJson data)
{
    List<Content> contents = new List<Content>();
    var contentName = string.Empty;
    var array = data.content;
    int order;

    for (int i = 0; i < array.Count; i++)
    {
        var files = JsonConvert.DeserializeObject<string[]>(array[i][1].ToString());

        if (files == null || files.Length == 0)
            continue;

        contentName = array[i][0].ToString();
        order = 1;

        foreach(var fileName in files)
        {
            Content content = new Content();    
            content.Order = order;
            content.UseCaseId = long.Parse(contentName);
            content.FileId = unitOfWork.FileRepository.Get(f => f.FileName.Equals(fileName)).First().FileId;
            contents.Add(content);
            order++;
        }
    }

    unitOfWork.ContentRepository.AddRange(contents);
    unitOfWork.Save();

    return Json(Ok());
}
  • The ContentId is automatically generated.
  • EntityFramework and Dotnet in the latest version
  • I've already tried to save on each iteration.
  • Tried to implement Equals and HashCode,

    public void Save()
    {
        context.SaveChanges();
    }
    
    private bool disposed = false;
    
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        disposed = true;
    }
    
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    
    
    
    public Repository<Content> ContentRepository
    {
        get
        {
            if(contentRepository == null)
            {
                contentRepository = new Repository<Content>(context);
            }
            return contentRepository;
        }
    }
    

Could anyone help me, please ? I got stuck on this problem.

1
2
1/21/2020 12:51:27 PM

Accepted Answer

You have conflicting FK configuration.

IsUnique(false) here

modelBuilder.Entity<Content>()
    .HasIndex(ct => ct.FileId)
    .IsUnique(false);

modelBuilder.Entity<Content>()
    .HasIndex(ct => ct.UseCaseId)
    .IsUnique(false);

implies that the FKs are not unique, but then WithOne() here

modelBuilder.Entity<Content>()
    .HasOne(cn => cn.File)
    .WithOne()
    .OnDelete(DeleteBehavior.Cascade);

modelBuilder.Entity<Content>()
    .HasOne(cn => cn.UseCase)
    .WithOne()
    .OnDelete(DeleteBehavior.Cascade);

implies that they are unique (the only difference between one-to-many and one-to-one FK relationships in relational databases is that the later FK is backed with unique constraint/index). And this takes precedence over non unique index mapping and is causing the issue.

Since you want them to be non unique, you have to change the relationships to be one-to-many (or many-to-one depending on which side you are looking at) by replacing in both places WithOne() with WithMany().

Once you do that, you could remove both HasIndex configurations because they will be automatically created for you by EF Core conventions. In fact they would have been created with your fluent configuration as well, but as unique. Probably that's what you were trying to fix with these HasIndex statements, but that's simply the wrong place and instead you should fix the what is causing it.

1
1/21/2020 2:08:38 PM

Popular Answer

In place of contentName use fileName.contentName
i.e content.UseCaseId = long.Parse(fileName.contentName); and same applies to fileId



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow