(Упрощенные) объекты выглядят так:
Код: Выделить всё
public class Excavator
{
public int Id { get; set; }
public ExcavatorType Type { get; set; } = new();
public IList Properties { get; set; } = new List();
public IList SpareParts { get; set; } = new List();
}
public class ExcavatorType
{
public int Id { get; set; }
public IList PropertyTypes { get; set; } = new List();
public IList ExcavatorsOfThisType { get; set; } = new List();
}
public class ExcavatorProperty
{
public int Id { get; set; }
public ExcavatorPropertyType PropertyType { get; set; } = null!;
}
public class SparePart
{
public int Id { get; set; }
public IList Excavators { get; set; } = new List();
}
public class ExcavatorPropertyType
{
public int Id { get; set; }
public IList ExcavatorTypesWithThisProperty { get; set; } = new List()!;
}
Я заполнил экскаватор данными из формы и прочитав ответ на этот вопрос, я попробовал следующее:
Код: Выделить всё
var excavatorTypeTmp = await context.ExcavatorTypes
.FirstAsync(et => et.Id == excavator.Type.Id);
excavator.Type = excavatorTypeTmp;
var sparePartsIds = excavator.SpareParts.Select(sp => sp.Id);
excavator.SpareParts = await context.SpareParts
.Where(sp => sparePartsIds.Contains(sp.Id))
.ToListAsync();
context.Add(excavator);
await context.SaveChangesAsync();
Я также пробовал .Attach() и .AttachRange() :
Код: Выделить всё
context.Attach(excavator.Type);
context.AttachRange(excavator.SpareParts);
context.Add(excavator);
await context.SaveChangesAsync();
Затем я даже попробовал (из-за некоторых комментариев в ранее упомянутом вопросе):
Код: Выделить всё
var typeTmp = excavator.Type;
excavator.Type = null!;
context.Attach(typeTmp);
excavator.Type = typeTmp;
var sparePartsTmp = excavator.SpareParts;
excavator.SpareParts = null!;
context.AttachRange(sparePartsTmp);
excavator.SpareParts = sparePartsTmp;
context.Add(excavator);
await context.SaveChangesAsync();
Если я не ошибаюсь, проблема возникает при попытке прикрепить запчасти (
Код: Выделить всё
context.AttachRange(sparePartsTmp);
Еще одна вещь, которую я обнаружил, это то, что когда я не коплю запасные части, проблем нет. Экскаватор, кажется, сохраняется правильно (но, конечно, без запасных частей).
Поэтому я подумал, что, возможно, проблема в том, что я ссылаюсь на одни и те же объекты экскаватора (я пытаюсь присоединить несколько экскаваторов с помощью один и тот же идентификатор) как из excavator.Type, так и из excavator.SpareParts.
И когда я пытался сохранить его таким образом (я избавился от ссылок на excavator из запасных части, присвоив значение null)...:
Код: Выделить всё
context.Attach(excavator.Type);
var excavatorsTmp = new List(excavator.SpareParts.Count);
for (int i = 0; i < excavator.SpareParts.Count; i++)
{
var sparePart = excavator.SpareParts[i];
excavatorsTmp.Add(sparePart.Excavators);
sparePart.Excavators = null!;
}
context.AttachRange(excavator.SpareParts);
context.Add(excavator);
await context.SaveChangesAsync();
Но я считаю, что есть другой (более разумный) способ сохранить экскаватор .
Изменить (подробнее):
Я использую оператор using (using декларацию, если быть точным). Я создаю контекст следующим образом:
Код: Выделить всё
using var context = factory.CreateDbContext();
Код: Выделить всё
var connectionString = GetConnectionString();
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
return new MyDbContext(optionsBuilder.Options);
Подробнее здесь: https://stackoverflow.com/questions/734 ... ng-ef-core