Reputation: 23
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.
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());
}
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.
Upvotes: 2
Views: 882
Reputation: 205539
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.
Upvotes: 1
Reputation: 1
In place of contentName use fileName.contentName
i.e content.UseCaseId = long.Parse(fileName.contentName);
and same applies to fileId
Upvotes: 0